@copilotkit/react-core 1.55.3-canary.1776243725 → 1.55.3-canary.1776979102
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-opur-20s.d.mts → copilotkit-3mXoM0Hd.d.mts} +9 -29
- package/dist/copilotkit-3mXoM0Hd.d.mts.map +1 -0
- package/dist/{copilotkit-EfopO2gn.d.cts → copilotkit-BDDjvB-p.d.cts} +9 -29
- package/dist/copilotkit-BDDjvB-p.d.cts.map +1 -0
- package/dist/{copilotkit-BoOnQHlE.cjs → copilotkit-BkcqmpWt.cjs} +162 -280
- package/dist/copilotkit-BkcqmpWt.cjs.map +1 -0
- package/dist/{copilotkit-Bm4ox8G0.mjs → copilotkit-C7n8Umv9.mjs} +164 -276
- package/dist/copilotkit-C7n8Umv9.mjs.map +1 -0
- package/dist/index.cjs +4 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +4 -9
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +143 -230
- package/dist/index.umd.js.map +1 -1
- package/dist/v2/index.cjs +1 -2
- package/dist/v2/index.d.cts +2 -2
- package/dist/v2/index.d.mts +2 -2
- package/dist/v2/index.mjs +2 -2
- package/dist/v2/index.umd.js +165 -279
- package/dist/v2/index.umd.js.map +1 -1
- package/package.json +6 -6
- package/src/components/copilot-provider/copilot-messages.tsx +24 -39
- package/src/components/copilot-provider/copilotkit-props.tsx +5 -9
- package/src/components/copilot-provider/copilotkit.tsx +1 -4
- package/src/hooks/__tests__/use-copilot-chat-internal-connect.test.tsx +16 -27
- package/src/hooks/use-copilot-chat_internal.ts +4 -15
- package/src/v2/__tests__/utils/test-helpers.tsx +7 -40
- package/src/v2/components/chat/CopilotChat.tsx +1 -1
- package/src/v2/components/chat/CopilotChatAssistantMessage.tsx +15 -18
- package/src/v2/components/chat/CopilotChatMessageView.tsx +2 -7
- package/src/v2/components/chat/CopilotChatReasoningMessage.tsx +4 -17
- package/src/v2/components/chat/CopilotChatUserMessage.tsx +10 -13
- package/src/v2/components/chat/__tests__/CopilotChat.e2e.test.tsx +5 -131
- package/src/v2/components/chat/__tests__/CopilotChatActivityRendering.e2e.test.tsx +0 -60
- package/src/v2/components/chat/__tests__/CopilotChatAssistantMessage.test.tsx +1 -1
- package/src/v2/components/chat/__tests__/CopilotChatToolRendering.e2e.test.tsx +2 -5
- package/src/v2/components/chat/__tests__/CopilotChatToolRerenders.e2e.test.tsx +2 -5
- package/src/v2/components/chat/__tests__/MCPAppsActivityRenderer.e2e.test.tsx +1 -55
- package/src/v2/hooks/__tests__/use-agent-context-timing.e2e.test.tsx +0 -8
- package/src/v2/hooks/__tests__/use-agent-throttle.test.tsx +10 -10
- package/src/v2/hooks/__tests__/use-agent.e2e.test.tsx +2 -13
- package/src/v2/hooks/__tests__/use-frontend-tool.e2e.test.tsx +4 -23
- package/src/v2/hooks/index.ts +0 -1
- package/src/v2/hooks/use-agent.tsx +10 -157
- package/src/v2/hooks/use-render-activity-message.tsx +3 -9
- package/src/v2/hooks/use-render-custom-messages.tsx +1 -6
- package/src/v2/providers/CopilotKitProvider.tsx +2 -6
- package/dist/copilotkit-Bm4ox8G0.mjs.map +0 -1
- package/dist/copilotkit-BoOnQHlE.cjs.map +0 -1
- package/dist/copilotkit-EfopO2gn.d.cts.map +0 -1
- package/dist/copilotkit-opur-20s.d.mts.map +0 -1
- package/src/components/copilot-provider/__tests__/error-visibility-prod.test.tsx +0 -70
- package/src/v2/components/chat/__tests__/CopilotChatCopyButton.clipboard.test.tsx +0 -241
- package/src/v2/hooks/__tests__/use-agent-thread-isolation.test.tsx +0 -327
- package/src/v2/hooks/__tests__/use-capabilities.test.tsx +0 -76
- package/src/v2/hooks/use-capabilities.tsx +0 -25
|
@@ -4,7 +4,7 @@ import { CopilotKitCore, CopilotKitCoreRuntimeConnectionStatus, ProxiedCopilotRu
|
|
|
4
4
|
import { HttpAgent } from "@ag-ui/client";
|
|
5
5
|
import { extendTailwindMerge, twMerge } from "tailwind-merge";
|
|
6
6
|
import { ArrowUp, Check, ChevronDown, ChevronLeft, ChevronRight, ChevronRightIcon, Copy, Edit, Loader2, MessageCircle, Mic, Play, Plus, RefreshCw, Square, ThumbsDown, ThumbsUp, Upload, Volume2, X } from "lucide-react";
|
|
7
|
-
import { A2UI_DEFAULT_DESIGN_GUIDELINES, A2UI_DEFAULT_GENERATION_GUIDELINES, COPILOT_CLOUD_API_URL, COPILOT_CLOUD_CHAT_URL, COPILOT_CLOUD_PUBLIC_API_KEY_HEADER, ConfigurationError, CopilotKitAgentDiscoveryError, CopilotKitApiDiscoveryError, CopilotKitError, CopilotKitErrorCode, CopilotKitLowLevelError, CopilotKitRemoteEndpointDiscoveryError, DEFAULT_AGENT_ID, ErrorVisibility, MissingPublicApiKeyError, Severity, TranscriptionErrorCode, TranscriptionErrorCode as TranscriptionErrorCode$1,
|
|
7
|
+
import { A2UI_DEFAULT_DESIGN_GUIDELINES, A2UI_DEFAULT_GENERATION_GUIDELINES, COPILOT_CLOUD_API_URL, COPILOT_CLOUD_CHAT_URL, COPILOT_CLOUD_PUBLIC_API_KEY_HEADER, ConfigurationError, CopilotKitAgentDiscoveryError, CopilotKitApiDiscoveryError, CopilotKitError, CopilotKitErrorCode, CopilotKitLowLevelError, CopilotKitRemoteEndpointDiscoveryError, DEFAULT_AGENT_ID, ErrorVisibility, MissingPublicApiKeyError, Severity, TranscriptionErrorCode, TranscriptionErrorCode as TranscriptionErrorCode$1, createLicenseContextValue, dataToUUID, exceedsMaxSize, formatFileSize, generateVideoThumbnail, getDocumentIcon, getModalityFromMimeType, getSourceUrl, matchesAcceptFilter, parseJson, partialJSONParse, randomId, randomUUID, readFileAsBase64, schemaToJsonSchema } from "@copilotkit/shared";
|
|
8
8
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
9
9
|
import { Slot } from "@radix-ui/react-slot";
|
|
10
10
|
import { cva } from "class-variance-authority";
|
|
@@ -3042,7 +3042,7 @@ function useStableArrayProp(prop, warningMessage, isMeaningfulChange) {
|
|
|
3042
3042
|
}, [value, warningMessage]);
|
|
3043
3043
|
return value;
|
|
3044
3044
|
}
|
|
3045
|
-
const CopilotKitProvider = ({ children, runtimeUrl, headers
|
|
3045
|
+
const CopilotKitProvider = ({ children, runtimeUrl, headers = {}, credentials, publicApiKey, publicLicenseKey, licenseToken, properties = {}, agents__unsafe_dev_only: agents = {}, selfManagedAgents = {}, renderToolCalls, renderActivityMessages, renderCustomMessages, frontendTools, humanInTheLoop, openGenerativeUI, showDevConsole = false, useSingleEndpoint, onError, a2ui, defaultThrottleMs, inspectorDefaultAnchor }) => {
|
|
3046
3046
|
const [shouldRenderInspector, setShouldRenderInspector] = useState(false);
|
|
3047
3047
|
const [runtimeA2UIEnabled, setRuntimeA2UIEnabled] = useState(false);
|
|
3048
3048
|
const [runtimeOpenGenUIEnabled, setRuntimeOpenGenUIEnabled] = useState(false);
|
|
@@ -3097,7 +3097,6 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = {}, c
|
|
|
3097
3097
|
...selfManagedAgents
|
|
3098
3098
|
}), [agents, selfManagedAgents]);
|
|
3099
3099
|
const hasLocalAgents = mergedAgents && Object.keys(mergedAgents).length > 0;
|
|
3100
|
-
const headers = typeof headersProp === "function" ? headersProp() : headersProp;
|
|
3101
3100
|
const mergedHeaders = useMemo(() => {
|
|
3102
3101
|
if (!resolvedPublicKey) return headers;
|
|
3103
3102
|
if (headers[HEADER_NAME]) return headers;
|
|
@@ -3455,200 +3454,6 @@ function useRenderToolCall() {
|
|
|
3455
3454
|
]);
|
|
3456
3455
|
}
|
|
3457
3456
|
|
|
3458
|
-
//#endregion
|
|
3459
|
-
//#region src/v2/hooks/use-agent.tsx
|
|
3460
|
-
let UseAgentUpdate = /* @__PURE__ */ function(UseAgentUpdate) {
|
|
3461
|
-
UseAgentUpdate["OnMessagesChanged"] = "OnMessagesChanged";
|
|
3462
|
-
UseAgentUpdate["OnStateChanged"] = "OnStateChanged";
|
|
3463
|
-
UseAgentUpdate["OnRunStatusChanged"] = "OnRunStatusChanged";
|
|
3464
|
-
return UseAgentUpdate;
|
|
3465
|
-
}({});
|
|
3466
|
-
const ALL_UPDATES = [
|
|
3467
|
-
UseAgentUpdate.OnMessagesChanged,
|
|
3468
|
-
UseAgentUpdate.OnStateChanged,
|
|
3469
|
-
UseAgentUpdate.OnRunStatusChanged
|
|
3470
|
-
];
|
|
3471
|
-
/**
|
|
3472
|
-
* Clone a registry agent for per-thread isolation.
|
|
3473
|
-
* Copies agent configuration (transport, headers, etc.) but resets conversation
|
|
3474
|
-
* state (messages, threadId, state) so each thread starts fresh.
|
|
3475
|
-
*/
|
|
3476
|
-
function cloneForThread(source, threadId, headers) {
|
|
3477
|
-
const clone = source.clone();
|
|
3478
|
-
if (clone === source) throw new Error(`useAgent: ${source.constructor.name}.clone() returned the same instance. clone() must return a new, independent object.`);
|
|
3479
|
-
clone.threadId = threadId;
|
|
3480
|
-
clone.setMessages([]);
|
|
3481
|
-
clone.setState({});
|
|
3482
|
-
if (clone instanceof HttpAgent) clone.headers = { ...headers };
|
|
3483
|
-
return clone;
|
|
3484
|
-
}
|
|
3485
|
-
/**
|
|
3486
|
-
* Module-level WeakMap: registryAgent → (threadId → clone).
|
|
3487
|
-
* Shared across all useAgent() calls so that every component using the same
|
|
3488
|
-
* (agentId, threadId) pair receives the same agent instance. Using WeakMap
|
|
3489
|
-
* ensures the clone map is garbage-collected when the registry agent is
|
|
3490
|
-
* replaced (e.g. after reconnect or hot-reload).
|
|
3491
|
-
*/
|
|
3492
|
-
const globalThreadCloneMap = /* @__PURE__ */ new WeakMap();
|
|
3493
|
-
/**
|
|
3494
|
-
* Look up an existing per-thread clone without creating one.
|
|
3495
|
-
* Returns undefined when no clone has been created yet for this pair.
|
|
3496
|
-
*/
|
|
3497
|
-
function getThreadClone(registryAgent, threadId) {
|
|
3498
|
-
if (!registryAgent || !threadId) return void 0;
|
|
3499
|
-
return globalThreadCloneMap.get(registryAgent)?.get(threadId);
|
|
3500
|
-
}
|
|
3501
|
-
function getOrCreateThreadClone(existing, threadId, headers) {
|
|
3502
|
-
let byThread = globalThreadCloneMap.get(existing);
|
|
3503
|
-
if (!byThread) {
|
|
3504
|
-
byThread = /* @__PURE__ */ new Map();
|
|
3505
|
-
globalThreadCloneMap.set(existing, byThread);
|
|
3506
|
-
}
|
|
3507
|
-
const cached = byThread.get(threadId);
|
|
3508
|
-
if (cached) return cached;
|
|
3509
|
-
const clone = cloneForThread(existing, threadId, headers);
|
|
3510
|
-
byThread.set(threadId, clone);
|
|
3511
|
-
return clone;
|
|
3512
|
-
}
|
|
3513
|
-
function useAgent({ agentId, threadId, updates, throttleMs } = {}) {
|
|
3514
|
-
agentId ??= DEFAULT_AGENT_ID;
|
|
3515
|
-
const { copilotkit } = useCopilotKit();
|
|
3516
|
-
const providerThrottleMs = copilotkit.defaultThrottleMs;
|
|
3517
|
-
const chatConfig = useCopilotChatConfiguration();
|
|
3518
|
-
threadId ??= chatConfig?.threadId;
|
|
3519
|
-
const effectiveThrottleMs = useMemo(() => {
|
|
3520
|
-
const resolved = throttleMs ?? providerThrottleMs ?? 0;
|
|
3521
|
-
if (!Number.isFinite(resolved) || resolved < 0) {
|
|
3522
|
-
const source = throttleMs !== void 0 ? "hook-level throttleMs" : "provider-level defaultThrottleMs";
|
|
3523
|
-
console.error(`useAgent: ${source} must be a non-negative finite number, got ${resolved}. Falling back to unthrottled.`);
|
|
3524
|
-
return 0;
|
|
3525
|
-
}
|
|
3526
|
-
return resolved;
|
|
3527
|
-
}, [throttleMs, providerThrottleMs]);
|
|
3528
|
-
const [, forceUpdate] = useReducer((x) => x + 1, 0);
|
|
3529
|
-
const updateFlags = useMemo(() => updates ?? ALL_UPDATES, [JSON.stringify(updates)]);
|
|
3530
|
-
const provisionalAgentCache = useRef(/* @__PURE__ */ new Map());
|
|
3531
|
-
const agent = useMemo(() => {
|
|
3532
|
-
const cacheKey = threadId ? `${agentId}:${threadId}` : agentId;
|
|
3533
|
-
const existing = copilotkit.getAgent(agentId);
|
|
3534
|
-
if (existing) {
|
|
3535
|
-
provisionalAgentCache.current.delete(cacheKey);
|
|
3536
|
-
provisionalAgentCache.current.delete(agentId);
|
|
3537
|
-
if (!threadId) return existing;
|
|
3538
|
-
return getOrCreateThreadClone(existing, threadId, copilotkit.headers);
|
|
3539
|
-
}
|
|
3540
|
-
const isRuntimeConfigured = copilotkit.runtimeUrl !== void 0;
|
|
3541
|
-
const status = copilotkit.runtimeConnectionStatus;
|
|
3542
|
-
if (isRuntimeConfigured && (status === CopilotKitCoreRuntimeConnectionStatus.Disconnected || status === CopilotKitCoreRuntimeConnectionStatus.Connecting)) {
|
|
3543
|
-
const cached = provisionalAgentCache.current.get(cacheKey);
|
|
3544
|
-
if (cached) {
|
|
3545
|
-
cached.headers = { ...copilotkit.headers };
|
|
3546
|
-
return cached;
|
|
3547
|
-
}
|
|
3548
|
-
const provisional = new ProxiedCopilotRuntimeAgent({
|
|
3549
|
-
runtimeUrl: copilotkit.runtimeUrl,
|
|
3550
|
-
agentId,
|
|
3551
|
-
transport: copilotkit.runtimeTransport,
|
|
3552
|
-
runtimeMode: "pending"
|
|
3553
|
-
});
|
|
3554
|
-
provisional.headers = { ...copilotkit.headers };
|
|
3555
|
-
if (threadId) provisional.threadId = threadId;
|
|
3556
|
-
provisionalAgentCache.current.set(cacheKey, provisional);
|
|
3557
|
-
return provisional;
|
|
3558
|
-
}
|
|
3559
|
-
if (isRuntimeConfigured && status === CopilotKitCoreRuntimeConnectionStatus.Error) {
|
|
3560
|
-
const cached = provisionalAgentCache.current.get(cacheKey);
|
|
3561
|
-
if (cached) {
|
|
3562
|
-
cached.headers = { ...copilotkit.headers };
|
|
3563
|
-
return cached;
|
|
3564
|
-
}
|
|
3565
|
-
const provisional = new ProxiedCopilotRuntimeAgent({
|
|
3566
|
-
runtimeUrl: copilotkit.runtimeUrl,
|
|
3567
|
-
agentId,
|
|
3568
|
-
transport: copilotkit.runtimeTransport,
|
|
3569
|
-
runtimeMode: "pending"
|
|
3570
|
-
});
|
|
3571
|
-
provisional.headers = { ...copilotkit.headers };
|
|
3572
|
-
if (threadId) provisional.threadId = threadId;
|
|
3573
|
-
provisionalAgentCache.current.set(cacheKey, provisional);
|
|
3574
|
-
return provisional;
|
|
3575
|
-
}
|
|
3576
|
-
const knownAgents = Object.keys(copilotkit.agents ?? {});
|
|
3577
|
-
const runtimePart = isRuntimeConfigured ? `runtimeUrl=${copilotkit.runtimeUrl}` : "no runtimeUrl";
|
|
3578
|
-
throw new Error(`useAgent: Agent '${agentId}' not found after runtime sync (${runtimePart}). ` + (knownAgents.length ? `Known agents: [${knownAgents.join(", ")}]` : "No agents registered.") + " Verify your runtime /info and/or agents__unsafe_dev_only.");
|
|
3579
|
-
}, [
|
|
3580
|
-
agentId,
|
|
3581
|
-
threadId,
|
|
3582
|
-
copilotkit.agents,
|
|
3583
|
-
copilotkit.runtimeConnectionStatus,
|
|
3584
|
-
copilotkit.runtimeUrl,
|
|
3585
|
-
copilotkit.runtimeTransport,
|
|
3586
|
-
JSON.stringify(copilotkit.headers)
|
|
3587
|
-
]);
|
|
3588
|
-
useEffect(() => {
|
|
3589
|
-
if (updateFlags.length === 0) return;
|
|
3590
|
-
const handlers = {};
|
|
3591
|
-
let timerId = null;
|
|
3592
|
-
let active = true;
|
|
3593
|
-
let batchScheduled = false;
|
|
3594
|
-
const batchedForceUpdate = () => {
|
|
3595
|
-
if (!active) return;
|
|
3596
|
-
if (!batchScheduled) {
|
|
3597
|
-
batchScheduled = true;
|
|
3598
|
-
queueMicrotask(() => {
|
|
3599
|
-
batchScheduled = false;
|
|
3600
|
-
if (active) forceUpdate();
|
|
3601
|
-
});
|
|
3602
|
-
}
|
|
3603
|
-
};
|
|
3604
|
-
if (updateFlags.includes(UseAgentUpdate.OnMessagesChanged)) {
|
|
3605
|
-
const ms = effectiveThrottleMs;
|
|
3606
|
-
if (ms > 0) {
|
|
3607
|
-
let throttleActive = false;
|
|
3608
|
-
let pending = false;
|
|
3609
|
-
const throttledNotify = () => {
|
|
3610
|
-
if (!active) return;
|
|
3611
|
-
if (!throttleActive) {
|
|
3612
|
-
throttleActive = true;
|
|
3613
|
-
pending = false;
|
|
3614
|
-
forceUpdate();
|
|
3615
|
-
timerId = setTimeout(function trailingEdge() {
|
|
3616
|
-
timerId = null;
|
|
3617
|
-
if (active && pending) {
|
|
3618
|
-
pending = false;
|
|
3619
|
-
forceUpdate();
|
|
3620
|
-
timerId = setTimeout(trailingEdge, ms);
|
|
3621
|
-
} else throttleActive = false;
|
|
3622
|
-
}, ms);
|
|
3623
|
-
} else pending = true;
|
|
3624
|
-
};
|
|
3625
|
-
handlers.onMessagesChanged = throttledNotify;
|
|
3626
|
-
} else handlers.onMessagesChanged = forceUpdate;
|
|
3627
|
-
}
|
|
3628
|
-
if (updateFlags.includes(UseAgentUpdate.OnStateChanged)) handlers.onStateChanged = batchedForceUpdate;
|
|
3629
|
-
if (updateFlags.includes(UseAgentUpdate.OnRunStatusChanged)) {
|
|
3630
|
-
handlers.onRunInitialized = batchedForceUpdate;
|
|
3631
|
-
handlers.onRunFinalized = batchedForceUpdate;
|
|
3632
|
-
handlers.onRunFailed = batchedForceUpdate;
|
|
3633
|
-
}
|
|
3634
|
-
const subscription = agent.subscribe(handlers);
|
|
3635
|
-
return () => {
|
|
3636
|
-
active = false;
|
|
3637
|
-
if (timerId !== null) clearTimeout(timerId);
|
|
3638
|
-
subscription.unsubscribe();
|
|
3639
|
-
};
|
|
3640
|
-
}, [
|
|
3641
|
-
agent,
|
|
3642
|
-
forceUpdate,
|
|
3643
|
-
effectiveThrottleMs,
|
|
3644
|
-
updateFlags
|
|
3645
|
-
]);
|
|
3646
|
-
useEffect(() => {
|
|
3647
|
-
if (agent instanceof HttpAgent) agent.headers = { ...copilotkit.headers };
|
|
3648
|
-
}, [agent, JSON.stringify(copilotkit.headers)]);
|
|
3649
|
-
return { agent };
|
|
3650
|
-
}
|
|
3651
|
-
|
|
3652
3457
|
//#endregion
|
|
3653
3458
|
//#region src/v2/hooks/use-render-custom-messages.tsx
|
|
3654
3459
|
function useRenderCustomMessages() {
|
|
@@ -3666,8 +3471,7 @@ function useRenderCustomMessages() {
|
|
|
3666
3471
|
const { message, position } = params;
|
|
3667
3472
|
const resolvedRunId = copilotkit.getRunIdForMessage(agentId, threadId, message.id) ?? copilotkit.getRunIdsForThread(agentId, threadId).slice(-1)[0];
|
|
3668
3473
|
const runId = resolvedRunId ?? `missing-run-id:${message.id}`;
|
|
3669
|
-
const
|
|
3670
|
-
const agent = getThreadClone(registryAgent, threadId) ?? registryAgent;
|
|
3474
|
+
const agent = copilotkit.getAgent(agentId);
|
|
3671
3475
|
if (!agent) throw new Error("Agent not found");
|
|
3672
3476
|
const messagesIdsInRun = resolvedRunId ? agent.messages.filter((msg) => copilotkit.getRunIdForMessage(agentId, threadId, msg.id) === resolvedRunId).map((msg) => msg.id) : [message.id];
|
|
3673
3477
|
const rawMessageIndex = agent.messages.findIndex((msg) => msg.id === message.id);
|
|
@@ -3699,8 +3503,7 @@ function useRenderCustomMessages() {
|
|
|
3699
3503
|
//#region src/v2/hooks/use-render-activity-message.tsx
|
|
3700
3504
|
function useRenderActivityMessage() {
|
|
3701
3505
|
const { copilotkit } = useCopilotKit();
|
|
3702
|
-
const
|
|
3703
|
-
const agentId = config?.agentId ?? DEFAULT_AGENT_ID;
|
|
3506
|
+
const agentId = useCopilotChatConfiguration()?.agentId ?? DEFAULT_AGENT_ID;
|
|
3704
3507
|
const renderers = copilotkit.renderActivityMessages;
|
|
3705
3508
|
const findRenderer = useCallback((activityType) => {
|
|
3706
3509
|
if (!renderers.length) return null;
|
|
@@ -3716,8 +3519,7 @@ function useRenderActivityMessage() {
|
|
|
3716
3519
|
return null;
|
|
3717
3520
|
}
|
|
3718
3521
|
const Component = renderer.render;
|
|
3719
|
-
const
|
|
3720
|
-
const agent = getThreadClone(registryAgent, config?.threadId) ?? registryAgent;
|
|
3522
|
+
const agent = copilotkit.getAgent(agentId);
|
|
3721
3523
|
return /* @__PURE__ */ jsx(Component, {
|
|
3722
3524
|
activityType: message.activityType,
|
|
3723
3525
|
content: parseResult.data,
|
|
@@ -3726,7 +3528,6 @@ function useRenderActivityMessage() {
|
|
|
3726
3528
|
}, message.id);
|
|
3727
3529
|
}, [
|
|
3728
3530
|
agentId,
|
|
3729
|
-
config?.threadId,
|
|
3730
3531
|
copilotkit,
|
|
3731
3532
|
findRenderer
|
|
3732
3533
|
]);
|
|
@@ -4167,21 +3968,127 @@ function useHumanInTheLoop(tool, deps) {
|
|
|
4167
3968
|
}
|
|
4168
3969
|
|
|
4169
3970
|
//#endregion
|
|
4170
|
-
//#region src/v2/hooks/use-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
function
|
|
4183
|
-
|
|
4184
|
-
|
|
3971
|
+
//#region src/v2/hooks/use-agent.tsx
|
|
3972
|
+
let UseAgentUpdate = /* @__PURE__ */ function(UseAgentUpdate) {
|
|
3973
|
+
UseAgentUpdate["OnMessagesChanged"] = "OnMessagesChanged";
|
|
3974
|
+
UseAgentUpdate["OnStateChanged"] = "OnStateChanged";
|
|
3975
|
+
UseAgentUpdate["OnRunStatusChanged"] = "OnRunStatusChanged";
|
|
3976
|
+
return UseAgentUpdate;
|
|
3977
|
+
}({});
|
|
3978
|
+
const ALL_UPDATES = [
|
|
3979
|
+
UseAgentUpdate.OnMessagesChanged,
|
|
3980
|
+
UseAgentUpdate.OnStateChanged,
|
|
3981
|
+
UseAgentUpdate.OnRunStatusChanged
|
|
3982
|
+
];
|
|
3983
|
+
function useAgent({ agentId, updates, throttleMs } = {}) {
|
|
3984
|
+
agentId ??= DEFAULT_AGENT_ID;
|
|
3985
|
+
const { copilotkit } = useCopilotKit();
|
|
3986
|
+
const providerThrottleMs = copilotkit.defaultThrottleMs;
|
|
3987
|
+
const effectiveThrottleMs = useMemo(() => {
|
|
3988
|
+
const resolved = throttleMs ?? providerThrottleMs ?? 0;
|
|
3989
|
+
if (!Number.isFinite(resolved) || resolved < 0) {
|
|
3990
|
+
const source = throttleMs !== void 0 ? "hook-level throttleMs" : "provider-level defaultThrottleMs";
|
|
3991
|
+
console.error(`useAgent: ${source} must be a non-negative finite number, got ${resolved}. Falling back to unthrottled.`);
|
|
3992
|
+
return 0;
|
|
3993
|
+
}
|
|
3994
|
+
return resolved;
|
|
3995
|
+
}, [throttleMs, providerThrottleMs]);
|
|
3996
|
+
const [, forceUpdate] = useReducer((x) => x + 1, 0);
|
|
3997
|
+
const updateFlags = useMemo(() => updates ?? ALL_UPDATES, [JSON.stringify(updates)]);
|
|
3998
|
+
const provisionalAgentCache = useRef(/* @__PURE__ */ new Map());
|
|
3999
|
+
const agent = useMemo(() => {
|
|
4000
|
+
const existing = copilotkit.getAgent(agentId);
|
|
4001
|
+
if (existing) {
|
|
4002
|
+
provisionalAgentCache.current.delete(agentId);
|
|
4003
|
+
return existing;
|
|
4004
|
+
}
|
|
4005
|
+
const isRuntimeConfigured = copilotkit.runtimeUrl !== void 0;
|
|
4006
|
+
const status = copilotkit.runtimeConnectionStatus;
|
|
4007
|
+
if (isRuntimeConfigured && (status === CopilotKitCoreRuntimeConnectionStatus.Disconnected || status === CopilotKitCoreRuntimeConnectionStatus.Connecting)) {
|
|
4008
|
+
const cached = provisionalAgentCache.current.get(agentId);
|
|
4009
|
+
if (cached) {
|
|
4010
|
+
cached.headers = { ...copilotkit.headers };
|
|
4011
|
+
return cached;
|
|
4012
|
+
}
|
|
4013
|
+
const provisional = new ProxiedCopilotRuntimeAgent({
|
|
4014
|
+
runtimeUrl: copilotkit.runtimeUrl,
|
|
4015
|
+
agentId,
|
|
4016
|
+
transport: copilotkit.runtimeTransport,
|
|
4017
|
+
runtimeMode: "pending"
|
|
4018
|
+
});
|
|
4019
|
+
provisional.headers = { ...copilotkit.headers };
|
|
4020
|
+
provisionalAgentCache.current.set(agentId, provisional);
|
|
4021
|
+
return provisional;
|
|
4022
|
+
}
|
|
4023
|
+
if (isRuntimeConfigured && status === CopilotKitCoreRuntimeConnectionStatus.Error) {
|
|
4024
|
+
const provisional = new ProxiedCopilotRuntimeAgent({
|
|
4025
|
+
runtimeUrl: copilotkit.runtimeUrl,
|
|
4026
|
+
agentId,
|
|
4027
|
+
transport: copilotkit.runtimeTransport,
|
|
4028
|
+
runtimeMode: "pending"
|
|
4029
|
+
});
|
|
4030
|
+
provisional.headers = { ...copilotkit.headers };
|
|
4031
|
+
return provisional;
|
|
4032
|
+
}
|
|
4033
|
+
const knownAgents = Object.keys(copilotkit.agents ?? {});
|
|
4034
|
+
const runtimePart = isRuntimeConfigured ? `runtimeUrl=${copilotkit.runtimeUrl}` : "no runtimeUrl";
|
|
4035
|
+
throw new Error(`useAgent: Agent '${agentId}' not found after runtime sync (${runtimePart}). ` + (knownAgents.length ? `Known agents: [${knownAgents.join(", ")}]` : "No agents registered.") + " Verify your runtime /info and/or agents__unsafe_dev_only.");
|
|
4036
|
+
}, [
|
|
4037
|
+
agentId,
|
|
4038
|
+
copilotkit.agents,
|
|
4039
|
+
copilotkit.runtimeConnectionStatus,
|
|
4040
|
+
copilotkit.runtimeUrl,
|
|
4041
|
+
copilotkit.runtimeTransport,
|
|
4042
|
+
JSON.stringify(copilotkit.headers)
|
|
4043
|
+
]);
|
|
4044
|
+
useEffect(() => {
|
|
4045
|
+
if (updateFlags.length === 0) return;
|
|
4046
|
+
const handlers = {};
|
|
4047
|
+
let timerId = null;
|
|
4048
|
+
let active = true;
|
|
4049
|
+
if (updateFlags.includes(UseAgentUpdate.OnMessagesChanged)) {
|
|
4050
|
+
const ms = effectiveThrottleMs;
|
|
4051
|
+
if (ms > 0) {
|
|
4052
|
+
let throttleActive = false;
|
|
4053
|
+
let pending = false;
|
|
4054
|
+
const throttledNotify = () => {
|
|
4055
|
+
if (!active) return;
|
|
4056
|
+
if (!throttleActive) {
|
|
4057
|
+
throttleActive = true;
|
|
4058
|
+
pending = false;
|
|
4059
|
+
forceUpdate();
|
|
4060
|
+
timerId = setTimeout(function trailingEdge() {
|
|
4061
|
+
timerId = null;
|
|
4062
|
+
if (active && pending) {
|
|
4063
|
+
pending = false;
|
|
4064
|
+
forceUpdate();
|
|
4065
|
+
timerId = setTimeout(trailingEdge, ms);
|
|
4066
|
+
} else throttleActive = false;
|
|
4067
|
+
}, ms);
|
|
4068
|
+
} else pending = true;
|
|
4069
|
+
};
|
|
4070
|
+
handlers.onMessagesChanged = throttledNotify;
|
|
4071
|
+
} else handlers.onMessagesChanged = forceUpdate;
|
|
4072
|
+
}
|
|
4073
|
+
if (updateFlags.includes(UseAgentUpdate.OnStateChanged)) handlers.onStateChanged = forceUpdate;
|
|
4074
|
+
if (updateFlags.includes(UseAgentUpdate.OnRunStatusChanged)) {
|
|
4075
|
+
handlers.onRunInitialized = forceUpdate;
|
|
4076
|
+
handlers.onRunFinalized = forceUpdate;
|
|
4077
|
+
handlers.onRunFailed = forceUpdate;
|
|
4078
|
+
}
|
|
4079
|
+
const subscription = agent.subscribe(handlers);
|
|
4080
|
+
return () => {
|
|
4081
|
+
active = false;
|
|
4082
|
+
if (timerId !== null) clearTimeout(timerId);
|
|
4083
|
+
subscription.unsubscribe();
|
|
4084
|
+
};
|
|
4085
|
+
}, [
|
|
4086
|
+
agent,
|
|
4087
|
+
forceUpdate,
|
|
4088
|
+
effectiveThrottleMs,
|
|
4089
|
+
updateFlags
|
|
4090
|
+
]);
|
|
4091
|
+
return { agent };
|
|
4185
4092
|
}
|
|
4186
4093
|
|
|
4187
4094
|
//#endregion
|
|
@@ -4835,8 +4742,11 @@ function CopilotChatAssistantMessage({ message, messages, isRunning, onThumbsUp,
|
|
|
4835
4742
|
useKatexStyles();
|
|
4836
4743
|
const boundMarkdownRenderer = renderSlot(markdownRenderer, CopilotChatAssistantMessage.MarkdownRenderer, { content: message.content || "" });
|
|
4837
4744
|
const boundCopyButton = renderSlot(copyButton, CopilotChatAssistantMessage.CopyButton, { onClick: async () => {
|
|
4838
|
-
if (message.content)
|
|
4839
|
-
|
|
4745
|
+
if (message.content) try {
|
|
4746
|
+
await navigator.clipboard.writeText(message.content);
|
|
4747
|
+
} catch (err) {
|
|
4748
|
+
console.error("Failed to copy message:", err);
|
|
4749
|
+
}
|
|
4840
4750
|
} });
|
|
4841
4751
|
const boundThumbsUpButton = renderSlot(thumbsUpButton, CopilotChatAssistantMessage.ThumbsUpButton, { onClick: onThumbsUp });
|
|
4842
4752
|
const boundThumbsDownButton = renderSlot(thumbsDownButton, CopilotChatAssistantMessage.ThumbsDownButton, { onClick: onThumbsDown });
|
|
@@ -4934,17 +4844,14 @@ function CopilotChatAssistantMessage({ message, messages, isRunning, onThumbsUp,
|
|
|
4934
4844
|
if (timerRef.current !== null) clearTimeout(timerRef.current);
|
|
4935
4845
|
};
|
|
4936
4846
|
}, []);
|
|
4937
|
-
const handleClick =
|
|
4938
|
-
|
|
4939
|
-
if (
|
|
4940
|
-
|
|
4941
|
-
|
|
4942
|
-
|
|
4943
|
-
|
|
4944
|
-
|
|
4945
|
-
setCopied(false);
|
|
4946
|
-
}, 2e3);
|
|
4947
|
-
}
|
|
4847
|
+
const handleClick = (event) => {
|
|
4848
|
+
setCopied(true);
|
|
4849
|
+
if (timerRef.current !== null) clearTimeout(timerRef.current);
|
|
4850
|
+
timerRef.current = setTimeout(() => {
|
|
4851
|
+
timerRef.current = null;
|
|
4852
|
+
setCopied(false);
|
|
4853
|
+
}, 2e3);
|
|
4854
|
+
if (onClick) onClick(event);
|
|
4948
4855
|
};
|
|
4949
4856
|
return /* @__PURE__ */ jsx(ToolbarButton, {
|
|
4950
4857
|
"data-testid": "copilot-copy-button",
|
|
@@ -5097,8 +5004,11 @@ function CopilotChatUserMessage({ message, onEditMessage, branchIndex, numberOfB
|
|
|
5097
5004
|
const mediaParts = useMemo(() => getMediaParts(message.content), [message.content]);
|
|
5098
5005
|
const BoundMessageRenderer = renderSlot(messageRenderer, CopilotChatUserMessage.MessageRenderer, { content: flattenedContent });
|
|
5099
5006
|
const BoundCopyButton = renderSlot(copyButton, CopilotChatUserMessage.CopyButton, { onClick: async () => {
|
|
5100
|
-
if (flattenedContent)
|
|
5101
|
-
|
|
5007
|
+
if (flattenedContent) try {
|
|
5008
|
+
await navigator.clipboard.writeText(flattenedContent);
|
|
5009
|
+
} catch (err) {
|
|
5010
|
+
console.error("Failed to copy message:", err);
|
|
5011
|
+
}
|
|
5102
5012
|
} });
|
|
5103
5013
|
const BoundEditButton = renderSlot(editButton, CopilotChatUserMessage.EditButton, { onClick: () => onEditMessage?.({ message }) });
|
|
5104
5014
|
const BoundBranchNavigation = renderSlot(branchNavigation, CopilotChatUserMessage.BranchNavigation, {
|
|
@@ -5186,13 +5096,10 @@ function CopilotChatUserMessage({ message, onEditMessage, branchIndex, numberOfB
|
|
|
5186
5096
|
_CopilotChatUserMessage.CopyButton = ({ className, title, onClick, ...props }) => {
|
|
5187
5097
|
const labels = useCopilotChatConfiguration()?.labels ?? CopilotChatDefaultLabels;
|
|
5188
5098
|
const [copied, setCopied] = useState(false);
|
|
5189
|
-
const handleClick =
|
|
5190
|
-
|
|
5191
|
-
|
|
5192
|
-
if (
|
|
5193
|
-
setCopied(true);
|
|
5194
|
-
setTimeout(() => setCopied(false), 2e3);
|
|
5195
|
-
}
|
|
5099
|
+
const handleClick = (event) => {
|
|
5100
|
+
setCopied(true);
|
|
5101
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
5102
|
+
if (onClick) onClick(event);
|
|
5196
5103
|
};
|
|
5197
5104
|
return /* @__PURE__ */ jsx(ToolbarButton, {
|
|
5198
5105
|
"data-testid": "copilot-user-copy-button",
|
|
@@ -5299,24 +5206,17 @@ function CopilotChatReasoningMessage({ message, messages, isRunning, header, con
|
|
|
5299
5206
|
return () => clearInterval(timer);
|
|
5300
5207
|
}, [isStreaming]);
|
|
5301
5208
|
const [isOpen, setIsOpen] = useState(isStreaming);
|
|
5302
|
-
const userToggledRef = useRef(false);
|
|
5303
5209
|
useEffect(() => {
|
|
5304
|
-
if (isStreaming)
|
|
5305
|
-
|
|
5306
|
-
setIsOpen(true);
|
|
5307
|
-
} else if (!userToggledRef.current) setIsOpen(false);
|
|
5210
|
+
if (isStreaming) setIsOpen(true);
|
|
5211
|
+
else setIsOpen(false);
|
|
5308
5212
|
}, [isStreaming]);
|
|
5309
|
-
const handleToggle = hasContent ? () => {
|
|
5310
|
-
userToggledRef.current = true;
|
|
5311
|
-
setIsOpen((prev) => !prev);
|
|
5312
|
-
} : void 0;
|
|
5313
5213
|
const label = isStreaming ? "Thinking…" : `Thought for ${formatDuration(elapsed)}`;
|
|
5314
5214
|
const boundHeader = renderSlot(header, CopilotChatReasoningMessage.Header, {
|
|
5315
5215
|
isOpen,
|
|
5316
5216
|
label,
|
|
5317
5217
|
hasContent,
|
|
5318
5218
|
isStreaming,
|
|
5319
|
-
onClick:
|
|
5219
|
+
onClick: hasContent ? () => setIsOpen((prev) => !prev) : void 0
|
|
5320
5220
|
});
|
|
5321
5221
|
const boundContent = renderSlot(contentView, CopilotChatReasoningMessage.Content, {
|
|
5322
5222
|
isStreaming,
|
|
@@ -5663,14 +5563,12 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
|
|
|
5663
5563
|
const [, forceUpdate] = useReducer((x) => x + 1, 0);
|
|
5664
5564
|
useEffect(() => {
|
|
5665
5565
|
if (!config?.agentId) return;
|
|
5666
|
-
const
|
|
5667
|
-
const agent = getThreadClone(registryAgent, config.threadId) ?? registryAgent;
|
|
5566
|
+
const agent = copilotkit.getAgent(config.agentId);
|
|
5668
5567
|
if (!agent) return;
|
|
5669
5568
|
const subscription = agent.subscribe({ onStateChanged: forceUpdate });
|
|
5670
5569
|
return () => subscription.unsubscribe();
|
|
5671
5570
|
}, [
|
|
5672
5571
|
config?.agentId,
|
|
5673
|
-
config?.threadId,
|
|
5674
5572
|
copilotkit,
|
|
5675
5573
|
forceUpdate
|
|
5676
5574
|
]);
|
|
@@ -6610,7 +6508,6 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
|
|
|
6610
6508
|
const resolvedThreadId = useMemo(() => threadId ?? existingConfig?.threadId ?? randomUUID(), [threadId, existingConfig?.threadId]);
|
|
6611
6509
|
const { agent } = useAgent({
|
|
6612
6510
|
agentId: resolvedAgentId,
|
|
6613
|
-
threadId: resolvedThreadId,
|
|
6614
6511
|
throttleMs
|
|
6615
6512
|
});
|
|
6616
6513
|
const { copilotkit } = useCopilotKit();
|
|
@@ -6657,6 +6554,7 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
|
|
|
6657
6554
|
console.error("CopilotChat: connectAgent failed", error);
|
|
6658
6555
|
}
|
|
6659
6556
|
};
|
|
6557
|
+
agent.threadId = resolvedThreadId;
|
|
6660
6558
|
connect(agent);
|
|
6661
6559
|
return () => {
|
|
6662
6560
|
detached = true;
|
|
@@ -8020,20 +7918,6 @@ function shouldShowDevConsole(showDevConsole) {
|
|
|
8020
7918
|
/**
|
|
8021
7919
|
* An internal context to separate the messages state (which is constantly changing) from the rest of CopilotKit context
|
|
8022
7920
|
*/
|
|
8023
|
-
/**
|
|
8024
|
-
* Determine whether a GraphQL error should be suppressed based on its visibility
|
|
8025
|
-
* and whether the dev console is active.
|
|
8026
|
-
*
|
|
8027
|
-
* Returns `null` when the error should be surfaced to the UI, or a log prefix
|
|
8028
|
-
* string when the error should be suppressed (logged to console only).
|
|
8029
|
-
*
|
|
8030
|
-
* Exported for unit testing.
|
|
8031
|
-
*/
|
|
8032
|
-
function getErrorSuppression(visibility, isDev) {
|
|
8033
|
-
if (visibility === ErrorVisibility.SILENT) return "CopilotKit Silent Error:";
|
|
8034
|
-
if (!isDev && visibility === ErrorVisibility.DEV_ONLY) return "CopilotKit Error (hidden in production):";
|
|
8035
|
-
return null;
|
|
8036
|
-
}
|
|
8037
7921
|
const MessagesTapContext = createContext(null);
|
|
8038
7922
|
function useMessagesTap() {
|
|
8039
7923
|
const tap = useContext(MessagesTapContext);
|
|
@@ -8117,9 +8001,12 @@ function CopilotMessages({ children }) {
|
|
|
8117
8001
|
const graphQLErrors = error.graphQLErrors;
|
|
8118
8002
|
const routeError = (gqlError) => {
|
|
8119
8003
|
const visibility = gqlError.extensions?.visibility;
|
|
8120
|
-
|
|
8121
|
-
|
|
8122
|
-
|
|
8004
|
+
if (!shouldShowDevConsole(showDevConsole)) {
|
|
8005
|
+
console.error("CopilotKit Error (hidden in production):", gqlError.message);
|
|
8006
|
+
return;
|
|
8007
|
+
}
|
|
8008
|
+
if (visibility === ErrorVisibility.SILENT) {
|
|
8009
|
+
console.error("CopilotKit Silent Error:", gqlError.message);
|
|
8123
8010
|
return;
|
|
8124
8011
|
}
|
|
8125
8012
|
const ckError = createStructuredError(gqlError);
|
|
@@ -8136,7 +8023,8 @@ function CopilotMessages({ children }) {
|
|
|
8136
8023
|
}
|
|
8137
8024
|
};
|
|
8138
8025
|
graphQLErrors.forEach(routeError);
|
|
8139
|
-
} else
|
|
8026
|
+
} else if (!shouldShowDevConsole(showDevConsole)) console.error("CopilotKit Error (hidden in production):", error);
|
|
8027
|
+
else {
|
|
8140
8028
|
const fallbackError = new CopilotKitError({
|
|
8141
8029
|
message: error?.message || String(error),
|
|
8142
8030
|
code: CopilotKitErrorCode.UNKNOWN
|
|
@@ -9203,7 +9091,7 @@ function CopilotKitInternal(cpkProps) {
|
|
|
9203
9091
|
publicApiKey,
|
|
9204
9092
|
...cloud ? { cloud } : {},
|
|
9205
9093
|
chatApiEndpoint,
|
|
9206
|
-
headers:
|
|
9094
|
+
headers: props.headers || {},
|
|
9207
9095
|
properties: props.properties || {},
|
|
9208
9096
|
transcribeAudioUrl: props.transcribeAudioUrl,
|
|
9209
9097
|
textToSpeechUrl: props.textToSpeechUrl,
|
|
@@ -9549,5 +9437,5 @@ function validateProps(props) {
|
|
|
9549
9437
|
}
|
|
9550
9438
|
|
|
9551
9439
|
//#endregion
|
|
9552
|
-
export {
|
|
9553
|
-
//# sourceMappingURL=copilotkit-
|
|
9440
|
+
export { useCopilotKit as $, CopilotChatSuggestionView as A, useConfigureSuggestions as B, CopilotChatToggleButton as C, CopilotChatView_default as D, CopilotChat as E, CopilotChatAssistantMessage_default as F, useDefaultRenderTool as G, UseAgentUpdate as H, CopilotChatToolCallsView as I, useFrontendTool as J, useRenderTool as K, useAttachments as L, CopilotChatReasoningMessage_default as M, CopilotChatUserMessage_default as N, CopilotChatAttachmentQueue as O, CopilotChatAttachmentRenderer as P, CopilotKitProvider as Q, useThreads$1 as R, CopilotModalHeader as S, DefaultOpenIcon as T, useAgent as U, useSuggestions as V, useHumanInTheLoop as W, useRenderCustomMessages as X, useRenderActivityMessage as Y, useRenderToolCall as Z, WildcardToolCallRender as _, ThreadsProvider as a, useSandboxFunctions as at, CopilotPopupView as b, CoAgentStateRendersProvider as c, MCPAppsActivityType as ct, shouldShowDevConsole as d, AudioRecorderError as dt, CopilotKitCoreReact as et, useToast as f, CopilotChatAudioRecorder as ft, useCopilotContext as g, CopilotContext as h, ThreadsContext as i, SandboxFunctionsContext as it, CopilotChatSuggestionPill as j, CopilotChatMessageView as k, useCoAgentStateRenders as l, CopilotKitInspector as lt, useCopilotMessagesContext as m, useCopilotChatConfiguration as mt, defaultCopilotContextCategories as n, defineToolCallRenderer as nt, useThreads as o, MCPAppsActivityContentSchema as ot, CopilotMessagesContext as p, CopilotChatConfigurationProvider as pt, useComponent as q, CoAgentStateRenderBridge as r, createA2UIMessageRenderer as rt, CoAgentStateRendersContext as s, MCPAppsActivityRenderer as st, CopilotKit as t, useAgentContext as tt, useAsyncCallback as u, CopilotChatInput_default as ut, CopilotPopup as v, DefaultCloseIcon as w, CopilotSidebarView as x, CopilotSidebar as y, useInterrupt as z };
|
|
9441
|
+
//# sourceMappingURL=copilotkit-C7n8Umv9.mjs.map
|