@copilotkitnext/react 1.54.1-next.6 → 1.54.1

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.
@@ -72,6 +72,8 @@ function useInterrupt(config) {
72
72
  const { copilotkit } = require_CopilotKitProvider.useCopilotKit();
73
73
  const { agent } = require_use_agent.useAgent({ agentId: config.agentId });
74
74
  const [pendingEvent, setPendingEvent] = (0, react.useState)(null);
75
+ const pendingEventRef = (0, react.useRef)(pendingEvent);
76
+ pendingEventRef.current = pendingEvent;
75
77
  const [handlerResult, setHandlerResult] = (0, react.useState)(null);
76
78
  (0, react.useEffect)(() => {
77
79
  let localInterrupt = null;
@@ -102,7 +104,10 @@ function useInterrupt(config) {
102
104
  setPendingEvent(null);
103
105
  copilotkit.runAgent({
104
106
  agent,
105
- forwardedProps: { command: { resume: response } }
107
+ forwardedProps: { command: {
108
+ resume: response,
109
+ interruptEvent: pendingEventRef.current?.value
110
+ } }
106
111
  });
107
112
  }, [agent, copilotkit]);
108
113
  (0, react.useEffect)(() => {
@@ -1 +1 @@
1
- {"version":3,"file":"use-interrupt.cjs","names":["useCopilotKit","useAgent"],"sources":["../../src/hooks/use-interrupt.tsx"],"sourcesContent":["import React, { useState, useEffect, useCallback, useMemo } from \"react\";\nimport { useCopilotKit } from \"@/providers/CopilotKitProvider\";\nimport { useAgent } from \"./use-agent\";\nimport type {\n InterruptEvent,\n InterruptRenderProps,\n InterruptHandlerProps,\n} from \"../types/interrupt\";\n\nexport type { InterruptEvent, InterruptRenderProps, InterruptHandlerProps };\n\nconst INTERRUPT_EVENT_NAME = \"on_interrupt\";\n\ntype InterruptHandlerFn<TValue, TResult> = (\n props: InterruptHandlerProps<TValue>,\n) => TResult | PromiseLike<TResult>;\n\ntype InterruptResultFromHandler<THandler> = THandler extends (\n ...args: never[]\n) => infer TResult\n ? TResult extends PromiseLike<infer TResolved>\n ? TResolved | null\n : TResult | null\n : null;\n\ntype InterruptResult<TValue, TResult> = InterruptResultFromHandler<\n InterruptHandlerFn<TValue, TResult>\n>;\n\ntype InterruptRenderInChat = boolean | undefined;\n\ntype UseInterruptReturn<TRenderInChat extends InterruptRenderInChat> =\n TRenderInChat extends false\n ? React.ReactElement | null\n : TRenderInChat extends true | undefined\n ? void\n : React.ReactElement | null | void;\n\nexport function isPromiseLike<TValue>(\n value: TValue | PromiseLike<TValue>,\n): value is PromiseLike<TValue> {\n return (\n (typeof value === \"object\" || typeof value === \"function\") &&\n value !== null &&\n typeof Reflect.get(value, \"then\") === \"function\"\n );\n}\n\n/**\n * Configuration options for `useInterrupt`.\n */\ninterface UseInterruptConfigBase<TValue = unknown, TResult = never> {\n /**\n * Render function for the interrupt UI.\n *\n * This is called once an interrupt is finalized and accepted by `enabled` (if provided).\n * Use `resolve` from render props to resume the agent run with user input.\n */\n render: (\n props: InterruptRenderProps<TValue, InterruptResult<TValue, TResult>>,\n ) => React.ReactElement;\n /**\n * Optional pre-render handler invoked when an interrupt is received.\n *\n * Return either a sync value or an async value to pass into `render` as `result`.\n * Rejecting/throwing falls back to `result = null`.\n */\n handler?: InterruptHandlerFn<TValue, TResult>;\n /**\n * Optional predicate to filter which interrupts should be handled by this hook.\n * Return `false` to ignore an interrupt.\n */\n enabled?: (event: InterruptEvent<TValue>) => boolean;\n /** Optional agent id. Defaults to the current configured chat agent. */\n agentId?: string;\n}\n\nexport interface UseInterruptInChatConfig<\n TValue = unknown,\n TResult = never,\n> extends UseInterruptConfigBase<TValue, TResult> {\n /** When true (default), the interrupt UI renders inside `<CopilotChat>` automatically. Set to false to render it yourself. */\n renderInChat?: true;\n}\n\nexport interface UseInterruptExternalConfig<\n TValue = unknown,\n TResult = never,\n> extends UseInterruptConfigBase<TValue, TResult> {\n /** When true (default), the interrupt UI renders inside `<CopilotChat>` automatically. Set to false to render it yourself. */\n renderInChat: false;\n}\n\nexport interface UseInterruptDynamicConfig<\n TValue = unknown,\n TResult = never,\n> extends UseInterruptConfigBase<TValue, TResult> {\n /** Dynamic boolean mode. When non-literal, return type is a union. */\n renderInChat: boolean;\n}\n\nexport type UseInterruptConfig<\n TValue = unknown,\n TResult = never,\n TRenderInChat extends InterruptRenderInChat = undefined,\n> = UseInterruptConfigBase<TValue, TResult> & {\n /** When true (default), the interrupt UI renders inside `<CopilotChat>` automatically. Set to false to render it yourself. */\n renderInChat?: TRenderInChat;\n};\n\n/**\n * Handles agent interrupts (`on_interrupt`) with optional filtering, preprocessing, and resume behavior.\n *\n * The hook listens to custom events on the active agent, stores interrupt payloads per run,\n * and surfaces a render callback once the run finalizes. Call `resolve` from your UI to resume\n * execution with user-provided data.\n *\n * - `renderInChat: true` (default): the element is published into `<CopilotChat>` and this hook returns `void`.\n * - `renderInChat: false`: the hook returns the interrupt element so you can place it anywhere in your component tree.\n *\n * `event.value` is typed as `any` since the interrupt payload shape depends on your agent.\n * Type-narrow it in your callbacks (e.g. `handler`, `enabled`, `render`) as needed.\n *\n * @typeParam TResult - Inferred from `handler` return type. Exposed as `result` in `render`.\n * @param config - Interrupt configuration (renderer, optional handler/filter, and render mode).\n * @returns When `renderInChat` is `false`, returns the interrupt element (or `null` when idle).\n * Otherwise returns `void` and publishes the element into chat. In `render`, `result` is always\n * either the handler's resolved return value or `null` (including when no handler is provided,\n * when filtering skips the interrupt, or when handler execution fails).\n *\n * @example\n * ```tsx\n * import { useInterrupt } from \"@copilotkitnext/react\";\n *\n * function InterruptUI() {\n * useInterrupt({\n * render: ({ event, resolve }) => (\n * <div>\n * <p>{event.value.question}</p>\n * <button onClick={() => resolve({ approved: true })}>Approve</button>\n * <button onClick={() => resolve({ approved: false })}>Reject</button>\n * </div>\n * ),\n * });\n *\n * return null;\n * }\n * ```\n *\n * @example\n * ```tsx\n * import { useInterrupt } from \"@copilotkitnext/react\";\n *\n * function CustomPanel() {\n * const interruptElement = useInterrupt({\n * renderInChat: false,\n * enabled: (event) => event.value.startsWith(\"approval:\"),\n * handler: async ({ event }) => ({ label: event.value.toUpperCase() }),\n * render: ({ event, result, resolve }) => (\n * <aside>\n * <strong>{result?.label ?? \"\"}</strong>\n * <button onClick={() => resolve({ value: event.value })}>Continue</button>\n * </aside>\n * ),\n * });\n *\n * return <>{interruptElement}</>;\n * }\n * ```\n */\n/* eslint-disable @typescript-eslint/no-explicit-any */\nexport function useInterrupt<\n TResult = never,\n TRenderInChat extends InterruptRenderInChat = undefined,\n>(\n config: UseInterruptConfig<any, TResult, TRenderInChat>,\n): UseInterruptReturn<TRenderInChat> {\n /* eslint-enable @typescript-eslint/no-explicit-any */\n const { copilotkit } = useCopilotKit();\n const { agent } = useAgent({ agentId: config.agentId });\n const [pendingEvent, setPendingEvent] = useState<InterruptEvent | null>(null);\n const [handlerResult, setHandlerResult] =\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n useState<InterruptResult<any, TResult>>(null);\n\n useEffect(() => {\n let localInterrupt: InterruptEvent | null = null;\n\n const subscription = agent.subscribe({\n onCustomEvent: ({ event }) => {\n if (event.name === INTERRUPT_EVENT_NAME) {\n localInterrupt = { name: event.name, value: event.value };\n }\n },\n onRunStartedEvent: () => {\n localInterrupt = null;\n setPendingEvent(null);\n },\n onRunFinalized: () => {\n if (localInterrupt) {\n setPendingEvent(localInterrupt);\n localInterrupt = null;\n }\n },\n onRunFailed: () => {\n localInterrupt = null;\n },\n });\n\n return () => subscription.unsubscribe();\n }, [agent]);\n\n const resolve = useCallback(\n (response: unknown) => {\n setPendingEvent(null);\n copilotkit.runAgent({\n agent,\n forwardedProps: { command: { resume: response } },\n });\n },\n [agent, copilotkit],\n );\n\n useEffect(() => {\n // No interrupt to process — reset any stale handler result from a previous interrupt\n if (!pendingEvent) {\n setHandlerResult(null);\n return;\n }\n // Interrupt exists but the consumer's filter rejects it — treat as no-op\n if (config.enabled && !config.enabled(pendingEvent)) {\n setHandlerResult(null);\n return;\n }\n const handler = config.handler;\n // No handler provided — skip straight to rendering with a null result\n if (!handler) {\n setHandlerResult(null);\n return;\n }\n\n let cancelled = false;\n const maybePromise = handler({\n event: pendingEvent,\n resolve,\n });\n\n // If the handler returns a promise/thenable, wait for resolution before setting result.\n if (isPromiseLike(maybePromise)) {\n Promise.resolve(maybePromise)\n .then((resolved) => {\n if (!cancelled) setHandlerResult(resolved);\n })\n .catch(() => {\n if (!cancelled) setHandlerResult(null);\n });\n } else {\n setHandlerResult(maybePromise);\n }\n\n return () => {\n cancelled = true;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [pendingEvent, config.enabled, config.handler, resolve]);\n\n const element = useMemo(() => {\n if (!pendingEvent) return null;\n if (config.enabled && !config.enabled(pendingEvent)) return null;\n\n return config.render({\n event: pendingEvent,\n result: handlerResult,\n resolve,\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [pendingEvent, handlerResult, config.enabled, config.render, resolve]);\n\n // Publish to core for in-chat rendering\n useEffect(() => {\n if (config.renderInChat === false) return;\n copilotkit.setInterruptElement(element);\n return () => copilotkit.setInterruptElement(null);\n }, [element, config.renderInChat, copilotkit]);\n\n // Only return element when rendering outside chat\n if (config.renderInChat === false) {\n return element as UseInterruptReturn<TRenderInChat>;\n }\n\n return undefined as UseInterruptReturn<TRenderInChat>;\n}\n"],"mappings":";;;;;;AAWA,MAAM,uBAAuB;AA2B7B,SAAgB,cACd,OAC8B;AAC9B,SACG,OAAO,UAAU,YAAY,OAAO,UAAU,eAC/C,UAAU,QACV,OAAO,QAAQ,IAAI,OAAO,OAAO,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+H1C,SAAgB,aAId,QACmC;CAEnC,MAAM,EAAE,eAAeA,0CAAe;CACtC,MAAM,EAAE,UAAUC,2BAAS,EAAE,SAAS,OAAO,SAAS,CAAC;CACvD,MAAM,CAAC,cAAc,uCAAmD,KAAK;CAC7E,MAAM,CAAC,eAAe,wCAEoB,KAAK;AAE/C,4BAAgB;EACd,IAAI,iBAAwC;EAE5C,MAAM,eAAe,MAAM,UAAU;GACnC,gBAAgB,EAAE,YAAY;AAC5B,QAAI,MAAM,SAAS,qBACjB,kBAAiB;KAAE,MAAM,MAAM;KAAM,OAAO,MAAM;KAAO;;GAG7D,yBAAyB;AACvB,qBAAiB;AACjB,oBAAgB,KAAK;;GAEvB,sBAAsB;AACpB,QAAI,gBAAgB;AAClB,qBAAgB,eAAe;AAC/B,sBAAiB;;;GAGrB,mBAAmB;AACjB,qBAAiB;;GAEpB,CAAC;AAEF,eAAa,aAAa,aAAa;IACtC,CAAC,MAAM,CAAC;CAEX,MAAM,kCACH,aAAsB;AACrB,kBAAgB,KAAK;AACrB,aAAW,SAAS;GAClB;GACA,gBAAgB,EAAE,SAAS,EAAE,QAAQ,UAAU,EAAE;GAClD,CAAC;IAEJ,CAAC,OAAO,WAAW,CACpB;AAED,4BAAgB;AAEd,MAAI,CAAC,cAAc;AACjB,oBAAiB,KAAK;AACtB;;AAGF,MAAI,OAAO,WAAW,CAAC,OAAO,QAAQ,aAAa,EAAE;AACnD,oBAAiB,KAAK;AACtB;;EAEF,MAAM,UAAU,OAAO;AAEvB,MAAI,CAAC,SAAS;AACZ,oBAAiB,KAAK;AACtB;;EAGF,IAAI,YAAY;EAChB,MAAM,eAAe,QAAQ;GAC3B,OAAO;GACP;GACD,CAAC;AAGF,MAAI,cAAc,aAAa,CAC7B,SAAQ,QAAQ,aAAa,CAC1B,MAAM,aAAa;AAClB,OAAI,CAAC,UAAW,kBAAiB,SAAS;IAC1C,CACD,YAAY;AACX,OAAI,CAAC,UAAW,kBAAiB,KAAK;IACtC;MAEJ,kBAAiB,aAAa;AAGhC,eAAa;AACX,eAAY;;IAGb;EAAC;EAAc,OAAO;EAAS,OAAO;EAAS;EAAQ,CAAC;CAE3D,MAAM,mCAAwB;AAC5B,MAAI,CAAC,aAAc,QAAO;AAC1B,MAAI,OAAO,WAAW,CAAC,OAAO,QAAQ,aAAa,CAAE,QAAO;AAE5D,SAAO,OAAO,OAAO;GACnB,OAAO;GACP,QAAQ;GACR;GACD,CAAC;IAED;EAAC;EAAc;EAAe,OAAO;EAAS,OAAO;EAAQ;EAAQ,CAAC;AAGzE,4BAAgB;AACd,MAAI,OAAO,iBAAiB,MAAO;AACnC,aAAW,oBAAoB,QAAQ;AACvC,eAAa,WAAW,oBAAoB,KAAK;IAChD;EAAC;EAAS,OAAO;EAAc;EAAW,CAAC;AAG9C,KAAI,OAAO,iBAAiB,MAC1B,QAAO"}
1
+ {"version":3,"file":"use-interrupt.cjs","names":["useCopilotKit","useAgent"],"sources":["../../src/hooks/use-interrupt.tsx"],"sourcesContent":["import React, {\n useState,\n useEffect,\n useCallback,\n useMemo,\n useRef,\n} from \"react\";\nimport { useCopilotKit } from \"@/providers/CopilotKitProvider\";\nimport { useAgent } from \"./use-agent\";\nimport type {\n InterruptEvent,\n InterruptRenderProps,\n InterruptHandlerProps,\n} from \"../types/interrupt\";\n\nexport type { InterruptEvent, InterruptRenderProps, InterruptHandlerProps };\n\nconst INTERRUPT_EVENT_NAME = \"on_interrupt\";\n\ntype InterruptHandlerFn<TValue, TResult> = (\n props: InterruptHandlerProps<TValue>,\n) => TResult | PromiseLike<TResult>;\n\ntype InterruptResultFromHandler<THandler> = THandler extends (\n ...args: never[]\n) => infer TResult\n ? TResult extends PromiseLike<infer TResolved>\n ? TResolved | null\n : TResult | null\n : null;\n\ntype InterruptResult<TValue, TResult> = InterruptResultFromHandler<\n InterruptHandlerFn<TValue, TResult>\n>;\n\ntype InterruptRenderInChat = boolean | undefined;\n\ntype UseInterruptReturn<TRenderInChat extends InterruptRenderInChat> =\n TRenderInChat extends false\n ? React.ReactElement | null\n : TRenderInChat extends true | undefined\n ? void\n : React.ReactElement | null | void;\n\nexport function isPromiseLike<TValue>(\n value: TValue | PromiseLike<TValue>,\n): value is PromiseLike<TValue> {\n return (\n (typeof value === \"object\" || typeof value === \"function\") &&\n value !== null &&\n typeof Reflect.get(value, \"then\") === \"function\"\n );\n}\n\n/**\n * Configuration options for `useInterrupt`.\n */\ninterface UseInterruptConfigBase<TValue = unknown, TResult = never> {\n /**\n * Render function for the interrupt UI.\n *\n * This is called once an interrupt is finalized and accepted by `enabled` (if provided).\n * Use `resolve` from render props to resume the agent run with user input.\n */\n render: (\n props: InterruptRenderProps<TValue, InterruptResult<TValue, TResult>>,\n ) => React.ReactElement;\n /**\n * Optional pre-render handler invoked when an interrupt is received.\n *\n * Return either a sync value or an async value to pass into `render` as `result`.\n * Rejecting/throwing falls back to `result = null`.\n */\n handler?: InterruptHandlerFn<TValue, TResult>;\n /**\n * Optional predicate to filter which interrupts should be handled by this hook.\n * Return `false` to ignore an interrupt.\n */\n enabled?: (event: InterruptEvent<TValue>) => boolean;\n /** Optional agent id. Defaults to the current configured chat agent. */\n agentId?: string;\n}\n\nexport interface UseInterruptInChatConfig<\n TValue = unknown,\n TResult = never,\n> extends UseInterruptConfigBase<TValue, TResult> {\n /** When true (default), the interrupt UI renders inside `<CopilotChat>` automatically. Set to false to render it yourself. */\n renderInChat?: true;\n}\n\nexport interface UseInterruptExternalConfig<\n TValue = unknown,\n TResult = never,\n> extends UseInterruptConfigBase<TValue, TResult> {\n /** When true (default), the interrupt UI renders inside `<CopilotChat>` automatically. Set to false to render it yourself. */\n renderInChat: false;\n}\n\nexport interface UseInterruptDynamicConfig<\n TValue = unknown,\n TResult = never,\n> extends UseInterruptConfigBase<TValue, TResult> {\n /** Dynamic boolean mode. When non-literal, return type is a union. */\n renderInChat: boolean;\n}\n\nexport type UseInterruptConfig<\n TValue = unknown,\n TResult = never,\n TRenderInChat extends InterruptRenderInChat = undefined,\n> = UseInterruptConfigBase<TValue, TResult> & {\n /** When true (default), the interrupt UI renders inside `<CopilotChat>` automatically. Set to false to render it yourself. */\n renderInChat?: TRenderInChat;\n};\n\n/**\n * Handles agent interrupts (`on_interrupt`) with optional filtering, preprocessing, and resume behavior.\n *\n * The hook listens to custom events on the active agent, stores interrupt payloads per run,\n * and surfaces a render callback once the run finalizes. Call `resolve` from your UI to resume\n * execution with user-provided data.\n *\n * - `renderInChat: true` (default): the element is published into `<CopilotChat>` and this hook returns `void`.\n * - `renderInChat: false`: the hook returns the interrupt element so you can place it anywhere in your component tree.\n *\n * `event.value` is typed as `any` since the interrupt payload shape depends on your agent.\n * Type-narrow it in your callbacks (e.g. `handler`, `enabled`, `render`) as needed.\n *\n * @typeParam TResult - Inferred from `handler` return type. Exposed as `result` in `render`.\n * @param config - Interrupt configuration (renderer, optional handler/filter, and render mode).\n * @returns When `renderInChat` is `false`, returns the interrupt element (or `null` when idle).\n * Otherwise returns `void` and publishes the element into chat. In `render`, `result` is always\n * either the handler's resolved return value or `null` (including when no handler is provided,\n * when filtering skips the interrupt, or when handler execution fails).\n *\n * @example\n * ```tsx\n * import { useInterrupt } from \"@copilotkitnext/react\";\n *\n * function InterruptUI() {\n * useInterrupt({\n * render: ({ event, resolve }) => (\n * <div>\n * <p>{event.value.question}</p>\n * <button onClick={() => resolve({ approved: true })}>Approve</button>\n * <button onClick={() => resolve({ approved: false })}>Reject</button>\n * </div>\n * ),\n * });\n *\n * return null;\n * }\n * ```\n *\n * @example\n * ```tsx\n * import { useInterrupt } from \"@copilotkitnext/react\";\n *\n * function CustomPanel() {\n * const interruptElement = useInterrupt({\n * renderInChat: false,\n * enabled: (event) => event.value.startsWith(\"approval:\"),\n * handler: async ({ event }) => ({ label: event.value.toUpperCase() }),\n * render: ({ event, result, resolve }) => (\n * <aside>\n * <strong>{result?.label ?? \"\"}</strong>\n * <button onClick={() => resolve({ value: event.value })}>Continue</button>\n * </aside>\n * ),\n * });\n *\n * return <>{interruptElement}</>;\n * }\n * ```\n */\n/* eslint-disable @typescript-eslint/no-explicit-any */\nexport function useInterrupt<\n TResult = never,\n TRenderInChat extends InterruptRenderInChat = undefined,\n>(\n config: UseInterruptConfig<any, TResult, TRenderInChat>,\n): UseInterruptReturn<TRenderInChat> {\n /* eslint-enable @typescript-eslint/no-explicit-any */\n const { copilotkit } = useCopilotKit();\n const { agent } = useAgent({ agentId: config.agentId });\n const [pendingEvent, setPendingEvent] = useState<InterruptEvent | null>(null);\n const pendingEventRef = useRef(pendingEvent);\n pendingEventRef.current = pendingEvent;\n const [handlerResult, setHandlerResult] =\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n useState<InterruptResult<any, TResult>>(null);\n\n useEffect(() => {\n let localInterrupt: InterruptEvent | null = null;\n\n const subscription = agent.subscribe({\n onCustomEvent: ({ event }) => {\n if (event.name === INTERRUPT_EVENT_NAME) {\n localInterrupt = { name: event.name, value: event.value };\n }\n },\n onRunStartedEvent: () => {\n localInterrupt = null;\n setPendingEvent(null);\n },\n onRunFinalized: () => {\n if (localInterrupt) {\n setPendingEvent(localInterrupt);\n localInterrupt = null;\n }\n },\n onRunFailed: () => {\n localInterrupt = null;\n },\n });\n\n return () => subscription.unsubscribe();\n }, [agent]);\n\n const resolve = useCallback(\n (response: unknown) => {\n setPendingEvent(null);\n copilotkit.runAgent({\n agent,\n forwardedProps: {\n command: {\n resume: response,\n interruptEvent: pendingEventRef.current?.value,\n },\n },\n });\n },\n [agent, copilotkit],\n );\n\n useEffect(() => {\n // No interrupt to process — reset any stale handler result from a previous interrupt\n if (!pendingEvent) {\n setHandlerResult(null);\n return;\n }\n // Interrupt exists but the consumer's filter rejects it — treat as no-op\n if (config.enabled && !config.enabled(pendingEvent)) {\n setHandlerResult(null);\n return;\n }\n const handler = config.handler;\n // No handler provided — skip straight to rendering with a null result\n if (!handler) {\n setHandlerResult(null);\n return;\n }\n\n let cancelled = false;\n const maybePromise = handler({\n event: pendingEvent,\n resolve,\n });\n\n // If the handler returns a promise/thenable, wait for resolution before setting result.\n if (isPromiseLike(maybePromise)) {\n Promise.resolve(maybePromise)\n .then((resolved) => {\n if (!cancelled) setHandlerResult(resolved);\n })\n .catch(() => {\n if (!cancelled) setHandlerResult(null);\n });\n } else {\n setHandlerResult(maybePromise);\n }\n\n return () => {\n cancelled = true;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [pendingEvent, config.enabled, config.handler, resolve]);\n\n const element = useMemo(() => {\n if (!pendingEvent) return null;\n if (config.enabled && !config.enabled(pendingEvent)) return null;\n\n return config.render({\n event: pendingEvent,\n result: handlerResult,\n resolve,\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [pendingEvent, handlerResult, config.enabled, config.render, resolve]);\n\n // Publish to core for in-chat rendering\n useEffect(() => {\n if (config.renderInChat === false) return;\n copilotkit.setInterruptElement(element);\n return () => copilotkit.setInterruptElement(null);\n }, [element, config.renderInChat, copilotkit]);\n\n // Only return element when rendering outside chat\n if (config.renderInChat === false) {\n return element as UseInterruptReturn<TRenderInChat>;\n }\n\n return undefined as UseInterruptReturn<TRenderInChat>;\n}\n"],"mappings":";;;;;;AAiBA,MAAM,uBAAuB;AA2B7B,SAAgB,cACd,OAC8B;AAC9B,SACG,OAAO,UAAU,YAAY,OAAO,UAAU,eAC/C,UAAU,QACV,OAAO,QAAQ,IAAI,OAAO,OAAO,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+H1C,SAAgB,aAId,QACmC;CAEnC,MAAM,EAAE,eAAeA,0CAAe;CACtC,MAAM,EAAE,UAAUC,2BAAS,EAAE,SAAS,OAAO,SAAS,CAAC;CACvD,MAAM,CAAC,cAAc,uCAAmD,KAAK;CAC7E,MAAM,oCAAyB,aAAa;AAC5C,iBAAgB,UAAU;CAC1B,MAAM,CAAC,eAAe,wCAEoB,KAAK;AAE/C,4BAAgB;EACd,IAAI,iBAAwC;EAE5C,MAAM,eAAe,MAAM,UAAU;GACnC,gBAAgB,EAAE,YAAY;AAC5B,QAAI,MAAM,SAAS,qBACjB,kBAAiB;KAAE,MAAM,MAAM;KAAM,OAAO,MAAM;KAAO;;GAG7D,yBAAyB;AACvB,qBAAiB;AACjB,oBAAgB,KAAK;;GAEvB,sBAAsB;AACpB,QAAI,gBAAgB;AAClB,qBAAgB,eAAe;AAC/B,sBAAiB;;;GAGrB,mBAAmB;AACjB,qBAAiB;;GAEpB,CAAC;AAEF,eAAa,aAAa,aAAa;IACtC,CAAC,MAAM,CAAC;CAEX,MAAM,kCACH,aAAsB;AACrB,kBAAgB,KAAK;AACrB,aAAW,SAAS;GAClB;GACA,gBAAgB,EACd,SAAS;IACP,QAAQ;IACR,gBAAgB,gBAAgB,SAAS;IAC1C,EACF;GACF,CAAC;IAEJ,CAAC,OAAO,WAAW,CACpB;AAED,4BAAgB;AAEd,MAAI,CAAC,cAAc;AACjB,oBAAiB,KAAK;AACtB;;AAGF,MAAI,OAAO,WAAW,CAAC,OAAO,QAAQ,aAAa,EAAE;AACnD,oBAAiB,KAAK;AACtB;;EAEF,MAAM,UAAU,OAAO;AAEvB,MAAI,CAAC,SAAS;AACZ,oBAAiB,KAAK;AACtB;;EAGF,IAAI,YAAY;EAChB,MAAM,eAAe,QAAQ;GAC3B,OAAO;GACP;GACD,CAAC;AAGF,MAAI,cAAc,aAAa,CAC7B,SAAQ,QAAQ,aAAa,CAC1B,MAAM,aAAa;AAClB,OAAI,CAAC,UAAW,kBAAiB,SAAS;IAC1C,CACD,YAAY;AACX,OAAI,CAAC,UAAW,kBAAiB,KAAK;IACtC;MAEJ,kBAAiB,aAAa;AAGhC,eAAa;AACX,eAAY;;IAGb;EAAC;EAAc,OAAO;EAAS,OAAO;EAAS;EAAQ,CAAC;CAE3D,MAAM,mCAAwB;AAC5B,MAAI,CAAC,aAAc,QAAO;AAC1B,MAAI,OAAO,WAAW,CAAC,OAAO,QAAQ,aAAa,CAAE,QAAO;AAE5D,SAAO,OAAO,OAAO;GACnB,OAAO;GACP,QAAQ;GACR;GACD,CAAC;IAED;EAAC;EAAc;EAAe,OAAO;EAAS,OAAO;EAAQ;EAAQ,CAAC;AAGzE,4BAAgB;AACd,MAAI,OAAO,iBAAiB,MAAO;AACnC,aAAW,oBAAoB,QAAQ;AACvC,eAAa,WAAW,oBAAoB,KAAK;IAChD;EAAC;EAAS,OAAO;EAAc;EAAW,CAAC;AAG9C,KAAI,OAAO,iBAAiB,MAC1B,QAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"use-interrupt.d.cts","names":[],"sources":["../../src/hooks/use-interrupt.tsx"],"mappings":";;;;KAaK,kBAAA,qBACH,KAAA,EAAO,qBAAA,CAAsB,MAAA,MAC1B,OAAA,GAAU,WAAA,CAAY,OAAA;AAAA,KAEtB,0BAAA,aAAuC,QAAA,cACvC,IAAA,+BAED,OAAA,SAAgB,WAAA,oBACd,SAAA,UACA,OAAA;AAAA,KAGD,eAAA,oBAAmC,0BAAA,CACtC,kBAAA,CAAmB,MAAA,EAAQ,OAAA;AAAA,KAGxB,qBAAA;AAAA,KAEA,kBAAA,uBAAyC,qBAAA,IAC5C,aAAA,iBACI,KAAA,CAAM,YAAA,UACN,aAAA,mCAEE,KAAA,CAAM,YAAA;;;;UAeJ,sBAAA;EApCgB;;;;;;EA2CxB,MAAA,GACE,KAAA,EAAO,oBAAA,CAAqB,MAAA,EAAQ,eAAA,CAAgB,MAAA,EAAQ,OAAA,OACzD,KAAA,CAAM,YAAA;EA7CE;;;;AAAmB;;EAoDhC,OAAA,GAAU,kBAAA,CAAmB,MAAA,EAAQ,OAAA;EAlDK;;;;EAuD1C,OAAA,IAAW,KAAA,EAAO,cAAA,CAAe,MAAA;EAlDtB;EAoDX,OAAA;AAAA;AAAA,KA2BU,kBAAA,0DAGY,qBAAA,gBACpB,sBAAA,CAAuB,MAAA,EAAQ,OAAA;EA/EN,8HAiF3B,YAAA,GAAe,aAAA;AAAA;;;;;;;;;;;AAjFmB;;;;;AAGV;;;;;;;;;;;;;;;;;;;;AAiBzB;;;;;;;;;;;;;;;;;;;;;;;;;iBA6He,YAAA,wCAEQ,qBAAA,aAAA,CAEtB,MAAA,EAAQ,kBAAA,MAAwB,OAAA,EAAS,aAAA,IACxC,kBAAA,CAAmB,aAAA"}
1
+ {"version":3,"file":"use-interrupt.d.cts","names":[],"sources":["../../src/hooks/use-interrupt.tsx"],"mappings":";;;;KAmBK,kBAAA,qBACH,KAAA,EAAO,qBAAA,CAAsB,MAAA,MAC1B,OAAA,GAAU,WAAA,CAAY,OAAA;AAAA,KAEtB,0BAAA,aAAuC,QAAA,cACvC,IAAA,+BAED,OAAA,SAAgB,WAAA,oBACd,SAAA,UACA,OAAA;AAAA,KAGD,eAAA,oBAAmC,0BAAA,CACtC,kBAAA,CAAmB,MAAA,EAAQ,OAAA;AAAA,KAGxB,qBAAA;AAAA,KAEA,kBAAA,uBAAyC,qBAAA,IAC5C,aAAA,iBACI,KAAA,CAAM,YAAA,UACN,aAAA,mCAEE,KAAA,CAAM,YAAA;;;;UAeJ,sBAAA;EApCgB;;;;;;EA2CxB,MAAA,GACE,KAAA,EAAO,oBAAA,CAAqB,MAAA,EAAQ,eAAA,CAAgB,MAAA,EAAQ,OAAA,OACzD,KAAA,CAAM,YAAA;EA7CE;;;;AAAmB;;EAoDhC,OAAA,GAAU,kBAAA,CAAmB,MAAA,EAAQ,OAAA;EAlDK;;;;EAuD1C,OAAA,IAAW,KAAA,EAAO,cAAA,CAAe,MAAA;EAlDtB;EAoDX,OAAA;AAAA;AAAA,KA2BU,kBAAA,0DAGY,qBAAA,gBACpB,sBAAA,CAAuB,MAAA,EAAQ,OAAA;EA/EN,8HAiF3B,YAAA,GAAe,aAAA;AAAA;;;;;;;;;;;AAjFmB;;;;;AAGV;;;;;;;;;;;;;;;;;;;;AAiBzB;;;;;;;;;;;;;;;;;;;;;;;;;iBA6He,YAAA,wCAEQ,qBAAA,aAAA,CAEtB,MAAA,EAAQ,kBAAA,MAAwB,OAAA,EAAS,aAAA,IACxC,kBAAA,CAAmB,aAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"use-interrupt.d.mts","names":[],"sources":["../../src/hooks/use-interrupt.tsx"],"mappings":";;;;KAaK,kBAAA,qBACH,KAAA,EAAO,qBAAA,CAAsB,MAAA,MAC1B,OAAA,GAAU,WAAA,CAAY,OAAA;AAAA,KAEtB,0BAAA,aAAuC,QAAA,cACvC,IAAA,+BAED,OAAA,SAAgB,WAAA,oBACd,SAAA,UACA,OAAA;AAAA,KAGD,eAAA,oBAAmC,0BAAA,CACtC,kBAAA,CAAmB,MAAA,EAAQ,OAAA;AAAA,KAGxB,qBAAA;AAAA,KAEA,kBAAA,uBAAyC,qBAAA,IAC5C,aAAA,iBACI,KAAA,CAAM,YAAA,UACN,aAAA,mCAEE,KAAA,CAAM,YAAA;;;;UAeJ,sBAAA;EApCgB;;;;;;EA2CxB,MAAA,GACE,KAAA,EAAO,oBAAA,CAAqB,MAAA,EAAQ,eAAA,CAAgB,MAAA,EAAQ,OAAA,OACzD,KAAA,CAAM,YAAA;EA7CE;;;;AAAmB;;EAoDhC,OAAA,GAAU,kBAAA,CAAmB,MAAA,EAAQ,OAAA;EAlDK;;;;EAuD1C,OAAA,IAAW,KAAA,EAAO,cAAA,CAAe,MAAA;EAlDtB;EAoDX,OAAA;AAAA;AAAA,KA2BU,kBAAA,0DAGY,qBAAA,gBACpB,sBAAA,CAAuB,MAAA,EAAQ,OAAA;EA/EN,8HAiF3B,YAAA,GAAe,aAAA;AAAA;;;;;;;;;;;AAjFmB;;;;;AAGV;;;;;;;;;;;;;;;;;;;;AAiBzB;;;;;;;;;;;;;;;;;;;;;;;;;iBA6He,YAAA,wCAEQ,qBAAA,aAAA,CAEtB,MAAA,EAAQ,kBAAA,MAAwB,OAAA,EAAS,aAAA,IACxC,kBAAA,CAAmB,aAAA"}
1
+ {"version":3,"file":"use-interrupt.d.mts","names":[],"sources":["../../src/hooks/use-interrupt.tsx"],"mappings":";;;;KAmBK,kBAAA,qBACH,KAAA,EAAO,qBAAA,CAAsB,MAAA,MAC1B,OAAA,GAAU,WAAA,CAAY,OAAA;AAAA,KAEtB,0BAAA,aAAuC,QAAA,cACvC,IAAA,+BAED,OAAA,SAAgB,WAAA,oBACd,SAAA,UACA,OAAA;AAAA,KAGD,eAAA,oBAAmC,0BAAA,CACtC,kBAAA,CAAmB,MAAA,EAAQ,OAAA;AAAA,KAGxB,qBAAA;AAAA,KAEA,kBAAA,uBAAyC,qBAAA,IAC5C,aAAA,iBACI,KAAA,CAAM,YAAA,UACN,aAAA,mCAEE,KAAA,CAAM,YAAA;;;;UAeJ,sBAAA;EApCgB;;;;;;EA2CxB,MAAA,GACE,KAAA,EAAO,oBAAA,CAAqB,MAAA,EAAQ,eAAA,CAAgB,MAAA,EAAQ,OAAA,OACzD,KAAA,CAAM,YAAA;EA7CE;;;;AAAmB;;EAoDhC,OAAA,GAAU,kBAAA,CAAmB,MAAA,EAAQ,OAAA;EAlDK;;;;EAuD1C,OAAA,IAAW,KAAA,EAAO,cAAA,CAAe,MAAA;EAlDtB;EAoDX,OAAA;AAAA;AAAA,KA2BU,kBAAA,0DAGY,qBAAA,gBACpB,sBAAA,CAAuB,MAAA,EAAQ,OAAA;EA/EN,8HAiF3B,YAAA,GAAe,aAAA;AAAA;;;;;;;;;;;AAjFmB;;;;;AAGV;;;;;;;;;;;;;;;;;;;;AAiBzB;;;;;;;;;;;;;;;;;;;;;;;;;iBA6He,YAAA,wCAEQ,qBAAA,aAAA,CAEtB,MAAA,EAAQ,kBAAA,MAAwB,OAAA,EAAS,aAAA,IACxC,kBAAA,CAAmB,aAAA"}
@@ -1,6 +1,6 @@
1
1
  import { useCopilotKit } from "../providers/CopilotKitProvider.mjs";
2
2
  import { useAgent } from "./use-agent.mjs";
3
- import { useCallback, useEffect, useMemo, useState } from "react";
3
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
4
4
 
5
5
  //#region src/hooks/use-interrupt.tsx
6
6
  const INTERRUPT_EVENT_NAME = "on_interrupt";
@@ -71,6 +71,8 @@ function useInterrupt(config) {
71
71
  const { copilotkit } = useCopilotKit();
72
72
  const { agent } = useAgent({ agentId: config.agentId });
73
73
  const [pendingEvent, setPendingEvent] = useState(null);
74
+ const pendingEventRef = useRef(pendingEvent);
75
+ pendingEventRef.current = pendingEvent;
74
76
  const [handlerResult, setHandlerResult] = useState(null);
75
77
  useEffect(() => {
76
78
  let localInterrupt = null;
@@ -101,7 +103,10 @@ function useInterrupt(config) {
101
103
  setPendingEvent(null);
102
104
  copilotkit.runAgent({
103
105
  agent,
104
- forwardedProps: { command: { resume: response } }
106
+ forwardedProps: { command: {
107
+ resume: response,
108
+ interruptEvent: pendingEventRef.current?.value
109
+ } }
105
110
  });
106
111
  }, [agent, copilotkit]);
107
112
  useEffect(() => {
@@ -1 +1 @@
1
- {"version":3,"file":"use-interrupt.mjs","names":[],"sources":["../../src/hooks/use-interrupt.tsx"],"sourcesContent":["import React, { useState, useEffect, useCallback, useMemo } from \"react\";\nimport { useCopilotKit } from \"@/providers/CopilotKitProvider\";\nimport { useAgent } from \"./use-agent\";\nimport type {\n InterruptEvent,\n InterruptRenderProps,\n InterruptHandlerProps,\n} from \"../types/interrupt\";\n\nexport type { InterruptEvent, InterruptRenderProps, InterruptHandlerProps };\n\nconst INTERRUPT_EVENT_NAME = \"on_interrupt\";\n\ntype InterruptHandlerFn<TValue, TResult> = (\n props: InterruptHandlerProps<TValue>,\n) => TResult | PromiseLike<TResult>;\n\ntype InterruptResultFromHandler<THandler> = THandler extends (\n ...args: never[]\n) => infer TResult\n ? TResult extends PromiseLike<infer TResolved>\n ? TResolved | null\n : TResult | null\n : null;\n\ntype InterruptResult<TValue, TResult> = InterruptResultFromHandler<\n InterruptHandlerFn<TValue, TResult>\n>;\n\ntype InterruptRenderInChat = boolean | undefined;\n\ntype UseInterruptReturn<TRenderInChat extends InterruptRenderInChat> =\n TRenderInChat extends false\n ? React.ReactElement | null\n : TRenderInChat extends true | undefined\n ? void\n : React.ReactElement | null | void;\n\nexport function isPromiseLike<TValue>(\n value: TValue | PromiseLike<TValue>,\n): value is PromiseLike<TValue> {\n return (\n (typeof value === \"object\" || typeof value === \"function\") &&\n value !== null &&\n typeof Reflect.get(value, \"then\") === \"function\"\n );\n}\n\n/**\n * Configuration options for `useInterrupt`.\n */\ninterface UseInterruptConfigBase<TValue = unknown, TResult = never> {\n /**\n * Render function for the interrupt UI.\n *\n * This is called once an interrupt is finalized and accepted by `enabled` (if provided).\n * Use `resolve` from render props to resume the agent run with user input.\n */\n render: (\n props: InterruptRenderProps<TValue, InterruptResult<TValue, TResult>>,\n ) => React.ReactElement;\n /**\n * Optional pre-render handler invoked when an interrupt is received.\n *\n * Return either a sync value or an async value to pass into `render` as `result`.\n * Rejecting/throwing falls back to `result = null`.\n */\n handler?: InterruptHandlerFn<TValue, TResult>;\n /**\n * Optional predicate to filter which interrupts should be handled by this hook.\n * Return `false` to ignore an interrupt.\n */\n enabled?: (event: InterruptEvent<TValue>) => boolean;\n /** Optional agent id. Defaults to the current configured chat agent. */\n agentId?: string;\n}\n\nexport interface UseInterruptInChatConfig<\n TValue = unknown,\n TResult = never,\n> extends UseInterruptConfigBase<TValue, TResult> {\n /** When true (default), the interrupt UI renders inside `<CopilotChat>` automatically. Set to false to render it yourself. */\n renderInChat?: true;\n}\n\nexport interface UseInterruptExternalConfig<\n TValue = unknown,\n TResult = never,\n> extends UseInterruptConfigBase<TValue, TResult> {\n /** When true (default), the interrupt UI renders inside `<CopilotChat>` automatically. Set to false to render it yourself. */\n renderInChat: false;\n}\n\nexport interface UseInterruptDynamicConfig<\n TValue = unknown,\n TResult = never,\n> extends UseInterruptConfigBase<TValue, TResult> {\n /** Dynamic boolean mode. When non-literal, return type is a union. */\n renderInChat: boolean;\n}\n\nexport type UseInterruptConfig<\n TValue = unknown,\n TResult = never,\n TRenderInChat extends InterruptRenderInChat = undefined,\n> = UseInterruptConfigBase<TValue, TResult> & {\n /** When true (default), the interrupt UI renders inside `<CopilotChat>` automatically. Set to false to render it yourself. */\n renderInChat?: TRenderInChat;\n};\n\n/**\n * Handles agent interrupts (`on_interrupt`) with optional filtering, preprocessing, and resume behavior.\n *\n * The hook listens to custom events on the active agent, stores interrupt payloads per run,\n * and surfaces a render callback once the run finalizes. Call `resolve` from your UI to resume\n * execution with user-provided data.\n *\n * - `renderInChat: true` (default): the element is published into `<CopilotChat>` and this hook returns `void`.\n * - `renderInChat: false`: the hook returns the interrupt element so you can place it anywhere in your component tree.\n *\n * `event.value` is typed as `any` since the interrupt payload shape depends on your agent.\n * Type-narrow it in your callbacks (e.g. `handler`, `enabled`, `render`) as needed.\n *\n * @typeParam TResult - Inferred from `handler` return type. Exposed as `result` in `render`.\n * @param config - Interrupt configuration (renderer, optional handler/filter, and render mode).\n * @returns When `renderInChat` is `false`, returns the interrupt element (or `null` when idle).\n * Otherwise returns `void` and publishes the element into chat. In `render`, `result` is always\n * either the handler's resolved return value or `null` (including when no handler is provided,\n * when filtering skips the interrupt, or when handler execution fails).\n *\n * @example\n * ```tsx\n * import { useInterrupt } from \"@copilotkitnext/react\";\n *\n * function InterruptUI() {\n * useInterrupt({\n * render: ({ event, resolve }) => (\n * <div>\n * <p>{event.value.question}</p>\n * <button onClick={() => resolve({ approved: true })}>Approve</button>\n * <button onClick={() => resolve({ approved: false })}>Reject</button>\n * </div>\n * ),\n * });\n *\n * return null;\n * }\n * ```\n *\n * @example\n * ```tsx\n * import { useInterrupt } from \"@copilotkitnext/react\";\n *\n * function CustomPanel() {\n * const interruptElement = useInterrupt({\n * renderInChat: false,\n * enabled: (event) => event.value.startsWith(\"approval:\"),\n * handler: async ({ event }) => ({ label: event.value.toUpperCase() }),\n * render: ({ event, result, resolve }) => (\n * <aside>\n * <strong>{result?.label ?? \"\"}</strong>\n * <button onClick={() => resolve({ value: event.value })}>Continue</button>\n * </aside>\n * ),\n * });\n *\n * return <>{interruptElement}</>;\n * }\n * ```\n */\n/* eslint-disable @typescript-eslint/no-explicit-any */\nexport function useInterrupt<\n TResult = never,\n TRenderInChat extends InterruptRenderInChat = undefined,\n>(\n config: UseInterruptConfig<any, TResult, TRenderInChat>,\n): UseInterruptReturn<TRenderInChat> {\n /* eslint-enable @typescript-eslint/no-explicit-any */\n const { copilotkit } = useCopilotKit();\n const { agent } = useAgent({ agentId: config.agentId });\n const [pendingEvent, setPendingEvent] = useState<InterruptEvent | null>(null);\n const [handlerResult, setHandlerResult] =\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n useState<InterruptResult<any, TResult>>(null);\n\n useEffect(() => {\n let localInterrupt: InterruptEvent | null = null;\n\n const subscription = agent.subscribe({\n onCustomEvent: ({ event }) => {\n if (event.name === INTERRUPT_EVENT_NAME) {\n localInterrupt = { name: event.name, value: event.value };\n }\n },\n onRunStartedEvent: () => {\n localInterrupt = null;\n setPendingEvent(null);\n },\n onRunFinalized: () => {\n if (localInterrupt) {\n setPendingEvent(localInterrupt);\n localInterrupt = null;\n }\n },\n onRunFailed: () => {\n localInterrupt = null;\n },\n });\n\n return () => subscription.unsubscribe();\n }, [agent]);\n\n const resolve = useCallback(\n (response: unknown) => {\n setPendingEvent(null);\n copilotkit.runAgent({\n agent,\n forwardedProps: { command: { resume: response } },\n });\n },\n [agent, copilotkit],\n );\n\n useEffect(() => {\n // No interrupt to process — reset any stale handler result from a previous interrupt\n if (!pendingEvent) {\n setHandlerResult(null);\n return;\n }\n // Interrupt exists but the consumer's filter rejects it — treat as no-op\n if (config.enabled && !config.enabled(pendingEvent)) {\n setHandlerResult(null);\n return;\n }\n const handler = config.handler;\n // No handler provided — skip straight to rendering with a null result\n if (!handler) {\n setHandlerResult(null);\n return;\n }\n\n let cancelled = false;\n const maybePromise = handler({\n event: pendingEvent,\n resolve,\n });\n\n // If the handler returns a promise/thenable, wait for resolution before setting result.\n if (isPromiseLike(maybePromise)) {\n Promise.resolve(maybePromise)\n .then((resolved) => {\n if (!cancelled) setHandlerResult(resolved);\n })\n .catch(() => {\n if (!cancelled) setHandlerResult(null);\n });\n } else {\n setHandlerResult(maybePromise);\n }\n\n return () => {\n cancelled = true;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [pendingEvent, config.enabled, config.handler, resolve]);\n\n const element = useMemo(() => {\n if (!pendingEvent) return null;\n if (config.enabled && !config.enabled(pendingEvent)) return null;\n\n return config.render({\n event: pendingEvent,\n result: handlerResult,\n resolve,\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [pendingEvent, handlerResult, config.enabled, config.render, resolve]);\n\n // Publish to core for in-chat rendering\n useEffect(() => {\n if (config.renderInChat === false) return;\n copilotkit.setInterruptElement(element);\n return () => copilotkit.setInterruptElement(null);\n }, [element, config.renderInChat, copilotkit]);\n\n // Only return element when rendering outside chat\n if (config.renderInChat === false) {\n return element as UseInterruptReturn<TRenderInChat>;\n }\n\n return undefined as UseInterruptReturn<TRenderInChat>;\n}\n"],"mappings":";;;;;AAWA,MAAM,uBAAuB;AA2B7B,SAAgB,cACd,OAC8B;AAC9B,SACG,OAAO,UAAU,YAAY,OAAO,UAAU,eAC/C,UAAU,QACV,OAAO,QAAQ,IAAI,OAAO,OAAO,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+H1C,SAAgB,aAId,QACmC;CAEnC,MAAM,EAAE,eAAe,eAAe;CACtC,MAAM,EAAE,UAAU,SAAS,EAAE,SAAS,OAAO,SAAS,CAAC;CACvD,MAAM,CAAC,cAAc,mBAAmB,SAAgC,KAAK;CAC7E,MAAM,CAAC,eAAe,oBAEpB,SAAwC,KAAK;AAE/C,iBAAgB;EACd,IAAI,iBAAwC;EAE5C,MAAM,eAAe,MAAM,UAAU;GACnC,gBAAgB,EAAE,YAAY;AAC5B,QAAI,MAAM,SAAS,qBACjB,kBAAiB;KAAE,MAAM,MAAM;KAAM,OAAO,MAAM;KAAO;;GAG7D,yBAAyB;AACvB,qBAAiB;AACjB,oBAAgB,KAAK;;GAEvB,sBAAsB;AACpB,QAAI,gBAAgB;AAClB,qBAAgB,eAAe;AAC/B,sBAAiB;;;GAGrB,mBAAmB;AACjB,qBAAiB;;GAEpB,CAAC;AAEF,eAAa,aAAa,aAAa;IACtC,CAAC,MAAM,CAAC;CAEX,MAAM,UAAU,aACb,aAAsB;AACrB,kBAAgB,KAAK;AACrB,aAAW,SAAS;GAClB;GACA,gBAAgB,EAAE,SAAS,EAAE,QAAQ,UAAU,EAAE;GAClD,CAAC;IAEJ,CAAC,OAAO,WAAW,CACpB;AAED,iBAAgB;AAEd,MAAI,CAAC,cAAc;AACjB,oBAAiB,KAAK;AACtB;;AAGF,MAAI,OAAO,WAAW,CAAC,OAAO,QAAQ,aAAa,EAAE;AACnD,oBAAiB,KAAK;AACtB;;EAEF,MAAM,UAAU,OAAO;AAEvB,MAAI,CAAC,SAAS;AACZ,oBAAiB,KAAK;AACtB;;EAGF,IAAI,YAAY;EAChB,MAAM,eAAe,QAAQ;GAC3B,OAAO;GACP;GACD,CAAC;AAGF,MAAI,cAAc,aAAa,CAC7B,SAAQ,QAAQ,aAAa,CAC1B,MAAM,aAAa;AAClB,OAAI,CAAC,UAAW,kBAAiB,SAAS;IAC1C,CACD,YAAY;AACX,OAAI,CAAC,UAAW,kBAAiB,KAAK;IACtC;MAEJ,kBAAiB,aAAa;AAGhC,eAAa;AACX,eAAY;;IAGb;EAAC;EAAc,OAAO;EAAS,OAAO;EAAS;EAAQ,CAAC;CAE3D,MAAM,UAAU,cAAc;AAC5B,MAAI,CAAC,aAAc,QAAO;AAC1B,MAAI,OAAO,WAAW,CAAC,OAAO,QAAQ,aAAa,CAAE,QAAO;AAE5D,SAAO,OAAO,OAAO;GACnB,OAAO;GACP,QAAQ;GACR;GACD,CAAC;IAED;EAAC;EAAc;EAAe,OAAO;EAAS,OAAO;EAAQ;EAAQ,CAAC;AAGzE,iBAAgB;AACd,MAAI,OAAO,iBAAiB,MAAO;AACnC,aAAW,oBAAoB,QAAQ;AACvC,eAAa,WAAW,oBAAoB,KAAK;IAChD;EAAC;EAAS,OAAO;EAAc;EAAW,CAAC;AAG9C,KAAI,OAAO,iBAAiB,MAC1B,QAAO"}
1
+ {"version":3,"file":"use-interrupt.mjs","names":[],"sources":["../../src/hooks/use-interrupt.tsx"],"sourcesContent":["import React, {\n useState,\n useEffect,\n useCallback,\n useMemo,\n useRef,\n} from \"react\";\nimport { useCopilotKit } from \"@/providers/CopilotKitProvider\";\nimport { useAgent } from \"./use-agent\";\nimport type {\n InterruptEvent,\n InterruptRenderProps,\n InterruptHandlerProps,\n} from \"../types/interrupt\";\n\nexport type { InterruptEvent, InterruptRenderProps, InterruptHandlerProps };\n\nconst INTERRUPT_EVENT_NAME = \"on_interrupt\";\n\ntype InterruptHandlerFn<TValue, TResult> = (\n props: InterruptHandlerProps<TValue>,\n) => TResult | PromiseLike<TResult>;\n\ntype InterruptResultFromHandler<THandler> = THandler extends (\n ...args: never[]\n) => infer TResult\n ? TResult extends PromiseLike<infer TResolved>\n ? TResolved | null\n : TResult | null\n : null;\n\ntype InterruptResult<TValue, TResult> = InterruptResultFromHandler<\n InterruptHandlerFn<TValue, TResult>\n>;\n\ntype InterruptRenderInChat = boolean | undefined;\n\ntype UseInterruptReturn<TRenderInChat extends InterruptRenderInChat> =\n TRenderInChat extends false\n ? React.ReactElement | null\n : TRenderInChat extends true | undefined\n ? void\n : React.ReactElement | null | void;\n\nexport function isPromiseLike<TValue>(\n value: TValue | PromiseLike<TValue>,\n): value is PromiseLike<TValue> {\n return (\n (typeof value === \"object\" || typeof value === \"function\") &&\n value !== null &&\n typeof Reflect.get(value, \"then\") === \"function\"\n );\n}\n\n/**\n * Configuration options for `useInterrupt`.\n */\ninterface UseInterruptConfigBase<TValue = unknown, TResult = never> {\n /**\n * Render function for the interrupt UI.\n *\n * This is called once an interrupt is finalized and accepted by `enabled` (if provided).\n * Use `resolve` from render props to resume the agent run with user input.\n */\n render: (\n props: InterruptRenderProps<TValue, InterruptResult<TValue, TResult>>,\n ) => React.ReactElement;\n /**\n * Optional pre-render handler invoked when an interrupt is received.\n *\n * Return either a sync value or an async value to pass into `render` as `result`.\n * Rejecting/throwing falls back to `result = null`.\n */\n handler?: InterruptHandlerFn<TValue, TResult>;\n /**\n * Optional predicate to filter which interrupts should be handled by this hook.\n * Return `false` to ignore an interrupt.\n */\n enabled?: (event: InterruptEvent<TValue>) => boolean;\n /** Optional agent id. Defaults to the current configured chat agent. */\n agentId?: string;\n}\n\nexport interface UseInterruptInChatConfig<\n TValue = unknown,\n TResult = never,\n> extends UseInterruptConfigBase<TValue, TResult> {\n /** When true (default), the interrupt UI renders inside `<CopilotChat>` automatically. Set to false to render it yourself. */\n renderInChat?: true;\n}\n\nexport interface UseInterruptExternalConfig<\n TValue = unknown,\n TResult = never,\n> extends UseInterruptConfigBase<TValue, TResult> {\n /** When true (default), the interrupt UI renders inside `<CopilotChat>` automatically. Set to false to render it yourself. */\n renderInChat: false;\n}\n\nexport interface UseInterruptDynamicConfig<\n TValue = unknown,\n TResult = never,\n> extends UseInterruptConfigBase<TValue, TResult> {\n /** Dynamic boolean mode. When non-literal, return type is a union. */\n renderInChat: boolean;\n}\n\nexport type UseInterruptConfig<\n TValue = unknown,\n TResult = never,\n TRenderInChat extends InterruptRenderInChat = undefined,\n> = UseInterruptConfigBase<TValue, TResult> & {\n /** When true (default), the interrupt UI renders inside `<CopilotChat>` automatically. Set to false to render it yourself. */\n renderInChat?: TRenderInChat;\n};\n\n/**\n * Handles agent interrupts (`on_interrupt`) with optional filtering, preprocessing, and resume behavior.\n *\n * The hook listens to custom events on the active agent, stores interrupt payloads per run,\n * and surfaces a render callback once the run finalizes. Call `resolve` from your UI to resume\n * execution with user-provided data.\n *\n * - `renderInChat: true` (default): the element is published into `<CopilotChat>` and this hook returns `void`.\n * - `renderInChat: false`: the hook returns the interrupt element so you can place it anywhere in your component tree.\n *\n * `event.value` is typed as `any` since the interrupt payload shape depends on your agent.\n * Type-narrow it in your callbacks (e.g. `handler`, `enabled`, `render`) as needed.\n *\n * @typeParam TResult - Inferred from `handler` return type. Exposed as `result` in `render`.\n * @param config - Interrupt configuration (renderer, optional handler/filter, and render mode).\n * @returns When `renderInChat` is `false`, returns the interrupt element (or `null` when idle).\n * Otherwise returns `void` and publishes the element into chat. In `render`, `result` is always\n * either the handler's resolved return value or `null` (including when no handler is provided,\n * when filtering skips the interrupt, or when handler execution fails).\n *\n * @example\n * ```tsx\n * import { useInterrupt } from \"@copilotkitnext/react\";\n *\n * function InterruptUI() {\n * useInterrupt({\n * render: ({ event, resolve }) => (\n * <div>\n * <p>{event.value.question}</p>\n * <button onClick={() => resolve({ approved: true })}>Approve</button>\n * <button onClick={() => resolve({ approved: false })}>Reject</button>\n * </div>\n * ),\n * });\n *\n * return null;\n * }\n * ```\n *\n * @example\n * ```tsx\n * import { useInterrupt } from \"@copilotkitnext/react\";\n *\n * function CustomPanel() {\n * const interruptElement = useInterrupt({\n * renderInChat: false,\n * enabled: (event) => event.value.startsWith(\"approval:\"),\n * handler: async ({ event }) => ({ label: event.value.toUpperCase() }),\n * render: ({ event, result, resolve }) => (\n * <aside>\n * <strong>{result?.label ?? \"\"}</strong>\n * <button onClick={() => resolve({ value: event.value })}>Continue</button>\n * </aside>\n * ),\n * });\n *\n * return <>{interruptElement}</>;\n * }\n * ```\n */\n/* eslint-disable @typescript-eslint/no-explicit-any */\nexport function useInterrupt<\n TResult = never,\n TRenderInChat extends InterruptRenderInChat = undefined,\n>(\n config: UseInterruptConfig<any, TResult, TRenderInChat>,\n): UseInterruptReturn<TRenderInChat> {\n /* eslint-enable @typescript-eslint/no-explicit-any */\n const { copilotkit } = useCopilotKit();\n const { agent } = useAgent({ agentId: config.agentId });\n const [pendingEvent, setPendingEvent] = useState<InterruptEvent | null>(null);\n const pendingEventRef = useRef(pendingEvent);\n pendingEventRef.current = pendingEvent;\n const [handlerResult, setHandlerResult] =\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n useState<InterruptResult<any, TResult>>(null);\n\n useEffect(() => {\n let localInterrupt: InterruptEvent | null = null;\n\n const subscription = agent.subscribe({\n onCustomEvent: ({ event }) => {\n if (event.name === INTERRUPT_EVENT_NAME) {\n localInterrupt = { name: event.name, value: event.value };\n }\n },\n onRunStartedEvent: () => {\n localInterrupt = null;\n setPendingEvent(null);\n },\n onRunFinalized: () => {\n if (localInterrupt) {\n setPendingEvent(localInterrupt);\n localInterrupt = null;\n }\n },\n onRunFailed: () => {\n localInterrupt = null;\n },\n });\n\n return () => subscription.unsubscribe();\n }, [agent]);\n\n const resolve = useCallback(\n (response: unknown) => {\n setPendingEvent(null);\n copilotkit.runAgent({\n agent,\n forwardedProps: {\n command: {\n resume: response,\n interruptEvent: pendingEventRef.current?.value,\n },\n },\n });\n },\n [agent, copilotkit],\n );\n\n useEffect(() => {\n // No interrupt to process — reset any stale handler result from a previous interrupt\n if (!pendingEvent) {\n setHandlerResult(null);\n return;\n }\n // Interrupt exists but the consumer's filter rejects it — treat as no-op\n if (config.enabled && !config.enabled(pendingEvent)) {\n setHandlerResult(null);\n return;\n }\n const handler = config.handler;\n // No handler provided — skip straight to rendering with a null result\n if (!handler) {\n setHandlerResult(null);\n return;\n }\n\n let cancelled = false;\n const maybePromise = handler({\n event: pendingEvent,\n resolve,\n });\n\n // If the handler returns a promise/thenable, wait for resolution before setting result.\n if (isPromiseLike(maybePromise)) {\n Promise.resolve(maybePromise)\n .then((resolved) => {\n if (!cancelled) setHandlerResult(resolved);\n })\n .catch(() => {\n if (!cancelled) setHandlerResult(null);\n });\n } else {\n setHandlerResult(maybePromise);\n }\n\n return () => {\n cancelled = true;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [pendingEvent, config.enabled, config.handler, resolve]);\n\n const element = useMemo(() => {\n if (!pendingEvent) return null;\n if (config.enabled && !config.enabled(pendingEvent)) return null;\n\n return config.render({\n event: pendingEvent,\n result: handlerResult,\n resolve,\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [pendingEvent, handlerResult, config.enabled, config.render, resolve]);\n\n // Publish to core for in-chat rendering\n useEffect(() => {\n if (config.renderInChat === false) return;\n copilotkit.setInterruptElement(element);\n return () => copilotkit.setInterruptElement(null);\n }, [element, config.renderInChat, copilotkit]);\n\n // Only return element when rendering outside chat\n if (config.renderInChat === false) {\n return element as UseInterruptReturn<TRenderInChat>;\n }\n\n return undefined as UseInterruptReturn<TRenderInChat>;\n}\n"],"mappings":";;;;;AAiBA,MAAM,uBAAuB;AA2B7B,SAAgB,cACd,OAC8B;AAC9B,SACG,OAAO,UAAU,YAAY,OAAO,UAAU,eAC/C,UAAU,QACV,OAAO,QAAQ,IAAI,OAAO,OAAO,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+H1C,SAAgB,aAId,QACmC;CAEnC,MAAM,EAAE,eAAe,eAAe;CACtC,MAAM,EAAE,UAAU,SAAS,EAAE,SAAS,OAAO,SAAS,CAAC;CACvD,MAAM,CAAC,cAAc,mBAAmB,SAAgC,KAAK;CAC7E,MAAM,kBAAkB,OAAO,aAAa;AAC5C,iBAAgB,UAAU;CAC1B,MAAM,CAAC,eAAe,oBAEpB,SAAwC,KAAK;AAE/C,iBAAgB;EACd,IAAI,iBAAwC;EAE5C,MAAM,eAAe,MAAM,UAAU;GACnC,gBAAgB,EAAE,YAAY;AAC5B,QAAI,MAAM,SAAS,qBACjB,kBAAiB;KAAE,MAAM,MAAM;KAAM,OAAO,MAAM;KAAO;;GAG7D,yBAAyB;AACvB,qBAAiB;AACjB,oBAAgB,KAAK;;GAEvB,sBAAsB;AACpB,QAAI,gBAAgB;AAClB,qBAAgB,eAAe;AAC/B,sBAAiB;;;GAGrB,mBAAmB;AACjB,qBAAiB;;GAEpB,CAAC;AAEF,eAAa,aAAa,aAAa;IACtC,CAAC,MAAM,CAAC;CAEX,MAAM,UAAU,aACb,aAAsB;AACrB,kBAAgB,KAAK;AACrB,aAAW,SAAS;GAClB;GACA,gBAAgB,EACd,SAAS;IACP,QAAQ;IACR,gBAAgB,gBAAgB,SAAS;IAC1C,EACF;GACF,CAAC;IAEJ,CAAC,OAAO,WAAW,CACpB;AAED,iBAAgB;AAEd,MAAI,CAAC,cAAc;AACjB,oBAAiB,KAAK;AACtB;;AAGF,MAAI,OAAO,WAAW,CAAC,OAAO,QAAQ,aAAa,EAAE;AACnD,oBAAiB,KAAK;AACtB;;EAEF,MAAM,UAAU,OAAO;AAEvB,MAAI,CAAC,SAAS;AACZ,oBAAiB,KAAK;AACtB;;EAGF,IAAI,YAAY;EAChB,MAAM,eAAe,QAAQ;GAC3B,OAAO;GACP;GACD,CAAC;AAGF,MAAI,cAAc,aAAa,CAC7B,SAAQ,QAAQ,aAAa,CAC1B,MAAM,aAAa;AAClB,OAAI,CAAC,UAAW,kBAAiB,SAAS;IAC1C,CACD,YAAY;AACX,OAAI,CAAC,UAAW,kBAAiB,KAAK;IACtC;MAEJ,kBAAiB,aAAa;AAGhC,eAAa;AACX,eAAY;;IAGb;EAAC;EAAc,OAAO;EAAS,OAAO;EAAS;EAAQ,CAAC;CAE3D,MAAM,UAAU,cAAc;AAC5B,MAAI,CAAC,aAAc,QAAO;AAC1B,MAAI,OAAO,WAAW,CAAC,OAAO,QAAQ,aAAa,CAAE,QAAO;AAE5D,SAAO,OAAO,OAAO;GACnB,OAAO;GACP,QAAQ;GACR;GACD,CAAC;IAED;EAAC;EAAc;EAAe,OAAO;EAAS,OAAO;EAAQ;EAAQ,CAAC;AAGzE,iBAAgB;AACd,MAAI,OAAO,iBAAiB,MAAO;AACnC,aAAW,oBAAoB,QAAQ;AACvC,eAAa,WAAW,oBAAoB,KAAK;IAChD;EAAC;EAAS,OAAO;EAAc;EAAW,CAAC;AAG9C,KAAI,OAAO,iBAAiB,MAC1B,QAAO"}
@@ -13,17 +13,17 @@ function useThreadStoreSelector(store, selector) {
13
13
  /**
14
14
  * React hook for listing and managing Intelligence platform threads.
15
15
  *
16
- * On mount the hook fetches the thread list for the given `userId`/`agentId`
17
- * pair. When the Intelligence platform exposes a WebSocket URL, it also opens
18
- * a realtime subscription so the `threads` array stays current without
19
- * polling — thread creates, renames, archives, and deletes from any client
20
- * are reflected immediately.
16
+ * On mount the hook fetches the thread list for the runtime-authenticated user
17
+ * and the given `agentId`. When the Intelligence platform exposes a WebSocket
18
+ * URL, it also opens a realtime subscription so the `threads` array stays
19
+ * current without polling — thread creates, renames, archives, and deletes
20
+ * from any client are reflected immediately.
21
21
  *
22
22
  * Mutation methods (`renameThread`, `archiveThread`, `deleteThread`) return
23
23
  * promises that resolve once the platform confirms the operation and reject
24
24
  * with an `Error` on failure.
25
25
  *
26
- * @param input - User and agent identifiers that scope the thread list.
26
+ * @param input - Agent identifier and optional list controls.
27
27
  * @returns Thread list state and stable mutation callbacks.
28
28
  *
29
29
  * @example
@@ -32,7 +32,6 @@ function useThreadStoreSelector(store, selector) {
32
32
  *
33
33
  * function ThreadList() {
34
34
  * const { threads, isLoading, renameThread, deleteThread } = useThreads({
35
- * userId: "user-1",
36
35
  * agentId: "agent-1",
37
36
  * });
38
37
  *
@@ -52,7 +51,7 @@ function useThreadStoreSelector(store, selector) {
52
51
  * }
53
52
  * ```
54
53
  */
55
- function useThreads({ userId, agentId, includeArchived, limit }) {
54
+ function useThreads({ agentId, includeArchived, limit }) {
56
55
  const { copilotkit } = require_CopilotKitProvider.useCopilotKit();
57
56
  const [store] = (0, react.useState)(() => (0, _copilotkitnext_core.ɵcreateThreadStore)({ fetch: globalThis.fetch }));
58
57
  const threads = useThreadStoreSelector(store, _copilotkitnext_core.ɵselectThreads);
@@ -80,7 +79,6 @@ function useThreads({ userId, agentId, includeArchived, limit }) {
80
79
  runtimeUrl: copilotkit.runtimeUrl,
81
80
  headers: { ...copilotkit.headers },
82
81
  wsUrl: copilotkit.intelligence?.wsUrl,
83
- userId,
84
82
  agentId,
85
83
  includeArchived,
86
84
  limit
@@ -91,7 +89,6 @@ function useThreads({ userId, agentId, includeArchived, limit }) {
91
89
  copilotkit.runtimeUrl,
92
90
  headersKey,
93
91
  copilotkit.intelligence?.wsUrl,
94
- userId,
95
92
  agentId,
96
93
  copilotkit.headers,
97
94
  includeArchived,
@@ -1 +1 @@
1
- {"version":3,"file":"use-threads.cjs","names":["useCopilotKit","ɵselectThreads","ɵselectThreadsIsLoading","ɵselectThreadsError","ɵselectHasNextPage","ɵselectIsFetchingNextPage"],"sources":["../../src/hooks/use-threads.tsx"],"sourcesContent":["import { useCopilotKit } from \"@/providers/CopilotKitProvider\";\nimport {\n ɵcreateThreadStore,\n ɵselectThreads,\n ɵselectThreadsError,\n ɵselectThreadsIsLoading,\n ɵselectHasNextPage,\n ɵselectIsFetchingNextPage,\n type ɵThread as CoreThread,\n type ɵThreadRuntimeContext,\n type ɵThreadStore,\n} from \"@copilotkitnext/core\";\nimport {\n useCallback,\n useEffect,\n useMemo,\n useState,\n useSyncExternalStore,\n} from \"react\";\n\n/**\n * A conversation thread managed by the Intelligence platform.\n *\n * Each thread has a unique `id`, an optional human-readable `name`, and\n * timestamp fields tracking creation and update times.\n */\nexport interface Thread extends CoreThread {}\n\n/**\n * Configuration for the {@link useThreads} hook.\n *\n * Both fields are required they scope the thread list and all mutations\n * to a specific user/agent pair on the Intelligence platform.\n */\nexport interface UseThreadsInput {\n /** The ID of the current user. Thread queries and mutations are scoped to this user. */\n userId: string;\n /** The ID of the agent whose threads to list and manage. */\n agentId: string;\n /** When `true`, archived threads are included in the list. Defaults to `false`. */\n includeArchived?: boolean;\n /** Maximum number of threads to fetch per page. When set, enables cursor-based pagination. */\n limit?: number;\n}\n\n/**\n * Return value of the {@link useThreads} hook.\n *\n * The `threads` array is kept in sync with the platform via a realtime\n * WebSocket subscription (when available) and is sorted most-recently-updated\n * first. Mutations reject with an `Error` if the platform request fails.\n */\nexport interface UseThreadsResult {\n /**\n * Threads for the current user/agent pair, sorted by most recently\n * updated first. Updated in realtime when the platform pushes metadata\n * events. Includes archived threads only when `includeArchived` is set.\n */\n threads: Thread[];\n /**\n * `true` while the initial thread list is being fetched from the platform.\n * Subsequent realtime updates do not re-enter the loading state.\n */\n isLoading: boolean;\n /**\n * The most recent error from fetching threads or executing a mutation,\n * or `null` when there is no error. Reset to `null` on the next\n * successful fetch.\n */\n error: Error | null;\n /**\n * `true` when there are more threads available to fetch via\n * {@link fetchNextPage}. Only meaningful when `limit` is set.\n */\n hasNextPage: boolean;\n /**\n * `true` while a subsequent page of threads is being fetched.\n */\n isFetchingNextPage: boolean;\n /**\n * Fetch the next page of threads. No-op when {@link hasNextPage} is\n * `false` or a page fetch is already in progress.\n */\n fetchNextPage: () => void;\n /**\n * Rename a thread on the platform.\n * Resolves when the server confirms the update; rejects on failure.\n */\n renameThread: (threadId: string, name: string) => Promise<void>;\n /**\n * Archive a thread on the platform.\n * Archived threads are excluded from subsequent list results.\n * Resolves when the server confirms the update; rejects on failure.\n */\n archiveThread: (threadId: string) => Promise<void>;\n /**\n * Permanently delete a thread from the platform.\n * This is irreversible. Resolves when the server confirms deletion;\n * rejects on failure.\n */\n deleteThread: (threadId: string) => Promise<void>;\n}\n\nfunction useThreadStoreSelector<T>(\n store: ɵThreadStore,\n selector: (state: ReturnType<ɵThreadStore[\"getState\"]>) => T,\n): T {\n return useSyncExternalStore(\n useCallback(\n (onStoreChange) => {\n const subscription = store.select(selector).subscribe(onStoreChange);\n return () => subscription.unsubscribe();\n },\n [store, selector],\n ),\n () => selector(store.getState()),\n );\n}\n\n/**\n * React hook for listing and managing Intelligence platform threads.\n *\n * On mount the hook fetches the thread list for the given `userId`/`agentId`\n * pair. When the Intelligence platform exposes a WebSocket URL, it also opens\n * a realtime subscription so the `threads` array stays current without\n * polling — thread creates, renames, archives, and deletes from any client\n * are reflected immediately.\n *\n * Mutation methods (`renameThread`, `archiveThread`, `deleteThread`) return\n * promises that resolve once the platform confirms the operation and reject\n * with an `Error` on failure.\n *\n * @param input - User and agent identifiers that scope the thread list.\n * @returns Thread list state and stable mutation callbacks.\n *\n * @example\n * ```tsx\n * import { useThreads } from \"@copilotkitnext/react\";\n *\n * function ThreadList() {\n * const { threads, isLoading, renameThread, deleteThread } = useThreads({\n * userId: \"user-1\",\n * agentId: \"agent-1\",\n * });\n *\n * if (isLoading) return <p>Loading…</p>;\n *\n * return (\n * <ul>\n * {threads.map((t) => (\n * <li key={t.id}>\n * {t.name ?? \"Untitled\"}\n * <button onClick={() => renameThread(t.id, \"New name\")}>Rename</button>\n * <button onClick={() => deleteThread(t.id)}>Delete</button>\n * </li>\n * ))}\n * </ul>\n * );\n * }\n * ```\n */\nexport function useThreads({\n userId,\n agentId,\n includeArchived,\n limit,\n}: UseThreadsInput): UseThreadsResult {\n const { copilotkit } = useCopilotKit();\n\n const [store] = useState(() =>\n ɵcreateThreadStore({\n fetch: globalThis.fetch,\n }),\n );\n\n const threads = useThreadStoreSelector(store, ɵselectThreads);\n const storeIsLoading = useThreadStoreSelector(store, ɵselectThreadsIsLoading);\n const storeError = useThreadStoreSelector(store, ɵselectThreadsError);\n const hasNextPage = useThreadStoreSelector(store, ɵselectHasNextPage);\n const isFetchingNextPage = useThreadStoreSelector(\n store,\n ɵselectIsFetchingNextPage,\n );\n const headersKey = useMemo(() => {\n return JSON.stringify(\n Object.entries(copilotkit.headers ?? {}).sort(([left], [right]) =>\n left.localeCompare(right),\n ),\n );\n }, [copilotkit.headers]);\n const runtimeError = useMemo(() => {\n if (copilotkit.runtimeUrl) {\n return null;\n }\n\n return new Error(\"Runtime URL is not configured\");\n }, [copilotkit.runtimeUrl]);\n const isLoading = runtimeError ? false : storeIsLoading;\n const error = runtimeError ?? storeError;\n\n useEffect(() => {\n store.start();\n return () => {\n store.stop();\n };\n }, [store]);\n\n useEffect(() => {\n const context: ɵThreadRuntimeContext | null = copilotkit.runtimeUrl\n ? {\n runtimeUrl: copilotkit.runtimeUrl,\n headers: { ...copilotkit.headers },\n wsUrl: copilotkit.intelligence?.wsUrl,\n userId,\n agentId,\n includeArchived,\n limit,\n }\n : null;\n\n store.setContext(context);\n }, [\n store,\n copilotkit.runtimeUrl,\n headersKey,\n copilotkit.intelligence?.wsUrl,\n userId,\n agentId,\n copilotkit.headers,\n includeArchived,\n limit,\n ]);\n\n const renameThread = useCallback(\n (threadId: string, name: string) => store.renameThread(threadId, name),\n [store],\n );\n\n const archiveThread = useCallback(\n (threadId: string) => store.archiveThread(threadId),\n [store],\n );\n\n const deleteThread = useCallback(\n (threadId: string) => store.deleteThread(threadId),\n [store],\n );\n\n const fetchNextPage = useCallback(() => store.fetchNextPage(), [store]);\n\n return {\n threads,\n isLoading,\n error,\n hasNextPage,\n isFetchingNextPage,\n fetchNextPage,\n renameThread,\n archiveThread,\n deleteThread,\n };\n}\n"],"mappings":";;;;;;AAuGA,SAAS,uBACP,OACA,UACG;AACH,gEAEK,kBAAkB;EACjB,MAAM,eAAe,MAAM,OAAO,SAAS,CAAC,UAAU,cAAc;AACpE,eAAa,aAAa,aAAa;IAEzC,CAAC,OAAO,SAAS,CAClB,QACK,SAAS,MAAM,UAAU,CAAC,CACjC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6CH,SAAgB,WAAW,EACzB,QACA,SACA,iBACA,SACoC;CACpC,MAAM,EAAE,eAAeA,0CAAe;CAEtC,MAAM,CAAC,gFACc,EACjB,OAAO,WAAW,OACnB,CAAC,CACH;CAED,MAAM,UAAU,uBAAuB,OAAOC,oCAAe;CAC7D,MAAM,iBAAiB,uBAAuB,OAAOC,6CAAwB;CAC7E,MAAM,aAAa,uBAAuB,OAAOC,yCAAoB;CACrE,MAAM,cAAc,uBAAuB,OAAOC,wCAAmB;CACrE,MAAM,qBAAqB,uBACzB,OACAC,+CACD;CACD,MAAM,sCAA2B;AAC/B,SAAO,KAAK,UACV,OAAO,QAAQ,WAAW,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,WACtD,KAAK,cAAc,MAAM,CAC1B,CACF;IACA,CAAC,WAAW,QAAQ,CAAC;CACxB,MAAM,wCAA6B;AACjC,MAAI,WAAW,WACb,QAAO;AAGT,yBAAO,IAAI,MAAM,gCAAgC;IAChD,CAAC,WAAW,WAAW,CAAC;CAC3B,MAAM,YAAY,eAAe,QAAQ;CACzC,MAAM,QAAQ,gBAAgB;AAE9B,4BAAgB;AACd,QAAM,OAAO;AACb,eAAa;AACX,SAAM,MAAM;;IAEb,CAAC,MAAM,CAAC;AAEX,4BAAgB;EACd,MAAM,UAAwC,WAAW,aACrD;GACE,YAAY,WAAW;GACvB,SAAS,EAAE,GAAG,WAAW,SAAS;GAClC,OAAO,WAAW,cAAc;GAChC;GACA;GACA;GACA;GACD,GACD;AAEJ,QAAM,WAAW,QAAQ;IACxB;EACD;EACA,WAAW;EACX;EACA,WAAW,cAAc;EACzB;EACA;EACA,WAAW;EACX;EACA;EACD,CAAC;CAEF,MAAM,uCACH,UAAkB,SAAiB,MAAM,aAAa,UAAU,KAAK,EACtE,CAAC,MAAM,CACR;CAED,MAAM,wCACH,aAAqB,MAAM,cAAc,SAAS,EACnD,CAAC,MAAM,CACR;CAED,MAAM,uCACH,aAAqB,MAAM,aAAa,SAAS,EAClD,CAAC,MAAM,CACR;AAID,QAAO;EACL;EACA;EACA;EACA;EACA;EACA,4CARsC,MAAM,eAAe,EAAE,CAAC,MAAM,CAAC;EASrE;EACA;EACA;EACD"}
1
+ {"version":3,"file":"use-threads.cjs","names":["useCopilotKit","ɵselectThreads","ɵselectThreadsIsLoading","ɵselectThreadsError","ɵselectHasNextPage","ɵselectIsFetchingNextPage"],"sources":["../../src/hooks/use-threads.tsx"],"sourcesContent":["import { useCopilotKit } from \"@/providers/CopilotKitProvider\";\nimport {\n ɵcreateThreadStore,\n ɵselectThreads,\n ɵselectThreadsError,\n ɵselectThreadsIsLoading,\n ɵselectHasNextPage,\n ɵselectIsFetchingNextPage,\n type ɵThread as CoreThread,\n type ɵThreadRuntimeContext,\n type ɵThreadStore,\n} from \"@copilotkitnext/core\";\nimport {\n useCallback,\n useEffect,\n useMemo,\n useState,\n useSyncExternalStore,\n} from \"react\";\n\n/**\n * A conversation thread managed by the Intelligence platform.\n *\n * Each thread has a unique `id`, an optional human-readable `name`, and\n * timestamp fields tracking creation and update times.\n */\nexport interface Thread extends CoreThread {}\n\n/**\n * Configuration for the {@link useThreads} hook.\n *\n * Thread operations are scoped to the runtime-authenticated user and the\n * provided agent on the Intelligence platform.\n */\nexport interface UseThreadsInput {\n /** The ID of the agent whose threads to list and manage. */\n agentId: string;\n /** When `true`, archived threads are included in the list. Defaults to `false`. */\n includeArchived?: boolean;\n /** Maximum number of threads to fetch per page. When set, enables cursor-based pagination. */\n limit?: number;\n}\n\n/**\n * Return value of the {@link useThreads} hook.\n *\n * The `threads` array is kept in sync with the platform via a realtime\n * WebSocket subscription (when available) and is sorted most-recently-updated\n * first. Mutations reject with an `Error` if the platform request fails.\n */\nexport interface UseThreadsResult {\n /**\n * Threads for the current user/agent pair, sorted by most recently\n * updated first. Updated in realtime when the platform pushes metadata\n * events. Includes archived threads only when `includeArchived` is set.\n */\n threads: Thread[];\n /**\n * `true` while the initial thread list is being fetched from the platform.\n * Subsequent realtime updates do not re-enter the loading state.\n */\n isLoading: boolean;\n /**\n * The most recent error from fetching threads or executing a mutation,\n * or `null` when there is no error. Reset to `null` on the next\n * successful fetch.\n */\n error: Error | null;\n /**\n * `true` when there are more threads available to fetch via\n * {@link fetchNextPage}. Only meaningful when `limit` is set.\n */\n hasNextPage: boolean;\n /**\n * `true` while a subsequent page of threads is being fetched.\n */\n isFetchingNextPage: boolean;\n /**\n * Fetch the next page of threads. No-op when {@link hasNextPage} is\n * `false` or a page fetch is already in progress.\n */\n fetchNextPage: () => void;\n /**\n * Rename a thread on the platform.\n * Resolves when the server confirms the update; rejects on failure.\n */\n renameThread: (threadId: string, name: string) => Promise<void>;\n /**\n * Archive a thread on the platform.\n * Archived threads are excluded from subsequent list results.\n * Resolves when the server confirms the update; rejects on failure.\n */\n archiveThread: (threadId: string) => Promise<void>;\n /**\n * Permanently delete a thread from the platform.\n * This is irreversible. Resolves when the server confirms deletion;\n * rejects on failure.\n */\n deleteThread: (threadId: string) => Promise<void>;\n}\n\nfunction useThreadStoreSelector<T>(\n store: ɵThreadStore,\n selector: (state: ReturnType<ɵThreadStore[\"getState\"]>) => T,\n): T {\n return useSyncExternalStore(\n useCallback(\n (onStoreChange) => {\n const subscription = store.select(selector).subscribe(onStoreChange);\n return () => subscription.unsubscribe();\n },\n [store, selector],\n ),\n () => selector(store.getState()),\n );\n}\n\n/**\n * React hook for listing and managing Intelligence platform threads.\n *\n * On mount the hook fetches the thread list for the runtime-authenticated user\n * and the given `agentId`. When the Intelligence platform exposes a WebSocket\n * URL, it also opens a realtime subscription so the `threads` array stays\n * current without polling — thread creates, renames, archives, and deletes\n * from any client are reflected immediately.\n *\n * Mutation methods (`renameThread`, `archiveThread`, `deleteThread`) return\n * promises that resolve once the platform confirms the operation and reject\n * with an `Error` on failure.\n *\n * @param input - Agent identifier and optional list controls.\n * @returns Thread list state and stable mutation callbacks.\n *\n * @example\n * ```tsx\n * import { useThreads } from \"@copilotkitnext/react\";\n *\n * function ThreadList() {\n * const { threads, isLoading, renameThread, deleteThread } = useThreads({\n * agentId: \"agent-1\",\n * });\n *\n * if (isLoading) return <p>Loading…</p>;\n *\n * return (\n * <ul>\n * {threads.map((t) => (\n * <li key={t.id}>\n * {t.name ?? \"Untitled\"}\n * <button onClick={() => renameThread(t.id, \"New name\")}>Rename</button>\n * <button onClick={() => deleteThread(t.id)}>Delete</button>\n * </li>\n * ))}\n * </ul>\n * );\n * }\n * ```\n */\nexport function useThreads({\n agentId,\n includeArchived,\n limit,\n}: UseThreadsInput): UseThreadsResult {\n const { copilotkit } = useCopilotKit();\n\n const [store] = useState(() =>\n ɵcreateThreadStore({\n fetch: globalThis.fetch,\n }),\n );\n\n const threads = useThreadStoreSelector(store, ɵselectThreads);\n const storeIsLoading = useThreadStoreSelector(store, ɵselectThreadsIsLoading);\n const storeError = useThreadStoreSelector(store, ɵselectThreadsError);\n const hasNextPage = useThreadStoreSelector(store, ɵselectHasNextPage);\n const isFetchingNextPage = useThreadStoreSelector(\n store,\n ɵselectIsFetchingNextPage,\n );\n const headersKey = useMemo(() => {\n return JSON.stringify(\n Object.entries(copilotkit.headers ?? {}).sort(([left], [right]) =>\n left.localeCompare(right),\n ),\n );\n }, [copilotkit.headers]);\n const runtimeError = useMemo(() => {\n if (copilotkit.runtimeUrl) {\n return null;\n }\n\n return new Error(\"Runtime URL is not configured\");\n }, [copilotkit.runtimeUrl]);\n const isLoading = runtimeError ? false : storeIsLoading;\n const error = runtimeError ?? storeError;\n\n useEffect(() => {\n store.start();\n return () => {\n store.stop();\n };\n }, [store]);\n\n useEffect(() => {\n const context: ɵThreadRuntimeContext | null = copilotkit.runtimeUrl\n ? {\n runtimeUrl: copilotkit.runtimeUrl,\n headers: { ...copilotkit.headers },\n wsUrl: copilotkit.intelligence?.wsUrl,\n agentId,\n includeArchived,\n limit,\n }\n : null;\n\n store.setContext(context);\n }, [\n store,\n copilotkit.runtimeUrl,\n headersKey,\n copilotkit.intelligence?.wsUrl,\n agentId,\n copilotkit.headers,\n includeArchived,\n limit,\n ]);\n\n const renameThread = useCallback(\n (threadId: string, name: string) => store.renameThread(threadId, name),\n [store],\n );\n\n const archiveThread = useCallback(\n (threadId: string) => store.archiveThread(threadId),\n [store],\n );\n\n const deleteThread = useCallback(\n (threadId: string) => store.deleteThread(threadId),\n [store],\n );\n\n const fetchNextPage = useCallback(() => store.fetchNextPage(), [store]);\n\n return {\n threads,\n isLoading,\n error,\n hasNextPage,\n isFetchingNextPage,\n fetchNextPage,\n renameThread,\n archiveThread,\n deleteThread,\n };\n}\n"],"mappings":";;;;;;AAqGA,SAAS,uBACP,OACA,UACG;AACH,gEAEK,kBAAkB;EACjB,MAAM,eAAe,MAAM,OAAO,SAAS,CAAC,UAAU,cAAc;AACpE,eAAa,aAAa,aAAa;IAEzC,CAAC,OAAO,SAAS,CAClB,QACK,SAAS,MAAM,UAAU,CAAC,CACjC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4CH,SAAgB,WAAW,EACzB,SACA,iBACA,SACoC;CACpC,MAAM,EAAE,eAAeA,0CAAe;CAEtC,MAAM,CAAC,gFACc,EACjB,OAAO,WAAW,OACnB,CAAC,CACH;CAED,MAAM,UAAU,uBAAuB,OAAOC,oCAAe;CAC7D,MAAM,iBAAiB,uBAAuB,OAAOC,6CAAwB;CAC7E,MAAM,aAAa,uBAAuB,OAAOC,yCAAoB;CACrE,MAAM,cAAc,uBAAuB,OAAOC,wCAAmB;CACrE,MAAM,qBAAqB,uBACzB,OACAC,+CACD;CACD,MAAM,sCAA2B;AAC/B,SAAO,KAAK,UACV,OAAO,QAAQ,WAAW,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,WACtD,KAAK,cAAc,MAAM,CAC1B,CACF;IACA,CAAC,WAAW,QAAQ,CAAC;CACxB,MAAM,wCAA6B;AACjC,MAAI,WAAW,WACb,QAAO;AAGT,yBAAO,IAAI,MAAM,gCAAgC;IAChD,CAAC,WAAW,WAAW,CAAC;CAC3B,MAAM,YAAY,eAAe,QAAQ;CACzC,MAAM,QAAQ,gBAAgB;AAE9B,4BAAgB;AACd,QAAM,OAAO;AACb,eAAa;AACX,SAAM,MAAM;;IAEb,CAAC,MAAM,CAAC;AAEX,4BAAgB;EACd,MAAM,UAAwC,WAAW,aACrD;GACE,YAAY,WAAW;GACvB,SAAS,EAAE,GAAG,WAAW,SAAS;GAClC,OAAO,WAAW,cAAc;GAChC;GACA;GACA;GACD,GACD;AAEJ,QAAM,WAAW,QAAQ;IACxB;EACD;EACA,WAAW;EACX;EACA,WAAW,cAAc;EACzB;EACA,WAAW;EACX;EACA;EACD,CAAC;CAEF,MAAM,uCACH,UAAkB,SAAiB,MAAM,aAAa,UAAU,KAAK,EACtE,CAAC,MAAM,CACR;CAED,MAAM,wCACH,aAAqB,MAAM,cAAc,SAAS,EACnD,CAAC,MAAM,CACR;CAED,MAAM,uCACH,aAAqB,MAAM,aAAa,SAAS,EAClD,CAAC,MAAM,CACR;AAID,QAAO;EACL;EACA;EACA;EACA;EACA;EACA,4CARsC,MAAM,eAAe,EAAE,CAAC,MAAM,CAAC;EASrE;EACA;EACA;EACD"}
@@ -11,12 +11,10 @@ interface Thread extends ɵThread {}
11
11
  /**
12
12
  * Configuration for the {@link useThreads} hook.
13
13
  *
14
- * Both fields are required they scope the thread list and all mutations
15
- * to a specific user/agent pair on the Intelligence platform.
14
+ * Thread operations are scoped to the runtime-authenticated user and the
15
+ * provided agent on the Intelligence platform.
16
16
  */
17
17
  interface UseThreadsInput {
18
- /** The ID of the current user. Thread queries and mutations are scoped to this user. */
19
- userId: string;
20
18
  /** The ID of the agent whose threads to list and manage. */
21
19
  agentId: string;
22
20
  /** When `true`, archived threads are included in the list. Defaults to `false`. */
@@ -84,17 +82,17 @@ interface UseThreadsResult {
84
82
  /**
85
83
  * React hook for listing and managing Intelligence platform threads.
86
84
  *
87
- * On mount the hook fetches the thread list for the given `userId`/`agentId`
88
- * pair. When the Intelligence platform exposes a WebSocket URL, it also opens
89
- * a realtime subscription so the `threads` array stays current without
90
- * polling — thread creates, renames, archives, and deletes from any client
91
- * are reflected immediately.
85
+ * On mount the hook fetches the thread list for the runtime-authenticated user
86
+ * and the given `agentId`. When the Intelligence platform exposes a WebSocket
87
+ * URL, it also opens a realtime subscription so the `threads` array stays
88
+ * current without polling — thread creates, renames, archives, and deletes
89
+ * from any client are reflected immediately.
92
90
  *
93
91
  * Mutation methods (`renameThread`, `archiveThread`, `deleteThread`) return
94
92
  * promises that resolve once the platform confirms the operation and reject
95
93
  * with an `Error` on failure.
96
94
  *
97
- * @param input - User and agent identifiers that scope the thread list.
95
+ * @param input - Agent identifier and optional list controls.
98
96
  * @returns Thread list state and stable mutation callbacks.
99
97
  *
100
98
  * @example
@@ -103,7 +101,6 @@ interface UseThreadsResult {
103
101
  *
104
102
  * function ThreadList() {
105
103
  * const { threads, isLoading, renameThread, deleteThread } = useThreads({
106
- * userId: "user-1",
107
104
  * agentId: "agent-1",
108
105
  * });
109
106
  *
@@ -124,7 +121,6 @@ interface UseThreadsResult {
124
121
  * ```
125
122
  */
126
123
  declare function useThreads({
127
- userId,
128
124
  agentId,
129
125
  includeArchived,
130
126
  limit
@@ -1 +1 @@
1
- {"version":3,"file":"use-threads.d.cts","names":[],"sources":["../../src/hooks/use-threads.tsx"],"mappings":";;;;;AA0BA;;;;UAAiB,MAAA,SAAe,OAAA;;;;;;;UAQf,eAAA;EAQV;EANL,MAAA;EAgBe;EAdf,OAAA;;EAEA,eAAA;EA6BO;EA3BP,KAAA;AAAA;;;;;;;;UAUe,gBAAA;EAsBf;;;;;EAhBA,OAAA,EAAS,MAAA;EA8ByC;;;;EAzBlD,SAAA;EAqCe;;;;AA6DjB;EA5FE,KAAA,EAAO,KAAA;;;;;EAKP,WAAA;EA4FC;;;EAxFD,kBAAA;EAoFA;;;;EA/EA,aAAA;EAiFA;;;;EA5EA,YAAA,GAAe,QAAA,UAAkB,IAAA,aAAiB,OAAA;EA8Ef;;;;;EAxEnC,aAAA,GAAgB,QAAA,aAAqB,OAAA;;;;;;EAMrC,YAAA,GAAe,QAAA,aAAqB,OAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA6DtB,UAAA,CAAA;EACd,MAAA;EACA,OAAA;EACA,eAAA;EACA;AAAA,GACC,eAAA,GAAkB,gBAAA"}
1
+ {"version":3,"file":"use-threads.d.cts","names":[],"sources":["../../src/hooks/use-threads.tsx"],"mappings":";;;;;AA0BA;;;;UAAiB,MAAA,SAAe,OAAA;;;;;;;UAQf,eAAA;EAMV;EAJL,OAAA;EAc+B;EAZ/B,eAAA;EAkBS;EAhBT,KAAA;AAAA;;;;;;;;UAUe,gBAAA;EAiBR;;;;;EAXP,OAAA,EAAS,MAAA;EA8BwB;;;;EAzBjC,SAAA;EAqCA;;;;;EA/BA,KAAA,EAAO,KAAA;EA2FiB;;;;EAtFxB,WAAA;EA0FC;;;EAtFD,kBAAA;EAmFA;;;;EA9EA,aAAA;EAgFA;;;;EA3EA,YAAA,GAAe,QAAA,UAAkB,IAAA,aAAiB,OAAA;;;;;;EAMlD,aAAA,GAAgB,QAAA,aAAqB,OAAA;;;;;;EAMrC,YAAA,GAAe,QAAA,aAAqB,OAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA4DtB,UAAA,CAAA;EACd,OAAA;EACA,eAAA;EACA;AAAA,GACC,eAAA,GAAkB,gBAAA"}
@@ -11,12 +11,10 @@ interface Thread extends ɵThread {}
11
11
  /**
12
12
  * Configuration for the {@link useThreads} hook.
13
13
  *
14
- * Both fields are required they scope the thread list and all mutations
15
- * to a specific user/agent pair on the Intelligence platform.
14
+ * Thread operations are scoped to the runtime-authenticated user and the
15
+ * provided agent on the Intelligence platform.
16
16
  */
17
17
  interface UseThreadsInput {
18
- /** The ID of the current user. Thread queries and mutations are scoped to this user. */
19
- userId: string;
20
18
  /** The ID of the agent whose threads to list and manage. */
21
19
  agentId: string;
22
20
  /** When `true`, archived threads are included in the list. Defaults to `false`. */
@@ -84,17 +82,17 @@ interface UseThreadsResult {
84
82
  /**
85
83
  * React hook for listing and managing Intelligence platform threads.
86
84
  *
87
- * On mount the hook fetches the thread list for the given `userId`/`agentId`
88
- * pair. When the Intelligence platform exposes a WebSocket URL, it also opens
89
- * a realtime subscription so the `threads` array stays current without
90
- * polling — thread creates, renames, archives, and deletes from any client
91
- * are reflected immediately.
85
+ * On mount the hook fetches the thread list for the runtime-authenticated user
86
+ * and the given `agentId`. When the Intelligence platform exposes a WebSocket
87
+ * URL, it also opens a realtime subscription so the `threads` array stays
88
+ * current without polling — thread creates, renames, archives, and deletes
89
+ * from any client are reflected immediately.
92
90
  *
93
91
  * Mutation methods (`renameThread`, `archiveThread`, `deleteThread`) return
94
92
  * promises that resolve once the platform confirms the operation and reject
95
93
  * with an `Error` on failure.
96
94
  *
97
- * @param input - User and agent identifiers that scope the thread list.
95
+ * @param input - Agent identifier and optional list controls.
98
96
  * @returns Thread list state and stable mutation callbacks.
99
97
  *
100
98
  * @example
@@ -103,7 +101,6 @@ interface UseThreadsResult {
103
101
  *
104
102
  * function ThreadList() {
105
103
  * const { threads, isLoading, renameThread, deleteThread } = useThreads({
106
- * userId: "user-1",
107
104
  * agentId: "agent-1",
108
105
  * });
109
106
  *
@@ -124,7 +121,6 @@ interface UseThreadsResult {
124
121
  * ```
125
122
  */
126
123
  declare function useThreads({
127
- userId,
128
124
  agentId,
129
125
  includeArchived,
130
126
  limit
@@ -1 +1 @@
1
- {"version":3,"file":"use-threads.d.mts","names":[],"sources":["../../src/hooks/use-threads.tsx"],"mappings":";;;;;AA0BA;;;;UAAiB,MAAA,SAAe,OAAA;;;;;;;UAQf,eAAA;EAQV;EANL,MAAA;EAgBe;EAdf,OAAA;;EAEA,eAAA;EA6BO;EA3BP,KAAA;AAAA;;;;;;;;UAUe,gBAAA;EAsBf;;;;;EAhBA,OAAA,EAAS,MAAA;EA8ByC;;;;EAzBlD,SAAA;EAqCe;;;;AA6DjB;EA5FE,KAAA,EAAO,KAAA;;;;;EAKP,WAAA;EA4FC;;;EAxFD,kBAAA;EAoFA;;;;EA/EA,aAAA;EAiFA;;;;EA5EA,YAAA,GAAe,QAAA,UAAkB,IAAA,aAAiB,OAAA;EA8Ef;;;;;EAxEnC,aAAA,GAAgB,QAAA,aAAqB,OAAA;;;;;;EAMrC,YAAA,GAAe,QAAA,aAAqB,OAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA6DtB,UAAA,CAAA;EACd,MAAA;EACA,OAAA;EACA,eAAA;EACA;AAAA,GACC,eAAA,GAAkB,gBAAA"}
1
+ {"version":3,"file":"use-threads.d.mts","names":[],"sources":["../../src/hooks/use-threads.tsx"],"mappings":";;;;;AA0BA;;;;UAAiB,MAAA,SAAe,OAAA;;;;;;;UAQf,eAAA;EAMV;EAJL,OAAA;EAc+B;EAZ/B,eAAA;EAkBS;EAhBT,KAAA;AAAA;;;;;;;;UAUe,gBAAA;EAiBR;;;;;EAXP,OAAA,EAAS,MAAA;EA8BwB;;;;EAzBjC,SAAA;EAqCA;;;;;EA/BA,KAAA,EAAO,KAAA;EA2FiB;;;;EAtFxB,WAAA;EA0FC;;;EAtFD,kBAAA;EAmFA;;;;EA9EA,aAAA;EAgFA;;;;EA3EA,YAAA,GAAe,QAAA,UAAkB,IAAA,aAAiB,OAAA;;;;;;EAMlD,aAAA,GAAgB,QAAA,aAAqB,OAAA;;;;;;EAMrC,YAAA,GAAe,QAAA,aAAqB,OAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA4DtB,UAAA,CAAA;EACd,OAAA;EACA,eAAA;EACA;AAAA,GACC,eAAA,GAAkB,gBAAA"}
@@ -12,17 +12,17 @@ function useThreadStoreSelector(store, selector) {
12
12
  /**
13
13
  * React hook for listing and managing Intelligence platform threads.
14
14
  *
15
- * On mount the hook fetches the thread list for the given `userId`/`agentId`
16
- * pair. When the Intelligence platform exposes a WebSocket URL, it also opens
17
- * a realtime subscription so the `threads` array stays current without
18
- * polling — thread creates, renames, archives, and deletes from any client
19
- * are reflected immediately.
15
+ * On mount the hook fetches the thread list for the runtime-authenticated user
16
+ * and the given `agentId`. When the Intelligence platform exposes a WebSocket
17
+ * URL, it also opens a realtime subscription so the `threads` array stays
18
+ * current without polling — thread creates, renames, archives, and deletes
19
+ * from any client are reflected immediately.
20
20
  *
21
21
  * Mutation methods (`renameThread`, `archiveThread`, `deleteThread`) return
22
22
  * promises that resolve once the platform confirms the operation and reject
23
23
  * with an `Error` on failure.
24
24
  *
25
- * @param input - User and agent identifiers that scope the thread list.
25
+ * @param input - Agent identifier and optional list controls.
26
26
  * @returns Thread list state and stable mutation callbacks.
27
27
  *
28
28
  * @example
@@ -31,7 +31,6 @@ function useThreadStoreSelector(store, selector) {
31
31
  *
32
32
  * function ThreadList() {
33
33
  * const { threads, isLoading, renameThread, deleteThread } = useThreads({
34
- * userId: "user-1",
35
34
  * agentId: "agent-1",
36
35
  * });
37
36
  *
@@ -51,7 +50,7 @@ function useThreadStoreSelector(store, selector) {
51
50
  * }
52
51
  * ```
53
52
  */
54
- function useThreads({ userId, agentId, includeArchived, limit }) {
53
+ function useThreads({ agentId, includeArchived, limit }) {
55
54
  const { copilotkit } = useCopilotKit();
56
55
  const [store] = useState(() => ɵcreateThreadStore({ fetch: globalThis.fetch }));
57
56
  const threads = useThreadStoreSelector(store, ɵselectThreads);
@@ -79,7 +78,6 @@ function useThreads({ userId, agentId, includeArchived, limit }) {
79
78
  runtimeUrl: copilotkit.runtimeUrl,
80
79
  headers: { ...copilotkit.headers },
81
80
  wsUrl: copilotkit.intelligence?.wsUrl,
82
- userId,
83
81
  agentId,
84
82
  includeArchived,
85
83
  limit
@@ -90,7 +88,6 @@ function useThreads({ userId, agentId, includeArchived, limit }) {
90
88
  copilotkit.runtimeUrl,
91
89
  headersKey,
92
90
  copilotkit.intelligence?.wsUrl,
93
- userId,
94
91
  agentId,
95
92
  copilotkit.headers,
96
93
  includeArchived,
@@ -1 +1 @@
1
- {"version":3,"file":"use-threads.mjs","names":[],"sources":["../../src/hooks/use-threads.tsx"],"sourcesContent":["import { useCopilotKit } from \"@/providers/CopilotKitProvider\";\nimport {\n ɵcreateThreadStore,\n ɵselectThreads,\n ɵselectThreadsError,\n ɵselectThreadsIsLoading,\n ɵselectHasNextPage,\n ɵselectIsFetchingNextPage,\n type ɵThread as CoreThread,\n type ɵThreadRuntimeContext,\n type ɵThreadStore,\n} from \"@copilotkitnext/core\";\nimport {\n useCallback,\n useEffect,\n useMemo,\n useState,\n useSyncExternalStore,\n} from \"react\";\n\n/**\n * A conversation thread managed by the Intelligence platform.\n *\n * Each thread has a unique `id`, an optional human-readable `name`, and\n * timestamp fields tracking creation and update times.\n */\nexport interface Thread extends CoreThread {}\n\n/**\n * Configuration for the {@link useThreads} hook.\n *\n * Both fields are required they scope the thread list and all mutations\n * to a specific user/agent pair on the Intelligence platform.\n */\nexport interface UseThreadsInput {\n /** The ID of the current user. Thread queries and mutations are scoped to this user. */\n userId: string;\n /** The ID of the agent whose threads to list and manage. */\n agentId: string;\n /** When `true`, archived threads are included in the list. Defaults to `false`. */\n includeArchived?: boolean;\n /** Maximum number of threads to fetch per page. When set, enables cursor-based pagination. */\n limit?: number;\n}\n\n/**\n * Return value of the {@link useThreads} hook.\n *\n * The `threads` array is kept in sync with the platform via a realtime\n * WebSocket subscription (when available) and is sorted most-recently-updated\n * first. Mutations reject with an `Error` if the platform request fails.\n */\nexport interface UseThreadsResult {\n /**\n * Threads for the current user/agent pair, sorted by most recently\n * updated first. Updated in realtime when the platform pushes metadata\n * events. Includes archived threads only when `includeArchived` is set.\n */\n threads: Thread[];\n /**\n * `true` while the initial thread list is being fetched from the platform.\n * Subsequent realtime updates do not re-enter the loading state.\n */\n isLoading: boolean;\n /**\n * The most recent error from fetching threads or executing a mutation,\n * or `null` when there is no error. Reset to `null` on the next\n * successful fetch.\n */\n error: Error | null;\n /**\n * `true` when there are more threads available to fetch via\n * {@link fetchNextPage}. Only meaningful when `limit` is set.\n */\n hasNextPage: boolean;\n /**\n * `true` while a subsequent page of threads is being fetched.\n */\n isFetchingNextPage: boolean;\n /**\n * Fetch the next page of threads. No-op when {@link hasNextPage} is\n * `false` or a page fetch is already in progress.\n */\n fetchNextPage: () => void;\n /**\n * Rename a thread on the platform.\n * Resolves when the server confirms the update; rejects on failure.\n */\n renameThread: (threadId: string, name: string) => Promise<void>;\n /**\n * Archive a thread on the platform.\n * Archived threads are excluded from subsequent list results.\n * Resolves when the server confirms the update; rejects on failure.\n */\n archiveThread: (threadId: string) => Promise<void>;\n /**\n * Permanently delete a thread from the platform.\n * This is irreversible. Resolves when the server confirms deletion;\n * rejects on failure.\n */\n deleteThread: (threadId: string) => Promise<void>;\n}\n\nfunction useThreadStoreSelector<T>(\n store: ɵThreadStore,\n selector: (state: ReturnType<ɵThreadStore[\"getState\"]>) => T,\n): T {\n return useSyncExternalStore(\n useCallback(\n (onStoreChange) => {\n const subscription = store.select(selector).subscribe(onStoreChange);\n return () => subscription.unsubscribe();\n },\n [store, selector],\n ),\n () => selector(store.getState()),\n );\n}\n\n/**\n * React hook for listing and managing Intelligence platform threads.\n *\n * On mount the hook fetches the thread list for the given `userId`/`agentId`\n * pair. When the Intelligence platform exposes a WebSocket URL, it also opens\n * a realtime subscription so the `threads` array stays current without\n * polling — thread creates, renames, archives, and deletes from any client\n * are reflected immediately.\n *\n * Mutation methods (`renameThread`, `archiveThread`, `deleteThread`) return\n * promises that resolve once the platform confirms the operation and reject\n * with an `Error` on failure.\n *\n * @param input - User and agent identifiers that scope the thread list.\n * @returns Thread list state and stable mutation callbacks.\n *\n * @example\n * ```tsx\n * import { useThreads } from \"@copilotkitnext/react\";\n *\n * function ThreadList() {\n * const { threads, isLoading, renameThread, deleteThread } = useThreads({\n * userId: \"user-1\",\n * agentId: \"agent-1\",\n * });\n *\n * if (isLoading) return <p>Loading…</p>;\n *\n * return (\n * <ul>\n * {threads.map((t) => (\n * <li key={t.id}>\n * {t.name ?? \"Untitled\"}\n * <button onClick={() => renameThread(t.id, \"New name\")}>Rename</button>\n * <button onClick={() => deleteThread(t.id)}>Delete</button>\n * </li>\n * ))}\n * </ul>\n * );\n * }\n * ```\n */\nexport function useThreads({\n userId,\n agentId,\n includeArchived,\n limit,\n}: UseThreadsInput): UseThreadsResult {\n const { copilotkit } = useCopilotKit();\n\n const [store] = useState(() =>\n ɵcreateThreadStore({\n fetch: globalThis.fetch,\n }),\n );\n\n const threads = useThreadStoreSelector(store, ɵselectThreads);\n const storeIsLoading = useThreadStoreSelector(store, ɵselectThreadsIsLoading);\n const storeError = useThreadStoreSelector(store, ɵselectThreadsError);\n const hasNextPage = useThreadStoreSelector(store, ɵselectHasNextPage);\n const isFetchingNextPage = useThreadStoreSelector(\n store,\n ɵselectIsFetchingNextPage,\n );\n const headersKey = useMemo(() => {\n return JSON.stringify(\n Object.entries(copilotkit.headers ?? {}).sort(([left], [right]) =>\n left.localeCompare(right),\n ),\n );\n }, [copilotkit.headers]);\n const runtimeError = useMemo(() => {\n if (copilotkit.runtimeUrl) {\n return null;\n }\n\n return new Error(\"Runtime URL is not configured\");\n }, [copilotkit.runtimeUrl]);\n const isLoading = runtimeError ? false : storeIsLoading;\n const error = runtimeError ?? storeError;\n\n useEffect(() => {\n store.start();\n return () => {\n store.stop();\n };\n }, [store]);\n\n useEffect(() => {\n const context: ɵThreadRuntimeContext | null = copilotkit.runtimeUrl\n ? {\n runtimeUrl: copilotkit.runtimeUrl,\n headers: { ...copilotkit.headers },\n wsUrl: copilotkit.intelligence?.wsUrl,\n userId,\n agentId,\n includeArchived,\n limit,\n }\n : null;\n\n store.setContext(context);\n }, [\n store,\n copilotkit.runtimeUrl,\n headersKey,\n copilotkit.intelligence?.wsUrl,\n userId,\n agentId,\n copilotkit.headers,\n includeArchived,\n limit,\n ]);\n\n const renameThread = useCallback(\n (threadId: string, name: string) => store.renameThread(threadId, name),\n [store],\n );\n\n const archiveThread = useCallback(\n (threadId: string) => store.archiveThread(threadId),\n [store],\n );\n\n const deleteThread = useCallback(\n (threadId: string) => store.deleteThread(threadId),\n [store],\n );\n\n const fetchNextPage = useCallback(() => store.fetchNextPage(), [store]);\n\n return {\n threads,\n isLoading,\n error,\n hasNextPage,\n isFetchingNextPage,\n fetchNextPage,\n renameThread,\n archiveThread,\n deleteThread,\n };\n}\n"],"mappings":";;;;;AAuGA,SAAS,uBACP,OACA,UACG;AACH,QAAO,qBACL,aACG,kBAAkB;EACjB,MAAM,eAAe,MAAM,OAAO,SAAS,CAAC,UAAU,cAAc;AACpE,eAAa,aAAa,aAAa;IAEzC,CAAC,OAAO,SAAS,CAClB,QACK,SAAS,MAAM,UAAU,CAAC,CACjC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6CH,SAAgB,WAAW,EACzB,QACA,SACA,iBACA,SACoC;CACpC,MAAM,EAAE,eAAe,eAAe;CAEtC,MAAM,CAAC,SAAS,eACd,mBAAmB,EACjB,OAAO,WAAW,OACnB,CAAC,CACH;CAED,MAAM,UAAU,uBAAuB,OAAO,eAAe;CAC7D,MAAM,iBAAiB,uBAAuB,OAAO,wBAAwB;CAC7E,MAAM,aAAa,uBAAuB,OAAO,oBAAoB;CACrE,MAAM,cAAc,uBAAuB,OAAO,mBAAmB;CACrE,MAAM,qBAAqB,uBACzB,OACA,0BACD;CACD,MAAM,aAAa,cAAc;AAC/B,SAAO,KAAK,UACV,OAAO,QAAQ,WAAW,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,WACtD,KAAK,cAAc,MAAM,CAC1B,CACF;IACA,CAAC,WAAW,QAAQ,CAAC;CACxB,MAAM,eAAe,cAAc;AACjC,MAAI,WAAW,WACb,QAAO;AAGT,yBAAO,IAAI,MAAM,gCAAgC;IAChD,CAAC,WAAW,WAAW,CAAC;CAC3B,MAAM,YAAY,eAAe,QAAQ;CACzC,MAAM,QAAQ,gBAAgB;AAE9B,iBAAgB;AACd,QAAM,OAAO;AACb,eAAa;AACX,SAAM,MAAM;;IAEb,CAAC,MAAM,CAAC;AAEX,iBAAgB;EACd,MAAM,UAAwC,WAAW,aACrD;GACE,YAAY,WAAW;GACvB,SAAS,EAAE,GAAG,WAAW,SAAS;GAClC,OAAO,WAAW,cAAc;GAChC;GACA;GACA;GACA;GACD,GACD;AAEJ,QAAM,WAAW,QAAQ;IACxB;EACD;EACA,WAAW;EACX;EACA,WAAW,cAAc;EACzB;EACA;EACA,WAAW;EACX;EACA;EACD,CAAC;CAEF,MAAM,eAAe,aAClB,UAAkB,SAAiB,MAAM,aAAa,UAAU,KAAK,EACtE,CAAC,MAAM,CACR;CAED,MAAM,gBAAgB,aACnB,aAAqB,MAAM,cAAc,SAAS,EACnD,CAAC,MAAM,CACR;CAED,MAAM,eAAe,aAClB,aAAqB,MAAM,aAAa,SAAS,EAClD,CAAC,MAAM,CACR;AAID,QAAO;EACL;EACA;EACA;EACA;EACA;EACA,eARoB,kBAAkB,MAAM,eAAe,EAAE,CAAC,MAAM,CAAC;EASrE;EACA;EACA;EACD"}
1
+ {"version":3,"file":"use-threads.mjs","names":[],"sources":["../../src/hooks/use-threads.tsx"],"sourcesContent":["import { useCopilotKit } from \"@/providers/CopilotKitProvider\";\nimport {\n ɵcreateThreadStore,\n ɵselectThreads,\n ɵselectThreadsError,\n ɵselectThreadsIsLoading,\n ɵselectHasNextPage,\n ɵselectIsFetchingNextPage,\n type ɵThread as CoreThread,\n type ɵThreadRuntimeContext,\n type ɵThreadStore,\n} from \"@copilotkitnext/core\";\nimport {\n useCallback,\n useEffect,\n useMemo,\n useState,\n useSyncExternalStore,\n} from \"react\";\n\n/**\n * A conversation thread managed by the Intelligence platform.\n *\n * Each thread has a unique `id`, an optional human-readable `name`, and\n * timestamp fields tracking creation and update times.\n */\nexport interface Thread extends CoreThread {}\n\n/**\n * Configuration for the {@link useThreads} hook.\n *\n * Thread operations are scoped to the runtime-authenticated user and the\n * provided agent on the Intelligence platform.\n */\nexport interface UseThreadsInput {\n /** The ID of the agent whose threads to list and manage. */\n agentId: string;\n /** When `true`, archived threads are included in the list. Defaults to `false`. */\n includeArchived?: boolean;\n /** Maximum number of threads to fetch per page. When set, enables cursor-based pagination. */\n limit?: number;\n}\n\n/**\n * Return value of the {@link useThreads} hook.\n *\n * The `threads` array is kept in sync with the platform via a realtime\n * WebSocket subscription (when available) and is sorted most-recently-updated\n * first. Mutations reject with an `Error` if the platform request fails.\n */\nexport interface UseThreadsResult {\n /**\n * Threads for the current user/agent pair, sorted by most recently\n * updated first. Updated in realtime when the platform pushes metadata\n * events. Includes archived threads only when `includeArchived` is set.\n */\n threads: Thread[];\n /**\n * `true` while the initial thread list is being fetched from the platform.\n * Subsequent realtime updates do not re-enter the loading state.\n */\n isLoading: boolean;\n /**\n * The most recent error from fetching threads or executing a mutation,\n * or `null` when there is no error. Reset to `null` on the next\n * successful fetch.\n */\n error: Error | null;\n /**\n * `true` when there are more threads available to fetch via\n * {@link fetchNextPage}. Only meaningful when `limit` is set.\n */\n hasNextPage: boolean;\n /**\n * `true` while a subsequent page of threads is being fetched.\n */\n isFetchingNextPage: boolean;\n /**\n * Fetch the next page of threads. No-op when {@link hasNextPage} is\n * `false` or a page fetch is already in progress.\n */\n fetchNextPage: () => void;\n /**\n * Rename a thread on the platform.\n * Resolves when the server confirms the update; rejects on failure.\n */\n renameThread: (threadId: string, name: string) => Promise<void>;\n /**\n * Archive a thread on the platform.\n * Archived threads are excluded from subsequent list results.\n * Resolves when the server confirms the update; rejects on failure.\n */\n archiveThread: (threadId: string) => Promise<void>;\n /**\n * Permanently delete a thread from the platform.\n * This is irreversible. Resolves when the server confirms deletion;\n * rejects on failure.\n */\n deleteThread: (threadId: string) => Promise<void>;\n}\n\nfunction useThreadStoreSelector<T>(\n store: ɵThreadStore,\n selector: (state: ReturnType<ɵThreadStore[\"getState\"]>) => T,\n): T {\n return useSyncExternalStore(\n useCallback(\n (onStoreChange) => {\n const subscription = store.select(selector).subscribe(onStoreChange);\n return () => subscription.unsubscribe();\n },\n [store, selector],\n ),\n () => selector(store.getState()),\n );\n}\n\n/**\n * React hook for listing and managing Intelligence platform threads.\n *\n * On mount the hook fetches the thread list for the runtime-authenticated user\n * and the given `agentId`. When the Intelligence platform exposes a WebSocket\n * URL, it also opens a realtime subscription so the `threads` array stays\n * current without polling — thread creates, renames, archives, and deletes\n * from any client are reflected immediately.\n *\n * Mutation methods (`renameThread`, `archiveThread`, `deleteThread`) return\n * promises that resolve once the platform confirms the operation and reject\n * with an `Error` on failure.\n *\n * @param input - Agent identifier and optional list controls.\n * @returns Thread list state and stable mutation callbacks.\n *\n * @example\n * ```tsx\n * import { useThreads } from \"@copilotkitnext/react\";\n *\n * function ThreadList() {\n * const { threads, isLoading, renameThread, deleteThread } = useThreads({\n * agentId: \"agent-1\",\n * });\n *\n * if (isLoading) return <p>Loading…</p>;\n *\n * return (\n * <ul>\n * {threads.map((t) => (\n * <li key={t.id}>\n * {t.name ?? \"Untitled\"}\n * <button onClick={() => renameThread(t.id, \"New name\")}>Rename</button>\n * <button onClick={() => deleteThread(t.id)}>Delete</button>\n * </li>\n * ))}\n * </ul>\n * );\n * }\n * ```\n */\nexport function useThreads({\n agentId,\n includeArchived,\n limit,\n}: UseThreadsInput): UseThreadsResult {\n const { copilotkit } = useCopilotKit();\n\n const [store] = useState(() =>\n ɵcreateThreadStore({\n fetch: globalThis.fetch,\n }),\n );\n\n const threads = useThreadStoreSelector(store, ɵselectThreads);\n const storeIsLoading = useThreadStoreSelector(store, ɵselectThreadsIsLoading);\n const storeError = useThreadStoreSelector(store, ɵselectThreadsError);\n const hasNextPage = useThreadStoreSelector(store, ɵselectHasNextPage);\n const isFetchingNextPage = useThreadStoreSelector(\n store,\n ɵselectIsFetchingNextPage,\n );\n const headersKey = useMemo(() => {\n return JSON.stringify(\n Object.entries(copilotkit.headers ?? {}).sort(([left], [right]) =>\n left.localeCompare(right),\n ),\n );\n }, [copilotkit.headers]);\n const runtimeError = useMemo(() => {\n if (copilotkit.runtimeUrl) {\n return null;\n }\n\n return new Error(\"Runtime URL is not configured\");\n }, [copilotkit.runtimeUrl]);\n const isLoading = runtimeError ? false : storeIsLoading;\n const error = runtimeError ?? storeError;\n\n useEffect(() => {\n store.start();\n return () => {\n store.stop();\n };\n }, [store]);\n\n useEffect(() => {\n const context: ɵThreadRuntimeContext | null = copilotkit.runtimeUrl\n ? {\n runtimeUrl: copilotkit.runtimeUrl,\n headers: { ...copilotkit.headers },\n wsUrl: copilotkit.intelligence?.wsUrl,\n agentId,\n includeArchived,\n limit,\n }\n : null;\n\n store.setContext(context);\n }, [\n store,\n copilotkit.runtimeUrl,\n headersKey,\n copilotkit.intelligence?.wsUrl,\n agentId,\n copilotkit.headers,\n includeArchived,\n limit,\n ]);\n\n const renameThread = useCallback(\n (threadId: string, name: string) => store.renameThread(threadId, name),\n [store],\n );\n\n const archiveThread = useCallback(\n (threadId: string) => store.archiveThread(threadId),\n [store],\n );\n\n const deleteThread = useCallback(\n (threadId: string) => store.deleteThread(threadId),\n [store],\n );\n\n const fetchNextPage = useCallback(() => store.fetchNextPage(), [store]);\n\n return {\n threads,\n isLoading,\n error,\n hasNextPage,\n isFetchingNextPage,\n fetchNextPage,\n renameThread,\n archiveThread,\n deleteThread,\n };\n}\n"],"mappings":";;;;;AAqGA,SAAS,uBACP,OACA,UACG;AACH,QAAO,qBACL,aACG,kBAAkB;EACjB,MAAM,eAAe,MAAM,OAAO,SAAS,CAAC,UAAU,cAAc;AACpE,eAAa,aAAa,aAAa;IAEzC,CAAC,OAAO,SAAS,CAClB,QACK,SAAS,MAAM,UAAU,CAAC,CACjC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4CH,SAAgB,WAAW,EACzB,SACA,iBACA,SACoC;CACpC,MAAM,EAAE,eAAe,eAAe;CAEtC,MAAM,CAAC,SAAS,eACd,mBAAmB,EACjB,OAAO,WAAW,OACnB,CAAC,CACH;CAED,MAAM,UAAU,uBAAuB,OAAO,eAAe;CAC7D,MAAM,iBAAiB,uBAAuB,OAAO,wBAAwB;CAC7E,MAAM,aAAa,uBAAuB,OAAO,oBAAoB;CACrE,MAAM,cAAc,uBAAuB,OAAO,mBAAmB;CACrE,MAAM,qBAAqB,uBACzB,OACA,0BACD;CACD,MAAM,aAAa,cAAc;AAC/B,SAAO,KAAK,UACV,OAAO,QAAQ,WAAW,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,WACtD,KAAK,cAAc,MAAM,CAC1B,CACF;IACA,CAAC,WAAW,QAAQ,CAAC;CACxB,MAAM,eAAe,cAAc;AACjC,MAAI,WAAW,WACb,QAAO;AAGT,yBAAO,IAAI,MAAM,gCAAgC;IAChD,CAAC,WAAW,WAAW,CAAC;CAC3B,MAAM,YAAY,eAAe,QAAQ;CACzC,MAAM,QAAQ,gBAAgB;AAE9B,iBAAgB;AACd,QAAM,OAAO;AACb,eAAa;AACX,SAAM,MAAM;;IAEb,CAAC,MAAM,CAAC;AAEX,iBAAgB;EACd,MAAM,UAAwC,WAAW,aACrD;GACE,YAAY,WAAW;GACvB,SAAS,EAAE,GAAG,WAAW,SAAS;GAClC,OAAO,WAAW,cAAc;GAChC;GACA;GACA;GACD,GACD;AAEJ,QAAM,WAAW,QAAQ;IACxB;EACD;EACA,WAAW;EACX;EACA,WAAW,cAAc;EACzB;EACA,WAAW;EACX;EACA;EACD,CAAC;CAEF,MAAM,eAAe,aAClB,UAAkB,SAAiB,MAAM,aAAa,UAAU,KAAK,EACtE,CAAC,MAAM,CACR;CAED,MAAM,gBAAgB,aACnB,aAAqB,MAAM,cAAc,SAAS,EACnD,CAAC,MAAM,CACR;CAED,MAAM,eAAe,aAClB,aAAqB,MAAM,aAAa,SAAS,EAClD,CAAC,MAAM,CACR;AAID,QAAO;EACL;EACA;EACA;EACA;EACA;EACA,eARoB,kBAAkB,MAAM,eAAe,EAAE,CAAC,MAAM,CAAC;EASrE;EACA;EACA;EACD"}
package/dist/index.umd.js CHANGED
@@ -3302,6 +3302,8 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
3302
3302
  const { copilotkit } = useCopilotKit();
3303
3303
  const { agent } = useAgent({ agentId: config.agentId });
3304
3304
  const [pendingEvent, setPendingEvent] = (0, react.useState)(null);
3305
+ const pendingEventRef = (0, react.useRef)(pendingEvent);
3306
+ pendingEventRef.current = pendingEvent;
3305
3307
  const [handlerResult, setHandlerResult] = (0, react.useState)(null);
3306
3308
  (0, react.useEffect)(() => {
3307
3309
  let localInterrupt = null;
@@ -3329,10 +3331,14 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
3329
3331
  return () => subscription.unsubscribe();
3330
3332
  }, [agent]);
3331
3333
  const resolve = (0, react.useCallback)((response) => {
3334
+ var _pendingEventRef$curr;
3332
3335
  setPendingEvent(null);
3333
3336
  copilotkit.runAgent({
3334
3337
  agent,
3335
- forwardedProps: { command: { resume: response } }
3338
+ forwardedProps: { command: {
3339
+ resume: response,
3340
+ interruptEvent: (_pendingEventRef$curr = pendingEventRef.current) === null || _pendingEventRef$curr === void 0 ? void 0 : _pendingEventRef$curr.value
3341
+ } }
3336
3342
  });
3337
3343
  }, [agent, copilotkit]);
3338
3344
  (0, react.useEffect)(() => {
@@ -3407,17 +3413,17 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
3407
3413
  /**
3408
3414
  * React hook for listing and managing Intelligence platform threads.
3409
3415
  *
3410
- * On mount the hook fetches the thread list for the given `userId`/`agentId`
3411
- * pair. When the Intelligence platform exposes a WebSocket URL, it also opens
3412
- * a realtime subscription so the `threads` array stays current without
3413
- * polling — thread creates, renames, archives, and deletes from any client
3414
- * are reflected immediately.
3416
+ * On mount the hook fetches the thread list for the runtime-authenticated user
3417
+ * and the given `agentId`. When the Intelligence platform exposes a WebSocket
3418
+ * URL, it also opens a realtime subscription so the `threads` array stays
3419
+ * current without polling — thread creates, renames, archives, and deletes
3420
+ * from any client are reflected immediately.
3415
3421
  *
3416
3422
  * Mutation methods (`renameThread`, `archiveThread`, `deleteThread`) return
3417
3423
  * promises that resolve once the platform confirms the operation and reject
3418
3424
  * with an `Error` on failure.
3419
3425
  *
3420
- * @param input - User and agent identifiers that scope the thread list.
3426
+ * @param input - Agent identifier and optional list controls.
3421
3427
  * @returns Thread list state and stable mutation callbacks.
3422
3428
  *
3423
3429
  * @example
@@ -3426,7 +3432,6 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
3426
3432
  *
3427
3433
  * function ThreadList() {
3428
3434
  * const { threads, isLoading, renameThread, deleteThread } = useThreads({
3429
- * userId: "user-1",
3430
3435
  * agentId: "agent-1",
3431
3436
  * });
3432
3437
  *
@@ -3446,7 +3451,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
3446
3451
  * }
3447
3452
  * ```
3448
3453
  */
3449
- function useThreads({ userId, agentId, includeArchived, limit }) {
3454
+ function useThreads({ agentId, includeArchived, limit }) {
3450
3455
  var _copilotkit$intellige2;
3451
3456
  const { copilotkit } = useCopilotKit();
3452
3457
  const [store] = (0, react.useState)(() => (0, _copilotkitnext_core.ɵcreateThreadStore)({ fetch: globalThis.fetch }));
@@ -3477,7 +3482,6 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
3477
3482
  runtimeUrl: copilotkit.runtimeUrl,
3478
3483
  headers: { ...copilotkit.headers },
3479
3484
  wsUrl: (_copilotkit$intellige = copilotkit.intelligence) === null || _copilotkit$intellige === void 0 ? void 0 : _copilotkit$intellige.wsUrl,
3480
- userId,
3481
3485
  agentId,
3482
3486
  includeArchived,
3483
3487
  limit
@@ -3488,7 +3492,6 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
3488
3492
  copilotkit.runtimeUrl,
3489
3493
  headersKey,
3490
3494
  (_copilotkit$intellige2 = copilotkit.intelligence) === null || _copilotkit$intellige2 === void 0 ? void 0 : _copilotkit$intellige2.wsUrl,
3491
- userId,
3492
3495
  agentId,
3493
3496
  copilotkit.headers,
3494
3497
  includeArchived,