@copilotkit/react-core 1.61.0 → 1.61.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{copilotkit-BCxdKlMw.mjs → copilotkit-Be-o2UaU.mjs} +262 -128
- package/dist/copilotkit-Be-o2UaU.mjs.map +1 -0
- package/dist/{copilotkit-M1FiciGd.d.mts → copilotkit-Bpt1c_-q.d.mts} +79 -71
- package/dist/copilotkit-Bpt1c_-q.d.mts.map +1 -0
- package/dist/{copilotkit-DtPCrXXd.cjs → copilotkit-CTCjVxkH.cjs} +251 -117
- package/dist/copilotkit-CTCjVxkH.cjs.map +1 -0
- package/dist/{copilotkit-CEdu_aie.d.cts → copilotkit-ClqbUuGX.d.cts} +79 -71
- package/dist/copilotkit-ClqbUuGX.d.cts.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +188 -96
- package/dist/index.umd.js.map +1 -1
- package/dist/v2/context.d.cts +5 -1
- package/dist/v2/context.d.cts.map +1 -1
- package/dist/v2/context.d.mts +5 -1
- package/dist/v2/context.d.mts.map +1 -1
- package/dist/v2/headless.cjs +219 -102
- package/dist/v2/headless.cjs.map +1 -1
- package/dist/v2/headless.d.cts +76 -68
- package/dist/v2/headless.d.cts.map +1 -1
- package/dist/v2/headless.d.mts +76 -68
- package/dist/v2/headless.d.mts.map +1 -1
- package/dist/v2/headless.mjs +220 -103
- package/dist/v2/headless.mjs.map +1 -1
- package/dist/v2/index.cjs +1 -1
- package/dist/v2/index.d.cts +2 -2
- package/dist/v2/index.d.mts +2 -2
- package/dist/v2/index.mjs +1 -1
- package/dist/v2/index.umd.js +250 -116
- package/dist/v2/index.umd.js.map +1 -1
- package/package.json +6 -6
- package/skills/react-core/references/provider-setup.md +20 -2
- package/dist/copilotkit-BCxdKlMw.mjs.map +0 -1
- package/dist/copilotkit-CEdu_aie.d.cts.map +0 -1
- package/dist/copilotkit-DtPCrXXd.cjs.map +0 -1
- package/dist/copilotkit-M1FiciGd.d.mts.map +0 -1
package/dist/v2/context.d.cts
CHANGED
|
@@ -8,7 +8,11 @@ import { AbstractAgent } from "@ag-ui/client";
|
|
|
8
8
|
//#region src/v2/types/react-tool-call-renderer.d.ts
|
|
9
9
|
interface ReactToolCallRenderer<T = unknown> {
|
|
10
10
|
name: string;
|
|
11
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Schema describing the tool arguments. Optional — renderers registered for
|
|
13
|
+
* tools without parameters (e.g. HITL confirm dialogs) have no schema.
|
|
14
|
+
*/
|
|
15
|
+
args?: StandardSchemaV1<any, T>;
|
|
12
16
|
/**
|
|
13
17
|
* Optional agent ID to constrain this tool renderer to a specific agent.
|
|
14
18
|
* If specified, this renderer will only be used for the specified agent.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.cts","names":[],"sources":["../../src/v2/types/react-tool-call-renderer.ts","../../src/v2/types/react-activity-message-renderer.ts","../../src/v2/types/react-custom-message-renderer.ts","../../src/v2/lib/react-core.ts","../../src/v2/context.ts"],"mappings":";;;;;;;;UAGiB,qBAAA;EACf,IAAA
|
|
1
|
+
{"version":3,"file":"context.d.cts","names":[],"sources":["../../src/v2/types/react-tool-call-renderer.ts","../../src/v2/types/react-activity-message-renderer.ts","../../src/v2/types/react-custom-message-renderer.ts","../../src/v2/lib/react-core.ts","../../src/v2/context.ts"],"mappings":";;;;;;;;UAGiB,qBAAA;EACf,IAAA;;;;;EAKA,IAAA,GAAO,gBAAA,MAAsB,CAAA;EANO;;;;EAWpC,OAAA;EACA,MAAA,EAAQ,KAAA,CAAM,aAAA;IAER,IAAA;IACA,UAAA;IACA,IAAA,EAAM,OAAA,CAAQ,CAAA;IACd,MAAA,EAAQ,cAAA,CAAe,UAAA;IACvB,MAAA;EAAA;IAGA,IAAA;IACA,UAAA;IACA,IAAA,EAAM,CAAA;IACN,MAAA,EAAQ,cAAA,CAAe,SAAA;IACvB,MAAA;EAAA;IAGA,IAAA;IACA,UAAA;IACA,IAAA,EAAM,CAAA;IACN,MAAA,EAAQ,cAAA,CAAe,QAAA;IACvB,MAAA;EAAA;AAAA;;;UC/BS,4BAAA;;;;EAIf,YAAA;EDLe;;;ECSf,OAAA;EDHO;;;ECOP,OAAA,EAAS,gBAAA,MAAsB,gBAAA;EDUnB;;;ECNZ,MAAA,EAAQ,KAAA,CAAM,aAAA;IACZ,YAAA;IACA,OAAA,EAAS,gBAAA;IACT,OAAA,EAAS,eAAA;IACT,KAAA,EAAO,aAAA;EAAA;AAAA;;;KCtBC,kCAAA;AAAA,UAEK,0BAAA;EACf,OAAA;EACA,MAAA,EAAQ,KAAA,CAAM,aAAA;IACZ,OAAA,EAAS,OAAA;IACT,QAAA,EAAU,kCAAA;IACV,KAAA;IACA,YAAA;IACA,iBAAA;IACA,qBAAA;IACA,OAAA;IACA,aAAA;EAAA;AAAA;;;UCJa,yBAAA,SAAkC,oBAAA;EAEjD,eAAA,GAAkB,qBAAA;EAClB,sBAAA,GAAyB,4BAAA;EAGzB,oBAAA,GAAuB,0BAAA;AAAA;AAAA,UAGR,6BAAA,SAAsC,wBAAA;EACrD,wBAAA,IAA4B,KAAA;IAC1B,UAAA,EAAY,cAAA;IACZ,eAAA,EAAiB,qBAAA;EAAA,aACN,OAAA;EACb,yBAAA,IAA6B,KAAA;IAC3B,UAAA,EAAY,cAAA;IACZ,gBAAA,EAAkB,OAAA,CAAM,YAAA;EAAA,aACb,OAAA;AAAA;AAAA,cAGF,mBAAA,SAA4B,cAAA;EAAA,QAC/B,gBAAA;EAAA,QACA,oBAAA;EAAA,QAEA,4BAAA;EAAA,QAEA,qBAAA;EAAA,QACA,uBAAA;EAAA,QACA,iBAAA;cAEI,MAAA,EAAQ,yBAAA;EAAA,IAOhB,oBAAA,CAAA,GAAwB,QAAA,CAAS,0BAAA;EAAA,IAIjC,sBAAA,CAAA,GAA0B,QAAA,CAAS,4BAAA;EAAA,IAInC,eAAA,CAAA,GAAmB,QAAA,CAAS,qBAAA;EAmBhC,yBAAA,CACE,SAAA,EAAW,4BAAA;EAKb,uBAAA,CAAwB,SAAA,EAAW,0BAAA;EAInC,kBAAA,CAAmB,eAAA,EAAiB,qBAAA;EAMpC,qBAAA,CAAsB,KAAA,EAAO,qBAAA;EAO7B,wBAAA,CAAyB,IAAA,UAAc,OAAA;EAAA,QAQ/B,6BAAA;EAAA,IAYJ,gBAAA,CAAA,GAAoB,OAAA,CAAM,YAAA;EAI9B,mBAAA,CAAoB,OAAA,EAAS,OAAA,CAAM,YAAA;EAYnC,SAAA,CACE,UAAA,EAAY,6BAAA,GACX,0BAAA;EHnH0B;;;;;;;;;;;;;EGoIvB,8BAAA,CAAA,GAAkC,OAAA;AAAA;;;UC7IzB,sBAAA;EACf,UAAA,EAAY,mBAAA;;AJTd;;;;EIeE,oBAAA,EAAsB,WAAA;AAAA;AAAA,cAGX,SAAA,EAAW,WAAA;AAAA,cAEX,iBAAA,EAAiB,KAAA,CAAA,OAAA,CAAA,sBAAA;AAAA,cAIjB,aAAA,QAAoB,sBAAA;AAAA,cA6BpB,cAAA,EAAc,KAAA,CAAA,OAAA,CAAA,mBAAA;AAAA,cAOd,iBAAA,QAAwB,mBAAA"}
|
package/dist/v2/context.d.mts
CHANGED
|
@@ -8,7 +8,11 @@ import { AbstractAgent } from "@ag-ui/client";
|
|
|
8
8
|
//#region src/v2/types/react-tool-call-renderer.d.ts
|
|
9
9
|
interface ReactToolCallRenderer<T = unknown> {
|
|
10
10
|
name: string;
|
|
11
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Schema describing the tool arguments. Optional — renderers registered for
|
|
13
|
+
* tools without parameters (e.g. HITL confirm dialogs) have no schema.
|
|
14
|
+
*/
|
|
15
|
+
args?: StandardSchemaV1<any, T>;
|
|
12
16
|
/**
|
|
13
17
|
* Optional agent ID to constrain this tool renderer to a specific agent.
|
|
14
18
|
* If specified, this renderer will only be used for the specified agent.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.mts","names":[],"sources":["../../src/v2/types/react-tool-call-renderer.ts","../../src/v2/types/react-activity-message-renderer.ts","../../src/v2/types/react-custom-message-renderer.ts","../../src/v2/lib/react-core.ts","../../src/v2/context.ts"],"mappings":";;;;;;;;UAGiB,qBAAA;EACf,IAAA
|
|
1
|
+
{"version":3,"file":"context.d.mts","names":[],"sources":["../../src/v2/types/react-tool-call-renderer.ts","../../src/v2/types/react-activity-message-renderer.ts","../../src/v2/types/react-custom-message-renderer.ts","../../src/v2/lib/react-core.ts","../../src/v2/context.ts"],"mappings":";;;;;;;;UAGiB,qBAAA;EACf,IAAA;;;;;EAKA,IAAA,GAAO,gBAAA,MAAsB,CAAA;EANO;;;;EAWpC,OAAA;EACA,MAAA,EAAQ,KAAA,CAAM,aAAA;IAER,IAAA;IACA,UAAA;IACA,IAAA,EAAM,OAAA,CAAQ,CAAA;IACd,MAAA,EAAQ,cAAA,CAAe,UAAA;IACvB,MAAA;EAAA;IAGA,IAAA;IACA,UAAA;IACA,IAAA,EAAM,CAAA;IACN,MAAA,EAAQ,cAAA,CAAe,SAAA;IACvB,MAAA;EAAA;IAGA,IAAA;IACA,UAAA;IACA,IAAA,EAAM,CAAA;IACN,MAAA,EAAQ,cAAA,CAAe,QAAA;IACvB,MAAA;EAAA;AAAA;;;UC/BS,4BAAA;;;;EAIf,YAAA;EDLe;;;ECSf,OAAA;EDHO;;;ECOP,OAAA,EAAS,gBAAA,MAAsB,gBAAA;EDUnB;;;ECNZ,MAAA,EAAQ,KAAA,CAAM,aAAA;IACZ,YAAA;IACA,OAAA,EAAS,gBAAA;IACT,OAAA,EAAS,eAAA;IACT,KAAA,EAAO,aAAA;EAAA;AAAA;;;KCtBC,kCAAA;AAAA,UAEK,0BAAA;EACf,OAAA;EACA,MAAA,EAAQ,KAAA,CAAM,aAAA;IACZ,OAAA,EAAS,OAAA;IACT,QAAA,EAAU,kCAAA;IACV,KAAA;IACA,YAAA;IACA,iBAAA;IACA,qBAAA;IACA,OAAA;IACA,aAAA;EAAA;AAAA;;;UCJa,yBAAA,SAAkC,oBAAA;EAEjD,eAAA,GAAkB,qBAAA;EAClB,sBAAA,GAAyB,4BAAA;EAGzB,oBAAA,GAAuB,0BAAA;AAAA;AAAA,UAGR,6BAAA,SAAsC,wBAAA;EACrD,wBAAA,IAA4B,KAAA;IAC1B,UAAA,EAAY,cAAA;IACZ,eAAA,EAAiB,qBAAA;EAAA,aACN,OAAA;EACb,yBAAA,IAA6B,KAAA;IAC3B,UAAA,EAAY,cAAA;IACZ,gBAAA,EAAkB,OAAA,CAAM,YAAA;EAAA,aACb,OAAA;AAAA;AAAA,cAGF,mBAAA,SAA4B,cAAA;EAAA,QAC/B,gBAAA;EAAA,QACA,oBAAA;EAAA,QAEA,4BAAA;EAAA,QAEA,qBAAA;EAAA,QACA,uBAAA;EAAA,QACA,iBAAA;cAEI,MAAA,EAAQ,yBAAA;EAAA,IAOhB,oBAAA,CAAA,GAAwB,QAAA,CAAS,0BAAA;EAAA,IAIjC,sBAAA,CAAA,GAA0B,QAAA,CAAS,4BAAA;EAAA,IAInC,eAAA,CAAA,GAAmB,QAAA,CAAS,qBAAA;EAmBhC,yBAAA,CACE,SAAA,EAAW,4BAAA;EAKb,uBAAA,CAAwB,SAAA,EAAW,0BAAA;EAInC,kBAAA,CAAmB,eAAA,EAAiB,qBAAA;EAMpC,qBAAA,CAAsB,KAAA,EAAO,qBAAA;EAO7B,wBAAA,CAAyB,IAAA,UAAc,OAAA;EAAA,QAQ/B,6BAAA;EAAA,IAYJ,gBAAA,CAAA,GAAoB,OAAA,CAAM,YAAA;EAI9B,mBAAA,CAAoB,OAAA,EAAS,OAAA,CAAM,YAAA;EAYnC,SAAA,CACE,UAAA,EAAY,6BAAA,GACX,0BAAA;EHnH0B;;;;;;;;;;;;;EGoIvB,8BAAA,CAAA,GAAkC,OAAA;AAAA;;;UC7IzB,sBAAA;EACf,UAAA,EAAY,mBAAA;;AJTd;;;;EIeE,oBAAA,EAAsB,WAAA;AAAA;AAAA,cAGX,SAAA,EAAW,WAAA;AAAA,cAEX,iBAAA,EAAiB,KAAA,CAAA,OAAA,CAAA,sBAAA;AAAA,cAIjB,aAAA,QAAoB,sBAAA;AAAA,cA6BpB,cAAA,EAAc,KAAA,CAAA,OAAA,CAAA,mBAAA;AAAA,cAOd,iBAAA,QAAwB,mBAAA"}
|
package/dist/v2/headless.cjs
CHANGED
|
@@ -233,7 +233,7 @@ function useAgent({ agentId, updates, throttleMs } = {}) {
|
|
|
233
233
|
if (isRuntimeConfigured && (status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Disconnected || status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Connecting)) {
|
|
234
234
|
const cached = provisionalAgentCache.current.get(agentId);
|
|
235
235
|
if (cached) {
|
|
236
|
-
|
|
236
|
+
copilotkit.applyHeadersToAgent(cached);
|
|
237
237
|
return cached;
|
|
238
238
|
}
|
|
239
239
|
const provisional = new _copilotkit_core.ProxiedCopilotRuntimeAgent({
|
|
@@ -242,14 +242,14 @@ function useAgent({ agentId, updates, throttleMs } = {}) {
|
|
|
242
242
|
transport: copilotkit.runtimeTransport,
|
|
243
243
|
runtimeMode: "pending"
|
|
244
244
|
});
|
|
245
|
-
|
|
245
|
+
copilotkit.applyHeadersToAgent(provisional);
|
|
246
246
|
provisionalAgentCache.current.set(agentId, provisional);
|
|
247
247
|
return provisional;
|
|
248
248
|
}
|
|
249
249
|
if (isRuntimeConfigured && status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Error) {
|
|
250
250
|
const cached = provisionalAgentCache.current.get(agentId);
|
|
251
251
|
if (cached) {
|
|
252
|
-
|
|
252
|
+
copilotkit.applyHeadersToAgent(cached);
|
|
253
253
|
return cached;
|
|
254
254
|
}
|
|
255
255
|
const provisional = new _copilotkit_core.ProxiedCopilotRuntimeAgent({
|
|
@@ -258,7 +258,7 @@ function useAgent({ agentId, updates, throttleMs } = {}) {
|
|
|
258
258
|
transport: copilotkit.runtimeTransport,
|
|
259
259
|
runtimeMode: "pending"
|
|
260
260
|
});
|
|
261
|
-
|
|
261
|
+
copilotkit.applyHeadersToAgent(provisional);
|
|
262
262
|
provisionalAgentCache.current.set(agentId, provisional);
|
|
263
263
|
return provisional;
|
|
264
264
|
}
|
|
@@ -309,7 +309,7 @@ function useAgent({ agentId, updates, throttleMs } = {}) {
|
|
|
309
309
|
updateFlags
|
|
310
310
|
]);
|
|
311
311
|
(0, react.useEffect)(() => {
|
|
312
|
-
if (agent instanceof _ag_ui_client.HttpAgent)
|
|
312
|
+
if (agent instanceof _ag_ui_client.HttpAgent) copilotkit.applyHeadersToAgent(agent);
|
|
313
313
|
}, [agent, JSON.stringify(copilotkit.headers)]);
|
|
314
314
|
const chatConfig = useCopilotChatConfiguration();
|
|
315
315
|
const configThreadId = chatConfig?.threadId;
|
|
@@ -431,15 +431,34 @@ function useComponent(config, deps) {
|
|
|
431
431
|
function useHumanInTheLoop(tool, deps) {
|
|
432
432
|
const { copilotkit } = (0, _copilotkit_react_core_v2_context.useCopilotKit)();
|
|
433
433
|
const resolvePromiseRef = (0, react.useRef)(null);
|
|
434
|
+
const cleanupAbortRef = (0, react.useRef)(null);
|
|
434
435
|
const respond = (0, react.useCallback)(async (result) => {
|
|
435
436
|
if (resolvePromiseRef.current) {
|
|
437
|
+
cleanupAbortRef.current?.();
|
|
438
|
+
cleanupAbortRef.current = null;
|
|
436
439
|
resolvePromiseRef.current(result);
|
|
437
440
|
resolvePromiseRef.current = null;
|
|
438
441
|
}
|
|
439
442
|
}, []);
|
|
440
|
-
const handler = (0, react.useCallback)(async () => {
|
|
441
|
-
|
|
443
|
+
const handler = (0, react.useCallback)(async (_args, context) => {
|
|
444
|
+
const signal = context?.signal;
|
|
445
|
+
return new Promise((resolve, reject) => {
|
|
446
|
+
if (signal?.aborted) {
|
|
447
|
+
reject(/* @__PURE__ */ new Error("Human-in-the-loop interaction aborted"));
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
442
450
|
resolvePromiseRef.current = resolve;
|
|
451
|
+
if (signal) {
|
|
452
|
+
const onAbort = () => {
|
|
453
|
+
cleanupAbortRef.current = null;
|
|
454
|
+
resolvePromiseRef.current = null;
|
|
455
|
+
reject(/* @__PURE__ */ new Error("Human-in-the-loop interaction aborted"));
|
|
456
|
+
};
|
|
457
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
458
|
+
cleanupAbortRef.current = () => {
|
|
459
|
+
signal.removeEventListener("abort", onAbort);
|
|
460
|
+
};
|
|
461
|
+
}
|
|
443
462
|
});
|
|
444
463
|
}, []);
|
|
445
464
|
const RenderComponent = (0, react.useCallback)((props) => {
|
|
@@ -502,114 +521,165 @@ const INTERRUPT_EVENT_NAME = "on_interrupt";
|
|
|
502
521
|
function isPromiseLike(value) {
|
|
503
522
|
return (typeof value === "object" || typeof value === "function") && value !== null && typeof Reflect.get(value, "then") === "function";
|
|
504
523
|
}
|
|
524
|
+
/** Derive the legacy-compatible `event` for any pending interrupt. */
|
|
525
|
+
function toLegacyEvent(pending) {
|
|
526
|
+
if (pending.kind === "legacy") return pending.event;
|
|
527
|
+
return {
|
|
528
|
+
name: INTERRUPT_EVENT_NAME,
|
|
529
|
+
value: pending.interrupts[0]
|
|
530
|
+
};
|
|
531
|
+
}
|
|
505
532
|
/**
|
|
506
|
-
* Handles agent interrupts
|
|
507
|
-
*
|
|
508
|
-
* The hook listens to custom events on the active agent, stores interrupt payloads per run,
|
|
509
|
-
* and surfaces a render callback once the run finalizes. Call `resolve` from your UI to resume
|
|
510
|
-
* execution with user-provided data.
|
|
533
|
+
* Handles agent interrupts with optional filtering, preprocessing, and resume behavior.
|
|
511
534
|
*
|
|
512
|
-
*
|
|
513
|
-
*
|
|
514
|
-
*
|
|
515
|
-
*
|
|
516
|
-
*
|
|
517
|
-
*
|
|
518
|
-
*
|
|
519
|
-
* @param config - Interrupt configuration (renderer, optional handler/filter, and render mode).
|
|
520
|
-
* @returns When `renderInChat` is `false`, returns the interrupt element (or `null` when idle).
|
|
521
|
-
* Otherwise returns `void` and publishes the element into chat. In `render`, `result` is always
|
|
522
|
-
* either the handler's resolved return value or `null` (including when no handler is provided,
|
|
523
|
-
* when filtering skips the interrupt, or when handler execution fails).
|
|
524
|
-
*
|
|
525
|
-
* @example
|
|
526
|
-
* ```tsx
|
|
527
|
-
* import { useInterrupt } from "@copilotkit/react-core/v2";
|
|
528
|
-
*
|
|
529
|
-
* function InterruptUI() {
|
|
530
|
-
* useInterrupt({
|
|
531
|
-
* render: ({ event, resolve }) => (
|
|
532
|
-
* <div>
|
|
533
|
-
* <p>{event.value.question}</p>
|
|
534
|
-
* <button onClick={() => resolve({ approved: true })}>Approve</button>
|
|
535
|
-
* <button onClick={() => resolve({ approved: false })}>Reject</button>
|
|
536
|
-
* </div>
|
|
537
|
-
* ),
|
|
538
|
-
* });
|
|
535
|
+
* Supports both the AG-UI standard interrupt flow (`RUN_FINISHED` with
|
|
536
|
+
* `outcome.type === "interrupt"`) and the legacy custom-event flow
|
|
537
|
+
* (`on_interrupt`). For standard interrupts, `render` receives `interrupt`
|
|
538
|
+
* (the primary one) and `interrupts` (the full open set); call `resolve(payload)`
|
|
539
|
+
* to resume or `cancel()` to cancel. Resuming addresses the targeted interrupt
|
|
540
|
+
* and, once every open interrupt is addressed, submits a single spec `resume`
|
|
541
|
+
* array via `copilotkit.runAgent`.
|
|
539
542
|
*
|
|
540
|
-
*
|
|
541
|
-
*
|
|
542
|
-
* ```
|
|
543
|
+
* - `renderInChat: true` (default): the element is published into `<CopilotChat>`; returns `void`.
|
|
544
|
+
* - `renderInChat: false`: the hook returns the interrupt element for manual placement.
|
|
543
545
|
*
|
|
544
546
|
* @example
|
|
545
547
|
* ```tsx
|
|
546
|
-
*
|
|
547
|
-
*
|
|
548
|
-
*
|
|
549
|
-
*
|
|
550
|
-
*
|
|
551
|
-
*
|
|
552
|
-
*
|
|
553
|
-
*
|
|
554
|
-
*
|
|
555
|
-
* <strong>{result?.label ?? ""}</strong>
|
|
556
|
-
* <button onClick={() => resolve({ value: event.value })}>Continue</button>
|
|
557
|
-
* </aside>
|
|
558
|
-
* ),
|
|
559
|
-
* });
|
|
560
|
-
*
|
|
561
|
-
* return <>{interruptElement}</>;
|
|
562
|
-
* }
|
|
548
|
+
* useInterrupt({
|
|
549
|
+
* render: ({ interrupt, resolve, cancel }) => (
|
|
550
|
+
* <div>
|
|
551
|
+
* <p>{interrupt?.message}</p>
|
|
552
|
+
* <button onClick={() => resolve({ approved: true })}>Approve</button>
|
|
553
|
+
* <button onClick={() => cancel()}>Cancel</button>
|
|
554
|
+
* </div>
|
|
555
|
+
* ),
|
|
556
|
+
* });
|
|
563
557
|
* ```
|
|
564
558
|
*/
|
|
565
559
|
function useInterrupt(config) {
|
|
566
560
|
const { copilotkit } = (0, _copilotkit_react_core_v2_context.useCopilotKit)();
|
|
567
561
|
const { agent } = useAgent({ agentId: config.agentId });
|
|
568
|
-
const [
|
|
569
|
-
const
|
|
570
|
-
|
|
562
|
+
const [pending, setPending] = (0, react.useState)(null);
|
|
563
|
+
const pendingRef = (0, react.useRef)(pending);
|
|
564
|
+
pendingRef.current = pending;
|
|
571
565
|
const [handlerResult, setHandlerResult] = (0, react.useState)(null);
|
|
566
|
+
const responsesRef = (0, react.useRef)({});
|
|
572
567
|
(0, react.useEffect)(() => {
|
|
573
|
-
let
|
|
568
|
+
let localLegacy = null;
|
|
569
|
+
let localStandard = null;
|
|
574
570
|
const subscription = agent.subscribe({
|
|
575
571
|
onCustomEvent: ({ event }) => {
|
|
576
|
-
if (event.name === INTERRUPT_EVENT_NAME)
|
|
572
|
+
if (event.name === INTERRUPT_EVENT_NAME) localLegacy = {
|
|
577
573
|
name: event.name,
|
|
578
574
|
value: event.value
|
|
579
575
|
};
|
|
580
576
|
},
|
|
577
|
+
onRunFinishedEvent: (params) => {
|
|
578
|
+
if (params.outcome === "interrupt") localStandard = params.interrupts;
|
|
579
|
+
},
|
|
581
580
|
onRunStartedEvent: () => {
|
|
582
|
-
|
|
583
|
-
|
|
581
|
+
localLegacy = null;
|
|
582
|
+
localStandard = null;
|
|
583
|
+
responsesRef.current = {};
|
|
584
|
+
setPending(null);
|
|
584
585
|
},
|
|
585
586
|
onRunFinalized: () => {
|
|
586
|
-
if (
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
}
|
|
587
|
+
if (localStandard && localStandard.length > 0) setPending({
|
|
588
|
+
kind: "standard",
|
|
589
|
+
interrupts: localStandard
|
|
590
|
+
});
|
|
591
|
+
else if (localLegacy) setPending({
|
|
592
|
+
kind: "legacy",
|
|
593
|
+
event: localLegacy
|
|
594
|
+
});
|
|
595
|
+
localLegacy = null;
|
|
596
|
+
localStandard = null;
|
|
590
597
|
},
|
|
591
598
|
onRunFailed: () => {
|
|
592
|
-
|
|
593
|
-
|
|
599
|
+
localLegacy = null;
|
|
600
|
+
localStandard = null;
|
|
601
|
+
responsesRef.current = {};
|
|
602
|
+
setPending(null);
|
|
594
603
|
}
|
|
595
604
|
});
|
|
596
605
|
return () => subscription.unsubscribe();
|
|
597
606
|
}, [agent]);
|
|
598
|
-
const
|
|
607
|
+
const submitStandardIfComplete = (0, react.useCallback)(async (interrupts) => {
|
|
608
|
+
if (!interrupts.every((i) => responsesRef.current[i.id])) return;
|
|
609
|
+
const expired = interrupts.find((i) => (0, _ag_ui_client.isInterruptExpired)(i));
|
|
610
|
+
if (expired) {
|
|
611
|
+
console.error(`[CopilotKit] useInterrupt: interrupt ${expired.id} expired at ${expired.expiresAt}; not resuming.`);
|
|
612
|
+
responsesRef.current = {};
|
|
613
|
+
setPending(null);
|
|
614
|
+
return;
|
|
615
|
+
}
|
|
616
|
+
const resume = (0, _ag_ui_client.buildResumeArray)(interrupts, responsesRef.current);
|
|
617
|
+
for (const i of interrupts) {
|
|
618
|
+
if (!i.toolCallId) continue;
|
|
619
|
+
const response = responsesRef.current[i.id];
|
|
620
|
+
const content = response.status === "cancelled" ? { status: "cancelled" } : response.payload ?? { status: "resolved" };
|
|
621
|
+
agent.addMessage({
|
|
622
|
+
id: (0, _ag_ui_client.randomUUID)(),
|
|
623
|
+
role: "tool",
|
|
624
|
+
toolCallId: i.toolCallId,
|
|
625
|
+
content: JSON.stringify(content)
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
responsesRef.current = {};
|
|
599
629
|
try {
|
|
630
|
+
return await copilotkit.runAgent({
|
|
631
|
+
agent,
|
|
632
|
+
resume
|
|
633
|
+
});
|
|
634
|
+
} catch (err) {
|
|
635
|
+
console.error("[CopilotKit] useInterrupt resolve: runAgent rejected; clearing pending + rethrowing", err);
|
|
636
|
+
setPending(null);
|
|
637
|
+
throw err;
|
|
638
|
+
}
|
|
639
|
+
}, [agent, copilotkit]);
|
|
640
|
+
const resolve = (0, react.useCallback)(async (payload, interruptId) => {
|
|
641
|
+
const current = pendingRef.current;
|
|
642
|
+
if (!current) return;
|
|
643
|
+
if (current.kind === "legacy") try {
|
|
600
644
|
return await copilotkit.runAgent({
|
|
601
645
|
agent,
|
|
602
646
|
forwardedProps: { command: {
|
|
603
|
-
resume:
|
|
604
|
-
interruptEvent:
|
|
647
|
+
resume: payload,
|
|
648
|
+
interruptEvent: current.event.value
|
|
605
649
|
} }
|
|
606
650
|
});
|
|
607
651
|
} catch (err) {
|
|
608
652
|
console.error("[CopilotKit] useInterrupt resolve: runAgent rejected; clearing pending + rethrowing", err);
|
|
609
|
-
|
|
653
|
+
setPending(null);
|
|
610
654
|
throw err;
|
|
611
655
|
}
|
|
612
|
-
|
|
656
|
+
if (current.interrupts.length > 1 && interruptId === void 0) console.warn(`[CopilotKit] useInterrupt: resolve()/cancel() called without an interruptId while ${current.interrupts.length} interrupts are open; defaulting to the first. Pass an interruptId to address a specific interrupt.`);
|
|
657
|
+
const id = interruptId ?? current.interrupts[0]?.id;
|
|
658
|
+
if (!id) return;
|
|
659
|
+
responsesRef.current[id] = {
|
|
660
|
+
status: "resolved",
|
|
661
|
+
payload
|
|
662
|
+
};
|
|
663
|
+
return submitStandardIfComplete(current.interrupts);
|
|
664
|
+
}, [
|
|
665
|
+
agent,
|
|
666
|
+
copilotkit,
|
|
667
|
+
submitStandardIfComplete
|
|
668
|
+
]);
|
|
669
|
+
const cancel = (0, react.useCallback)(async (interruptId) => {
|
|
670
|
+
const current = pendingRef.current;
|
|
671
|
+
if (!current) return;
|
|
672
|
+
if (current.kind === "legacy") {
|
|
673
|
+
console.warn("[CopilotKit] useInterrupt: cancel() is not supported for legacy on_interrupt interrupts; dismissing.");
|
|
674
|
+
setPending(null);
|
|
675
|
+
return;
|
|
676
|
+
}
|
|
677
|
+
if (current.interrupts.length > 1 && interruptId === void 0) console.warn(`[CopilotKit] useInterrupt: resolve()/cancel() called without an interruptId while ${current.interrupts.length} interrupts are open; defaulting to the first. Pass an interruptId to address a specific interrupt.`);
|
|
678
|
+
const id = interruptId ?? current.interrupts[0]?.id;
|
|
679
|
+
if (!id) return;
|
|
680
|
+
responsesRef.current[id] = { status: "cancelled" };
|
|
681
|
+
return submitStandardIfComplete(current.interrupts);
|
|
682
|
+
}, [submitStandardIfComplete]);
|
|
613
683
|
const renderRef = (0, react.useRef)(config.render);
|
|
614
684
|
renderRef.current = config.render;
|
|
615
685
|
const enabledRef = (0, react.useRef)(config.enabled);
|
|
@@ -618,6 +688,8 @@ function useInterrupt(config) {
|
|
|
618
688
|
handlerRef.current = config.handler;
|
|
619
689
|
const resolveRef = (0, react.useRef)(resolve);
|
|
620
690
|
resolveRef.current = resolve;
|
|
691
|
+
const cancelRef = (0, react.useRef)(cancel);
|
|
692
|
+
cancelRef.current = cancel;
|
|
621
693
|
const isEnabled = (event) => {
|
|
622
694
|
const predicate = enabledRef.current;
|
|
623
695
|
if (!predicate) return true;
|
|
@@ -629,11 +701,12 @@ function useInterrupt(config) {
|
|
|
629
701
|
}
|
|
630
702
|
};
|
|
631
703
|
(0, react.useEffect)(() => {
|
|
632
|
-
if (!
|
|
704
|
+
if (!pending) {
|
|
633
705
|
setHandlerResult(null);
|
|
634
706
|
return;
|
|
635
707
|
}
|
|
636
|
-
|
|
708
|
+
const legacyEvent = toLegacyEvent(pending);
|
|
709
|
+
if (!isEnabled(legacyEvent)) {
|
|
637
710
|
setHandlerResult(null);
|
|
638
711
|
return;
|
|
639
712
|
}
|
|
@@ -646,8 +719,11 @@ function useInterrupt(config) {
|
|
|
646
719
|
let maybePromise;
|
|
647
720
|
try {
|
|
648
721
|
maybePromise = handler({
|
|
649
|
-
event:
|
|
650
|
-
|
|
722
|
+
event: legacyEvent,
|
|
723
|
+
interrupt: pending.kind === "standard" ? pending.interrupts[0] : null,
|
|
724
|
+
interrupts: pending.kind === "standard" ? pending.interrupts : [],
|
|
725
|
+
resolve: resolveRef.current,
|
|
726
|
+
cancel: cancelRef.current
|
|
651
727
|
});
|
|
652
728
|
} catch (err) {
|
|
653
729
|
console.error("[CopilotKit] useInterrupt handler threw; result will be null:", err);
|
|
@@ -666,19 +742,24 @@ function useInterrupt(config) {
|
|
|
666
742
|
return () => {
|
|
667
743
|
cancelled = true;
|
|
668
744
|
};
|
|
669
|
-
}, [
|
|
745
|
+
}, [pending]);
|
|
670
746
|
const element = (0, react.useMemo)(() => {
|
|
671
|
-
if (!
|
|
672
|
-
|
|
747
|
+
if (!pending) return null;
|
|
748
|
+
const legacyEvent = toLegacyEvent(pending);
|
|
749
|
+
if (!isEnabled(legacyEvent)) return null;
|
|
673
750
|
return renderRef.current({
|
|
674
|
-
event:
|
|
751
|
+
event: legacyEvent,
|
|
752
|
+
interrupt: pending.kind === "standard" ? pending.interrupts[0] : null,
|
|
753
|
+
interrupts: pending.kind === "standard" ? pending.interrupts : [],
|
|
675
754
|
result: handlerResult,
|
|
676
|
-
resolve
|
|
755
|
+
resolve,
|
|
756
|
+
cancel
|
|
677
757
|
});
|
|
678
758
|
}, [
|
|
679
|
-
|
|
759
|
+
pending,
|
|
680
760
|
handlerResult,
|
|
681
|
-
resolve
|
|
761
|
+
resolve,
|
|
762
|
+
cancel
|
|
682
763
|
]);
|
|
683
764
|
(0, react.useEffect)(() => {
|
|
684
765
|
if (config.renderInChat === false) return;
|
|
@@ -951,9 +1032,9 @@ function useThreadStoreSelector(store, selector) {
|
|
|
951
1032
|
* current without polling — thread creates, renames, archives, and deletes
|
|
952
1033
|
* from any client are reflected immediately.
|
|
953
1034
|
*
|
|
954
|
-
* Mutation methods (`renameThread`, `archiveThread`, `
|
|
955
|
-
* promises that resolve once the platform confirms the
|
|
956
|
-
* with an `Error` on failure.
|
|
1035
|
+
* Mutation methods (`renameThread`, `archiveThread`, `unarchiveThread`,
|
|
1036
|
+
* `deleteThread`) return promises that resolve once the platform confirms the
|
|
1037
|
+
* operation and reject with an `Error` on failure.
|
|
957
1038
|
*
|
|
958
1039
|
* @param input - Agent identifier and optional list controls.
|
|
959
1040
|
* @returns Thread list state and stable mutation callbacks.
|
|
@@ -1003,21 +1084,32 @@ function useThreads({ agentId, includeArchived, limit }) {
|
|
|
1003
1084
|
const headersKey = (0, react.useMemo)(() => {
|
|
1004
1085
|
return JSON.stringify(Object.entries(copilotkit.headers ?? {}).sort(([left], [right]) => left.localeCompare(right)));
|
|
1005
1086
|
}, [copilotkit.headers]);
|
|
1087
|
+
const runtimeStatus = copilotkit.runtimeConnectionStatus;
|
|
1088
|
+
const threadListEndpointSupported = copilotkit.threadEndpoints?.list !== false;
|
|
1089
|
+
const threadMutationsSupported = copilotkit.threadEndpoints?.mutations !== false;
|
|
1090
|
+
const threadEndpointsUnavailable = !!copilotkit.runtimeUrl && runtimeStatus === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Connected && !threadListEndpointSupported;
|
|
1006
1091
|
const runtimeError = (0, react.useMemo)(() => {
|
|
1007
1092
|
if (copilotkit.runtimeUrl) return null;
|
|
1008
1093
|
return /* @__PURE__ */ new Error("Runtime URL is not configured");
|
|
1009
1094
|
}, [copilotkit.runtimeUrl]);
|
|
1095
|
+
const threadEndpointsError = (0, react.useMemo)(() => {
|
|
1096
|
+
if (!threadEndpointsUnavailable) return null;
|
|
1097
|
+
return /* @__PURE__ */ new Error("Thread endpoints are not available on this CopilotKit runtime");
|
|
1098
|
+
}, [threadEndpointsUnavailable]);
|
|
1099
|
+
const threadMutationsError = (0, react.useMemo)(() => {
|
|
1100
|
+
if (threadMutationsSupported) return null;
|
|
1101
|
+
return /* @__PURE__ */ new Error("Thread mutations are not available on this CopilotKit runtime");
|
|
1102
|
+
}, [threadMutationsSupported]);
|
|
1010
1103
|
const [hasDispatchedContext, setHasDispatchedContext] = (0, react.useState)(false);
|
|
1011
|
-
const preConnectLoading = !!copilotkit.runtimeUrl && !hasDispatchedContext;
|
|
1012
|
-
const isLoading = runtimeError ? false : preConnectLoading || storeIsLoading;
|
|
1013
|
-
const error = runtimeError ?? storeError;
|
|
1104
|
+
const preConnectLoading = !!copilotkit.runtimeUrl && !threadEndpointsUnavailable && !hasDispatchedContext;
|
|
1105
|
+
const isLoading = runtimeError || threadEndpointsError ? false : preConnectLoading || storeIsLoading;
|
|
1106
|
+
const error = runtimeError ?? threadEndpointsError ?? storeError;
|
|
1014
1107
|
(0, react.useEffect)(() => {
|
|
1015
1108
|
store.start();
|
|
1016
1109
|
return () => {
|
|
1017
1110
|
store.stop();
|
|
1018
1111
|
};
|
|
1019
1112
|
}, [store]);
|
|
1020
|
-
const runtimeStatus = copilotkit.runtimeConnectionStatus;
|
|
1021
1113
|
(0, react.useEffect)(() => {
|
|
1022
1114
|
copilotkit.registerThreadStore(agentId, store);
|
|
1023
1115
|
return () => {
|
|
@@ -1031,9 +1123,15 @@ function useThreads({ agentId, includeArchived, limit }) {
|
|
|
1031
1123
|
(0, react.useEffect)(() => {
|
|
1032
1124
|
if (!copilotkit.runtimeUrl) {
|
|
1033
1125
|
store.setContext(null);
|
|
1126
|
+
setHasDispatchedContext(false);
|
|
1034
1127
|
return;
|
|
1035
1128
|
}
|
|
1036
1129
|
if (runtimeStatus !== _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Connected) return;
|
|
1130
|
+
if (!threadListEndpointSupported) {
|
|
1131
|
+
store.setContext(null);
|
|
1132
|
+
setHasDispatchedContext(false);
|
|
1133
|
+
return;
|
|
1134
|
+
}
|
|
1037
1135
|
const context = {
|
|
1038
1136
|
runtimeUrl: copilotkit.runtimeUrl,
|
|
1039
1137
|
headers: { ...copilotkit.headers },
|
|
@@ -1050,13 +1148,21 @@ function useThreads({ agentId, includeArchived, limit }) {
|
|
|
1050
1148
|
runtimeStatus,
|
|
1051
1149
|
headersKey,
|
|
1052
1150
|
copilotkit.intelligence?.wsUrl,
|
|
1151
|
+
threadListEndpointSupported,
|
|
1053
1152
|
agentId,
|
|
1054
1153
|
includeArchived,
|
|
1055
1154
|
limit
|
|
1056
1155
|
]);
|
|
1057
|
-
const
|
|
1058
|
-
|
|
1059
|
-
|
|
1156
|
+
const guardMutation = (0, react.useCallback)((mutation) => {
|
|
1157
|
+
return (...args) => {
|
|
1158
|
+
if (threadMutationsError) return Promise.reject(threadMutationsError);
|
|
1159
|
+
return mutation(...args);
|
|
1160
|
+
};
|
|
1161
|
+
}, [threadMutationsError]);
|
|
1162
|
+
const renameThread = (0, react.useMemo)(() => guardMutation((threadId, name) => store.renameThread(threadId, name)), [store, guardMutation]);
|
|
1163
|
+
const archiveThread = (0, react.useMemo)(() => guardMutation((threadId) => store.archiveThread(threadId)), [store, guardMutation]);
|
|
1164
|
+
const unarchiveThread = (0, react.useMemo)(() => guardMutation((threadId) => store.unarchiveThread(threadId)), [store, guardMutation]);
|
|
1165
|
+
const deleteThread = (0, react.useMemo)(() => guardMutation((threadId) => store.deleteThread(threadId)), [store, guardMutation]);
|
|
1060
1166
|
return {
|
|
1061
1167
|
threads,
|
|
1062
1168
|
isLoading,
|
|
@@ -1066,6 +1172,7 @@ function useThreads({ agentId, includeArchived, limit }) {
|
|
|
1066
1172
|
fetchMoreThreads: (0, react.useCallback)(() => store.fetchNextPage(), [store]),
|
|
1067
1173
|
renameThread,
|
|
1068
1174
|
archiveThread,
|
|
1175
|
+
unarchiveThread,
|
|
1069
1176
|
deleteThread
|
|
1070
1177
|
};
|
|
1071
1178
|
}
|
|
@@ -1140,10 +1247,20 @@ function useRenderTool(config, deps) {
|
|
|
1140
1247
|
}) : defineToolCallRenderer({
|
|
1141
1248
|
name: config.name,
|
|
1142
1249
|
args: config.parameters,
|
|
1143
|
-
render: (props) =>
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1250
|
+
render: (props) => {
|
|
1251
|
+
if (props.status === _copilotkit_core.ToolCallStatus.InProgress) return config.render({
|
|
1252
|
+
...props,
|
|
1253
|
+
parameters: props.args
|
|
1254
|
+
});
|
|
1255
|
+
if (props.status === _copilotkit_core.ToolCallStatus.Executing) return config.render({
|
|
1256
|
+
...props,
|
|
1257
|
+
parameters: props.args
|
|
1258
|
+
});
|
|
1259
|
+
return config.render({
|
|
1260
|
+
...props,
|
|
1261
|
+
parameters: props.args
|
|
1262
|
+
});
|
|
1263
|
+
},
|
|
1147
1264
|
...config.agentId ? { agentId: config.agentId } : {}
|
|
1148
1265
|
});
|
|
1149
1266
|
copilotkit.addHookRenderToolCall(renderer);
|