@copilotkit/react-core 1.79.2-canary.1792172552 → 1.80.0
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-DcENKLnJ.mjs → copilotkit-BNLtgOyD.mjs} +1783 -238
- package/dist/copilotkit-BNLtgOyD.mjs.map +1 -0
- package/dist/{copilotkit-kcYN96tM.d.mts → copilotkit-CWOSXhRO.d.mts} +278 -41
- package/dist/copilotkit-CWOSXhRO.d.mts.map +1 -0
- package/dist/{copilotkit-ConxFSB2.cjs → copilotkit-DKICi3nC.cjs} +1764 -206
- package/dist/copilotkit-DKICi3nC.cjs.map +1 -0
- package/dist/{copilotkit-BA0vyDds.d.cts → copilotkit-Dfw9HzO9.d.cts} +278 -41
- package/dist/copilotkit-Dfw9HzO9.d.cts.map +1 -0
- package/dist/index.cjs +15 -3
- 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 +15 -3
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +48 -11
- package/dist/index.umd.js.map +1 -1
- package/dist/v2/context.d.cts +7 -0
- package/dist/v2/context.d.cts.map +1 -1
- package/dist/v2/context.d.mts +7 -0
- package/dist/v2/context.d.mts.map +1 -1
- package/dist/v2/headless.cjs +23 -6
- package/dist/v2/headless.cjs.map +1 -1
- package/dist/v2/headless.d.cts +20 -2
- package/dist/v2/headless.d.cts.map +1 -1
- package/dist/v2/headless.d.mts +20 -2
- package/dist/v2/headless.d.mts.map +1 -1
- package/dist/v2/headless.mjs +23 -6
- package/dist/v2/headless.mjs.map +1 -1
- package/dist/v2/index.cjs +3 -7
- package/dist/v2/index.css +1 -1
- 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 +1756 -215
- package/dist/v2/index.umd.js.map +1 -1
- package/package.json +14 -11
- package/dist/copilotkit-BA0vyDds.d.cts.map +0 -1
- package/dist/copilotkit-ConxFSB2.cjs.map +0 -1
- package/dist/copilotkit-DcENKLnJ.mjs.map +0 -1
- package/dist/copilotkit-kcYN96tM.d.mts.map +0 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import * as React$1 from "react";
|
|
2
|
-
import React, { createContext, createElement, forwardRef, memo, useCallback, useContext, useEffect, useId, useImperativeHandle, useLayoutEffect, useMemo, useReducer, useRef, useState, useSyncExternalStore } from "react";
|
|
3
|
-
import { AgentRegistry, AgentThreadLockedError, ContextStore, CopilotKitCore, CopilotKitCore as CopilotKitCore$1, CopilotKitCoreErrorCode, CopilotKitCoreErrorCode as CopilotKitCoreErrorCode$1, CopilotKitCoreRuntimeConnectionStatus, CopilotKitCoreRuntimeConnectionStatus as CopilotKitCoreRuntimeConnectionStatus$1, CopilotKitHeaderResolutionError, INSPECTOR_THREAD_BRIDGE_PLUGIN_ID, IntelligenceAgent,
|
|
2
|
+
import React, { Fragment, createContext, createElement, forwardRef, memo, useCallback, useContext, useEffect, useId, useImperativeHandle, useLayoutEffect, useMemo, useReducer, useRef, useState, useSyncExternalStore } from "react";
|
|
3
|
+
import { AgentRegistry, AgentThreadLockedError, ContextStore, CopilotKitCore, CopilotKitCore as CopilotKitCore$1, CopilotKitCoreErrorCode, CopilotKitCoreErrorCode as CopilotKitCoreErrorCode$1, CopilotKitCoreRuntimeConnectionStatus, CopilotKitCoreRuntimeConnectionStatus as CopilotKitCoreRuntimeConnectionStatus$1, CopilotKitHeaderResolutionError, INSPECTOR_THREAD_BRIDGE_PLUGIN_ID, IntelligenceAgent, MEMORY_ERROR_REGISTRY, MemoryError, ProxiedCopilotRuntimeAgent, ProxiedCopilotRuntimeAgent as ProxiedCopilotRuntimeAgent$1, RunHandler, StateManager, SuggestionEngine, ToolCallStatus, ToolCallStatus as ToolCallStatus$1, WebMCPRegistry, completePartialMarkdown, createActionGroup, createEffect, createInspectorThreadRequestId, createReducer, createSelector, createStore, emitInspectorActiveThread, emitInspectorActiveThread as emitInspectorActiveThread$1, emitInspectorStopViewing, emitInspectorViewThread, emitInspectorViewThreadResult, emitInspectorViewThreadResult as emitInspectorViewThreadResult$1, empty, ensureObjectArgs, getWebMCPModelContext, isAbortError, isInspectorThreadBridgeEnabled, isInspectorThreadBridgeEnabled as isInspectorThreadBridgeEnabled$1, isRunCompletionAware, isRunCompletionAware as isRunCompletionAware$1, ofType, on, onInspectorActiveThread, onInspectorStopViewing, onInspectorStopViewing as onInspectorStopViewing$1, onInspectorViewThread, onInspectorViewThread as onInspectorViewThread$1, onInspectorViewThreadResult, parseToolArguments, props, select, ɵCOPILOTKIT_FEATURES, ɵInterruptState, ɵInterruptState as ɵInterruptState$1, ɵMAX_SOCKET_RETRIES, ɵRUNTIME_PROBE_TIMEOUT_MS, ɵTHREAD_REQUEST_TIMEOUT_MS, ɵcreateMemoryStore, ɵcreateThreadSelectors, ɵcreateThreadStore, ɵcreateThreadStore as ɵcreateThreadStore$1, ɵisCopilotKitFeature, ɵisHttpAgent, ɵisHttpAgent as ɵisHttpAgent$1, ɵisRetryableMemoryStatus, ɵjoinPhoenixChannel$, ɵmapMemoryMetadataEvent, ɵmemoryAdapterEvents, ɵmemoryDomainEvents, ɵmemoryReducer, ɵmemoryRestEvents, ɵobservePhoenixEvent$, ɵobservePhoenixJoinOutcome$, ɵobservePhoenixSocketHealth$, ɵobservePhoenixSocketSignals$, ɵphoenixChannel$, ɵphoenixSocket$, ɵselectFetchMoreError, ɵselectFetchMoreError as ɵselectFetchMoreError$1, ɵselectHasNextPage, ɵselectHasNextPage as ɵselectHasNextPage$1, ɵselectIsFetchingNextPage, ɵselectIsFetchingNextPage as ɵselectIsFetchingNextPage$1, ɵselectIsMutating, ɵselectIsMutating as ɵselectIsMutating$1, ɵselectMemories, ɵselectMemories as ɵselectMemories$1, ɵselectMemoriesAvailable, ɵselectMemoriesAvailable as ɵselectMemoriesAvailable$1, ɵselectMemoriesError, ɵselectMemoriesError as ɵselectMemoriesError$1, ɵselectMemoriesIsLoading, ɵselectMemoriesIsLoading as ɵselectMemoriesIsLoading$1, ɵselectMemoriesIsMutating, ɵselectMemoriesRealtimeStatus, ɵselectMemoriesRealtimeStatus as ɵselectMemoriesRealtimeStatus$1, ɵselectThreads, ɵselectThreads as ɵselectThreads$1, ɵselectThreadsError, ɵselectThreadsError as ɵselectThreadsError$1, ɵselectThreadsIsLoading, ɵselectThreadsIsLoading as ɵselectThreadsIsLoading$1, ɵthreadAdapterEvents, ɵwithHeaderDefaults, ɵwithHeaderDefaults as ɵwithHeaderDefaults$1 } from "@copilotkit/core";
|
|
4
4
|
import { ACTIVITY_HISTORY_METADATA, AGUIConnectNotImplementedError as AGUIConnectNotImplementedError$1, AGUIError, AGUI_METADATA_KEY, AbstractAgent as AbstractAgent$1, BackwardCompatibility_0_0_39, BackwardCompatibility_0_0_45, BackwardCompatibility_0_0_57, CompatibilityBoundary, DebugLogger, EventType, FilterToolCallsMiddleware, FunctionMiddleware, HttpAgent, Middleware, PROTOCOL_VERSION, aggregateTokenUsage, authoritativeActivityTypes, buildResumeArray, compactEvents, contentHasMedia, contentToText as contentToText$1, convertToLegacyEvents, createDebugLogger, defaultApplyEvents, enforceEvents, enforceOutgoingInput, getRunOutcome, isInterruptExpired, isRecognizedEvent, mergeMetadata, omitOptionalNulls, parseProtoStream, parseSSEStream, randomUUID, randomUUID as randomUUID$2, resolveAgentDebugConfig, resolveDebugLogger, runHttpRequest, structuredClone_, tokenUsageFromAiSdkUsage, tokenUsageFromLangChainMetadata, transformChunks, transformHttpEventStream, verifyEvents, withAuthoritativeActivityTypes } from "@ag-ui/client";
|
|
5
5
|
import { ActivityDeltaEventSchema, ActivityMessageSchema, ActivitySnapshotEventSchema, AddOperationSchema, AgentCapabilitiesSchema, AssistantMessageSchema, AttributableSchema, AudioInputContentSchema, AudioInputPartSchema, AudioPartSchema, BaseEventSchema, BaseMessageSchema, ContentPartSchema, ContextSchema, CopyOperationSchema, CustomEventSchema, DataSourceSchema, DeveloperMessageSchema, DocumentInputContentSchema, DocumentInputPartSchema, DocumentPartSchema, EventSchema, EventSchemas, EventTypeSchema, ExecutionCapabilitiesSchema, FileSourceSchema, FunctionCallSchema, HumanInTheLoopCapabilitiesSchema, IdentityCapabilitiesSchema, ImageInputContentSchema, ImageInputPartSchema, ImagePartSchema, InputContentDataSourceSchema, InputContentSchema, InputContentSourceSchema, InputContentUrlSourceSchema, InterruptSchema, JsonPatchOperationSchema, JsonPatchSchema, JsonPointerSchema, MessageSchema, MessagesSnapshotEventSchema, MetadataSchema, MoveOperationSchema, MultiAgentCapabilitiesSchema, MultimodalCapabilitiesSchema, MultimodalInputCapabilitiesSchema, MultimodalOutputCapabilitiesSchema, OptionalMetadataSchema, OutputCapabilitiesSchema, PartSourceSchema, RawEventSchema, ReasoningCapabilitiesSchema, ReasoningEncryptedValueEventSchema, ReasoningEncryptedValueSubtypeSchema, ReasoningEndEventSchema, ReasoningMessageChunkEventSchema, ReasoningMessageContentEventSchema, ReasoningMessageEndEventSchema, ReasoningMessageSchema, ReasoningMessageStartEventSchema, ReasoningStartEventSchema, RemoveOperationSchema, ReplaceOperationSchema, ResumeEntrySchema, RoleSchema, RunAgentInputSchema, RunErrorEventSchema, RunFinishedCancelledOutcomeSchema, RunFinishedEventSchema, RunFinishedInterruptOutcomeSchema, RunFinishedOutcomeSchema, RunFinishedSuccessOutcomeSchema, RunStartedEventSchema, StateCapabilitiesSchema, StateDeltaEventSchema, StateSchema, StateSnapshotEventSchema, StepFinishedEventSchema, StepStartedEventSchema, SubagentErrorEventSchema, SubagentFinishedEventSchema, SubagentFinishedOutcomeSchema, SubagentFinishedSuccessOutcomeSchema, SubagentFinishedSuspendedOutcomeSchema, SubagentInfoSchema, SubagentRunIdSchema, SubagentStartedEventSchema, SystemMessageSchema, TestOperationSchema, TextInputContentSchema, TextMessageChunkEventSchema, TextMessageContentEventSchema, TextMessageEndEventSchema, TextMessageRoleSchema, TextMessageStartEventSchema, TextPartSchema, TokenUsageSchema, ToolCallArgsEventSchema, ToolCallChunkEventSchema, ToolCallEndEventSchema, ToolCallResultEventSchema, ToolCallSchema, ToolCallStartEventSchema, ToolMessageSchema, ToolSchema, ToolsCapabilitiesSchema, TransportCapabilitiesSchema, UrlSourceSchema, UserMessageSchema, VideoInputContentSchema, VideoInputPartSchema, VideoPartSchema } from "@ag-ui/core/schemas";
|
|
6
6
|
import { extendTailwindMerge, twMerge } from "tailwind-merge";
|
|
7
|
-
import { ArrowUp, Check, ChevronDown, ChevronLeft, ChevronRight, ChevronRightIcon, Copy, Edit, EyeOff, Loader2, MessageCircle, Mic, PanelLeftOpen, Play, Plus, RefreshCw, Square, ThumbsDown, ThumbsUp, Upload, Volume2, Wrench, X } from "lucide-react";
|
|
7
|
+
import { ArrowUp, Check, ChevronDown, ChevronLeft, ChevronRight, ChevronRightIcon, Circle, Copy, Edit, EyeOff, Loader2, MessageCircle, Mic, PanelLeftOpen, Play, Plus, RefreshCw, Square, ThumbsDown, ThumbsUp, Upload, Volume2, Wrench, X } from "lucide-react";
|
|
8
8
|
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, GENERATE_SANDBOXED_UI_DESCRIPTION, MissingPublicApiKeyError, Severity, TranscriptionErrorCode, TranscriptionErrorCode as TranscriptionErrorCode$1, commitRowKeyStore, copyToClipboard, createAttachmentContent, createLicenseContextValue, createRowKeyStore, dataToUUID, exceedsMaxSize, formatFileSize, generateVideoThumbnail, getDocumentIcon, getModalityFromMimeType, getSourceUrl, matchesAcceptFilter, parseJson, partialJSONParse, randomId, randomUUID as randomUUID$1, readFileAsBase64, resolveRowRenderKeysById, schemaToJsonSchema, shouldEnableInspector } from "@copilotkit/shared";
|
|
9
9
|
import { CopilotKitAgentIdContext, CopilotKitContext, LicenseContext, useCopilotKit, useCopilotKit as useCopilotKit$1, useDefaultAgentId, useLicenseContext, useLicenseContext as useLicenseContext$1 } from "@copilotkit/react-core/v2/context";
|
|
10
10
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -19,6 +19,7 @@ import { z } from "zod";
|
|
|
19
19
|
import { MCPAppsActivityContentSchema, MCPAppsActivityType, ɵrunMcpFollowUp } from "@copilotkit/mcp-apps-renderer/activity";
|
|
20
20
|
import { A2UIProvider, A2UIRenderer, A2UI_SCHEMA_CONTEXT_DESCRIPTION, Catalog, DEFAULT_SURFACE_ID, ROOT_COMPONENT_ID, buildCatalogContextValue, extractCatalogComponentSchemas, filterCatalog, initializeDefaultCatalog, injectStyles, useA2UIActions, useA2UIError, viewerTheme } from "@copilotkit/a2ui-renderer";
|
|
21
21
|
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
22
|
+
import * as PopoverPrimitive from "@radix-ui/react-popover";
|
|
22
23
|
import { createPortal, flushSync } from "react-dom";
|
|
23
24
|
import { useVirtualizer } from "@tanstack/react-virtual";
|
|
24
25
|
import { StickToBottom, useStickToBottomContext } from "use-stick-to-bottom";
|
|
@@ -75,6 +76,8 @@ const CopilotChatDefaultLabels = {
|
|
|
75
76
|
chatInputToolbarFinishTranscribeButtonLabel: "Finish",
|
|
76
77
|
chatInputToolbarAddButtonLabel: "Add attachments",
|
|
77
78
|
chatInputToolbarToolsButtonLabel: "Tools",
|
|
79
|
+
chatInputToolbarSendButtonLabel: "Send message",
|
|
80
|
+
chatInputToolbarStopButtonLabel: "Stop",
|
|
78
81
|
assistantMessageToolbarCopyCodeLabel: "Copy",
|
|
79
82
|
assistantMessageToolbarCopyCodeCopiedLabel: "Copied",
|
|
80
83
|
assistantMessageToolbarCopyMessageLabel: "Copy",
|
|
@@ -87,13 +90,18 @@ const CopilotChatDefaultLabels = {
|
|
|
87
90
|
assistantMessageToolbarInspectorHideDescription: "Until you reload this page",
|
|
88
91
|
assistantMessageToolbarThumbsUpLabel: "Good response",
|
|
89
92
|
assistantMessageToolbarThumbsDownLabel: "Bad response",
|
|
93
|
+
assistantMessageFeedbackCommentPlaceholder: "Add a comment (optional)",
|
|
94
|
+
assistantMessageFeedbackCommentSubmitLabel: "Send comment",
|
|
90
95
|
assistantMessageToolbarReadAloudLabel: "Read aloud",
|
|
91
96
|
assistantMessageToolbarRegenerateLabel: "Regenerate",
|
|
92
97
|
userMessageToolbarCopyMessageLabel: "Copy",
|
|
93
98
|
userMessageToolbarEditMessageLabel: "Edit",
|
|
99
|
+
userMessageToolbarPreviousBranchLabel: "Previous branch",
|
|
100
|
+
userMessageToolbarNextBranchLabel: "Next branch",
|
|
94
101
|
chatDisclaimerText: "AI can make mistakes. Please verify important information.",
|
|
95
102
|
chatToggleOpenLabel: "Open chat",
|
|
96
103
|
chatToggleCloseLabel: "Close chat",
|
|
104
|
+
chatScrollToBottomLabel: "Scroll to bottom",
|
|
97
105
|
modalHeaderTitle: "CopilotKit Chat",
|
|
98
106
|
welcomeMessageText: "How can I help you today?"
|
|
99
107
|
};
|
|
@@ -805,6 +813,11 @@ function renderSlot(slot, DefaultComponent, props) {
|
|
|
805
813
|
//#region src/v2/components/chat/CopilotChatInput.tsx
|
|
806
814
|
const SLASH_MENU_MAX_VISIBLE_ITEMS = 5;
|
|
807
815
|
const SLASH_MENU_ITEM_HEIGHT_PX = 40;
|
|
816
|
+
/**
|
|
817
|
+
* The chat composer: a text area with the add-menu, voice and send/stop
|
|
818
|
+
* buttons, and a slash-command menu that lists `toolsMenu` items once the text
|
|
819
|
+
* starts with "/".
|
|
820
|
+
*/
|
|
808
821
|
function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning = false, onStartTranscribe, onCancelTranscribe, onFinishTranscribe, onFinishTranscribeWithAudio, onAddFile, onChange, value, toolsMenu, autoFocus = false, positioning = "static", keyboardHeight = 0, containerRef, showDisclaimer, bottomAnchored = false, textArea, sendButton, startTranscribeButton, cancelTranscribeButton, finishTranscribeButton, addMenuButton, audioRecorder, disclaimer, children, className, ...props }) {
|
|
809
822
|
const isControlled = value !== void 0;
|
|
810
823
|
const [internalValue, setInternalValue] = useState(() => value ?? "");
|
|
@@ -1024,10 +1037,12 @@ function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning =
|
|
|
1024
1037
|
send();
|
|
1025
1038
|
};
|
|
1026
1039
|
const BoundAudioRecorder = renderSlot(audioRecorder, CopilotChatAudioRecorder, { ref: audioRecorderRef });
|
|
1040
|
+
const showsStop = isProcessing && canStop;
|
|
1027
1041
|
const BoundSendButton = renderSlot(sendButton, CopilotChatInput.SendButton, {
|
|
1028
1042
|
onClick: handleSendButtonClick,
|
|
1029
1043
|
disabled: isProcessing ? !canStop : !canSend,
|
|
1030
|
-
|
|
1044
|
+
"aria-label": showsStop ? labels.chatInputToolbarStopButtonLabel : labels.chatInputToolbarSendButtonLabel,
|
|
1045
|
+
children: showsStop ? /* @__PURE__ */ jsx(Square, { className: "cpk:size-[18px] cpk:fill-current" }) : void 0
|
|
1031
1046
|
});
|
|
1032
1047
|
const BoundStartTranscribeButton = renderSlot(startTranscribeButton, CopilotChatInput.StartTranscribeButton, { onClick: onStartTranscribe });
|
|
1033
1048
|
const BoundCancelTranscribeButton = renderSlot(cancelTranscribeButton, CopilotChatInput.CancelTranscribeButton, { onClick: onCancelTranscribe });
|
|
@@ -1339,18 +1354,22 @@ function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning =
|
|
|
1339
1354
|
});
|
|
1340
1355
|
}
|
|
1341
1356
|
(function(_CopilotChatInput) {
|
|
1342
|
-
_CopilotChatInput.SendButton = ({ className, children, ...props }) =>
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1357
|
+
_CopilotChatInput.SendButton = ({ className, children, ...props }) => {
|
|
1358
|
+
const labels = useCopilotChatConfiguration()?.labels ?? CopilotChatDefaultLabels;
|
|
1359
|
+
return /* @__PURE__ */ jsx("div", {
|
|
1360
|
+
className: "cpk:mr-[10px]",
|
|
1361
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
1362
|
+
type: "button",
|
|
1363
|
+
"data-testid": "copilot-send-button",
|
|
1364
|
+
variant: "chatInputToolbarPrimary",
|
|
1365
|
+
size: "chatInputToolbarIcon",
|
|
1366
|
+
className,
|
|
1367
|
+
"aria-label": labels.chatInputToolbarSendButtonLabel,
|
|
1368
|
+
...props,
|
|
1369
|
+
children: children ?? /* @__PURE__ */ jsx(ArrowUp, { className: "cpk:size-[18px]" })
|
|
1370
|
+
})
|
|
1371
|
+
});
|
|
1372
|
+
};
|
|
1354
1373
|
const ToolbarButton = _CopilotChatInput.ToolbarButton = ({ icon, labelKey, defaultClassName, className, ...props }) => {
|
|
1355
1374
|
const labels = useCopilotChatConfiguration()?.labels ?? CopilotChatDefaultLabels;
|
|
1356
1375
|
return /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
|
|
@@ -1360,6 +1379,7 @@ function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning =
|
|
|
1360
1379
|
variant: "chatInputToolbarSecondary",
|
|
1361
1380
|
size: "chatInputToolbarIcon",
|
|
1362
1381
|
className: twMerge(defaultClassName, className),
|
|
1382
|
+
"aria-label": labels[labelKey],
|
|
1363
1383
|
...props,
|
|
1364
1384
|
children: icon
|
|
1365
1385
|
})
|
|
@@ -1430,6 +1450,7 @@ function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning =
|
|
|
1430
1450
|
size: "chatInputToolbarIcon",
|
|
1431
1451
|
className: twMerge("cpk:ml-1", className),
|
|
1432
1452
|
disabled: isDisabled,
|
|
1453
|
+
"aria-label": labels.chatInputToolbarAddButtonLabel,
|
|
1433
1454
|
...props,
|
|
1434
1455
|
children: /* @__PURE__ */ jsx(Plus, { className: "cpk:size-[20px]" })
|
|
1435
1456
|
});
|
|
@@ -1579,6 +1600,32 @@ function warnAboutUnrenderedToolCalls(toolNames, registered, alreadyWarned) {
|
|
|
1579
1600
|
}
|
|
1580
1601
|
}
|
|
1581
1602
|
/**
|
|
1603
|
+
* The tool-call renderers registered on the provider, kept current.
|
|
1604
|
+
* @internal
|
|
1605
|
+
*/
|
|
1606
|
+
function useToolCallRenderers() {
|
|
1607
|
+
const { copilotkit } = useCopilotKit();
|
|
1608
|
+
return useSyncExternalStore((callback) => copilotkit.subscribe({ onRenderToolCallsChanged: callback }).unsubscribe, () => copilotkit.renderToolCalls, () => copilotkit.renderToolCalls);
|
|
1609
|
+
}
|
|
1610
|
+
/**
|
|
1611
|
+
* Which tool names have a renderer of their own, whether a wildcard (`"*"`)
|
|
1612
|
+
* renderer is registered, and which of them opted into grouping.
|
|
1613
|
+
* @internal
|
|
1614
|
+
*/
|
|
1615
|
+
function useToolCallRendererNames() {
|
|
1616
|
+
const renderers = useToolCallRenderers();
|
|
1617
|
+
return useMemo(() => {
|
|
1618
|
+
const named = renderers.filter((rc) => rc.name !== "*");
|
|
1619
|
+
const wildcards = renderers.filter((rc) => rc.name === "*");
|
|
1620
|
+
return {
|
|
1621
|
+
named: new Set(named.map((rc) => rc.name)),
|
|
1622
|
+
groupedNames: new Set(named.filter((rc) => rc.group).map((rc) => rc.name)),
|
|
1623
|
+
wildcard: wildcards.length > 0,
|
|
1624
|
+
wildcardGroups: wildcards.some((rc) => rc.group)
|
|
1625
|
+
};
|
|
1626
|
+
}, [renderers]);
|
|
1627
|
+
}
|
|
1628
|
+
/**
|
|
1582
1629
|
* Hook that returns a function to render tool calls based on the render functions
|
|
1583
1630
|
* defined in CopilotKitProvider.
|
|
1584
1631
|
*
|
|
@@ -1589,9 +1636,7 @@ function useRenderToolCall() {
|
|
|
1589
1636
|
const agentId = useCopilotChatConfiguration()?.agentId ?? DEFAULT_AGENT_ID;
|
|
1590
1637
|
const unrenderedToolNames = useRef(/* @__PURE__ */ new Set());
|
|
1591
1638
|
const warnedToolNames = useRef(/* @__PURE__ */ new Set());
|
|
1592
|
-
const renderToolCalls =
|
|
1593
|
-
return copilotkit.subscribe({ onRenderToolCallsChanged: callback }).unsubscribe;
|
|
1594
|
-
}, () => copilotkit.renderToolCalls, () => copilotkit.renderToolCalls);
|
|
1639
|
+
const renderToolCalls = useToolCallRenderers();
|
|
1595
1640
|
const renderToolCall = useCallback(({ toolCall, toolMessage }) => {
|
|
1596
1641
|
const exactMatches = renderToolCalls.filter((rc) => rc.name === toolCall.function.name);
|
|
1597
1642
|
const renderConfig = exactMatches.find((rc) => rc.agentId === agentId) || exactMatches.find((rc) => !rc.agentId) || exactMatches[0] || renderToolCalls.find((rc) => rc.name === "*");
|
|
@@ -1626,7 +1671,7 @@ function useRenderToolCall() {
|
|
|
1626
1671
|
|
|
1627
1672
|
//#endregion
|
|
1628
1673
|
//#region package.json
|
|
1629
|
-
var version = "1.
|
|
1674
|
+
var version = "1.80.0";
|
|
1630
1675
|
|
|
1631
1676
|
//#endregion
|
|
1632
1677
|
//#region src/v2/components/CopilotKitInspector.tsx
|
|
@@ -1862,7 +1907,7 @@ function InlineFeatureWarning({ featureName }) {
|
|
|
1862
1907
|
* Fetches resource content on-demand via proxied MCP requests. The React shell
|
|
1863
1908
|
* owns the iframe; `bindMcpApp` owns the protocol.
|
|
1864
1909
|
*/
|
|
1865
|
-
const MCPAppsActivityRenderer = function MCPAppsActivityRenderer({ content, message, agent }) {
|
|
1910
|
+
const MCPAppsActivityRenderer = function MCPAppsActivityRenderer({ content, message, agent, allowSameOriginFallback }) {
|
|
1866
1911
|
const { copilotkit } = useCopilotKit$1();
|
|
1867
1912
|
const messageId = message?.id;
|
|
1868
1913
|
const containerRef = useRef(null);
|
|
@@ -1912,6 +1957,7 @@ const MCPAppsActivityRenderer = function MCPAppsActivityRenderer({ content, mess
|
|
|
1912
1957
|
getAgent: () => agentRef.current,
|
|
1913
1958
|
host: copilotkit,
|
|
1914
1959
|
messageId,
|
|
1960
|
+
options: { allowSameOriginFallback },
|
|
1915
1961
|
hooks: {
|
|
1916
1962
|
onResource: (resource) => {
|
|
1917
1963
|
if (!mounted) return;
|
|
@@ -1953,6 +1999,7 @@ const MCPAppsActivityRenderer = function MCPAppsActivityRenderer({ content, mess
|
|
|
1953
1999
|
agent,
|
|
1954
2000
|
copilotkit,
|
|
1955
2001
|
messageId,
|
|
2002
|
+
allowSameOriginFallback,
|
|
1956
2003
|
content.resourceUri,
|
|
1957
2004
|
content.serverHash,
|
|
1958
2005
|
content.serverId
|
|
@@ -3167,7 +3214,8 @@ function defineToolCallRenderer(def) {
|
|
|
3167
3214
|
name: def.name,
|
|
3168
3215
|
args: argsSchema,
|
|
3169
3216
|
render: def.render,
|
|
3170
|
-
...def.agentId ? { agentId: def.agentId } : {}
|
|
3217
|
+
...def.agentId ? { agentId: def.agentId } : {},
|
|
3218
|
+
...def.group ? { group: true } : {}
|
|
3171
3219
|
};
|
|
3172
3220
|
}
|
|
3173
3221
|
|
|
@@ -3383,6 +3431,11 @@ const DEFAULT_DESIGN_SKILL = `When generating UI with generateSandboxedUi, follo
|
|
|
3383
3431
|
- Use CSS Grid or Flexbox for layout. Ensure the UI looks good at any width.
|
|
3384
3432
|
- Minimal transitions (150ms) for hover/focus states only. No decorative animations.
|
|
3385
3433
|
- Keep the UI focused and dense — avoid excessive padding. Use compact spacing (8–12px gaps, 10–14px padding in controls).`;
|
|
3434
|
+
/** The MCP Apps renderer with `mcpApps.allowSameOriginFallback` applied. */
|
|
3435
|
+
const SameOriginMCPAppsActivityRenderer = (props) => /* @__PURE__ */ jsx(MCPAppsActivityRenderer, {
|
|
3436
|
+
...props,
|
|
3437
|
+
allowSameOriginFallback: true
|
|
3438
|
+
});
|
|
3386
3439
|
const DEFAULT_LEARNING = Object.freeze({});
|
|
3387
3440
|
function toLearningConfig(learning) {
|
|
3388
3441
|
if (learning === true) return DEFAULT_LEARNING;
|
|
@@ -3399,7 +3452,8 @@ function useStableArrayProp(prop, warningMessage, isMeaningfulChange) {
|
|
|
3399
3452
|
}, [value, warningMessage]);
|
|
3400
3453
|
return value;
|
|
3401
3454
|
}
|
|
3402
|
-
|
|
3455
|
+
/** Provide a shared core instance and synchronize runtime, tool, and UI configuration. */
|
|
3456
|
+
const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY_HEADERS, credentials, messageFilter, publicApiKey, publicLicenseKey, licenseToken, properties = EMPTY_PROPERTIES, agents__unsafe_dev_only: agents = EMPTY_AGENTS, selfManagedAgents = EMPTY_AGENTS, renderToolCalls, renderActivityMessages, renderCustomMessages, frontendTools, humanInTheLoop, openGenerativeUI, enableInspector, agentId, showIntelligenceIndicator = true, useSingleEndpoint, onError, a2ui, mcpApps, defaultThrottleMs, debug, learning }) => {
|
|
3403
3457
|
const learningConfig = useMemo(() => toLearningConfig(learning), [learning]);
|
|
3404
3458
|
const [shouldRenderInspector, setShouldRenderInspector] = useState(false);
|
|
3405
3459
|
const [inspectorVisible, setInspectorVisible] = useState(false);
|
|
@@ -3456,11 +3510,12 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY
|
|
|
3456
3510
|
const core = copilotkitRef.current;
|
|
3457
3511
|
return filterCatalog(rawCatalog, (name) => core ? core.isCatalogComponentEnabled(name) : true);
|
|
3458
3512
|
}, [rawCatalog, catalogToggleVersion]);
|
|
3513
|
+
const mcpAppsAllowSameOrigin = mcpApps?.allowSameOriginFallback === true;
|
|
3459
3514
|
const builtInActivityRenderers = useMemo(() => {
|
|
3460
3515
|
const renderers = [{
|
|
3461
3516
|
activityType: MCPAppsActivityType,
|
|
3462
3517
|
content: MCPAppsActivityContentSchema,
|
|
3463
|
-
render: MCPAppsActivityRenderer
|
|
3518
|
+
render: mcpAppsAllowSameOrigin ? SameOriginMCPAppsActivityRenderer : MCPAppsActivityRenderer
|
|
3464
3519
|
}];
|
|
3465
3520
|
if (openGenUIActive) renderers.push({
|
|
3466
3521
|
activityType: OpenGenerativeUIActivityType,
|
|
@@ -3478,7 +3533,8 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY
|
|
|
3478
3533
|
a2uiActive,
|
|
3479
3534
|
openGenUIActive,
|
|
3480
3535
|
a2ui,
|
|
3481
|
-
filteredCatalog
|
|
3536
|
+
filteredCatalog,
|
|
3537
|
+
mcpAppsAllowSameOrigin
|
|
3482
3538
|
]);
|
|
3483
3539
|
const allActivityRenderers = useMemo(() => {
|
|
3484
3540
|
return [...renderActivityMessagesList, ...builtInActivityRenderers];
|
|
@@ -3586,6 +3642,7 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY
|
|
|
3586
3642
|
description: GENERATE_SANDBOXED_UI_DESCRIPTION,
|
|
3587
3643
|
parameters: GenerateSandboxedUiArgsSchema,
|
|
3588
3644
|
handler: async () => "UI generated",
|
|
3645
|
+
reconnectBehavior: "resume-pending",
|
|
3589
3646
|
followUp: true,
|
|
3590
3647
|
render: OpenGenerativeUIToolRenderer
|
|
3591
3648
|
}];
|
|
@@ -4317,7 +4374,8 @@ function useRenderTool(config, deps) {
|
|
|
4317
4374
|
...props,
|
|
4318
4375
|
parameters: props.args
|
|
4319
4376
|
}),
|
|
4320
|
-
...config.agentId ? { agentId: config.agentId } : {}
|
|
4377
|
+
...config.agentId ? { agentId: config.agentId } : {},
|
|
4378
|
+
group: config.group
|
|
4321
4379
|
}) : defineToolCallRenderer({
|
|
4322
4380
|
name: config.name,
|
|
4323
4381
|
args: config.parameters,
|
|
@@ -4335,16 +4393,395 @@ function useRenderTool(config, deps) {
|
|
|
4335
4393
|
parameters: props.args
|
|
4336
4394
|
});
|
|
4337
4395
|
},
|
|
4338
|
-
...config.agentId ? { agentId: config.agentId } : {}
|
|
4396
|
+
...config.agentId ? { agentId: config.agentId } : {},
|
|
4397
|
+
group: config.group
|
|
4339
4398
|
});
|
|
4340
4399
|
copilotkit.addHookRenderToolCall(renderer);
|
|
4341
4400
|
}, [
|
|
4342
4401
|
config.name,
|
|
4402
|
+
config.group,
|
|
4343
4403
|
copilotkit,
|
|
4344
4404
|
depsVersion
|
|
4345
4405
|
]);
|
|
4346
4406
|
}
|
|
4347
4407
|
|
|
4408
|
+
//#endregion
|
|
4409
|
+
//#region src/v2/components/chat/CopilotChatToolCallGroup.tsx
|
|
4410
|
+
/**
|
|
4411
|
+
* Set by a group around the calls it shows, so CopilotKit's built-in tool card
|
|
4412
|
+
* draws itself as a compact row that fits the group instead of a card.
|
|
4413
|
+
* @internal
|
|
4414
|
+
*/
|
|
4415
|
+
const ToolCallGroupContext = createContext(null);
|
|
4416
|
+
/**
|
|
4417
|
+
* A call without a result is running only while the group is active: once
|
|
4418
|
+
* the run has moved on or ended, its result is never coming.
|
|
4419
|
+
*/
|
|
4420
|
+
const entryStatus = ({ toolMessage }, active) => toolMessage ? toolMessage.error ? "failed" : "done" : active ? "running" : "stopped";
|
|
4421
|
+
/** @internal */
|
|
4422
|
+
const statusLabels = {
|
|
4423
|
+
running: "Running",
|
|
4424
|
+
done: "Done",
|
|
4425
|
+
failed: "Failed",
|
|
4426
|
+
stopped: "Stopped"
|
|
4427
|
+
};
|
|
4428
|
+
/** The first non-empty string argument: usually a command, path or query. */
|
|
4429
|
+
function argumentPreview(parameters) {
|
|
4430
|
+
if (!parameters || typeof parameters !== "object") return void 0;
|
|
4431
|
+
return Object.values(parameters).find((v) => typeof v === "string" && v.trim().length > 0)?.replace(/\s+/g, " ");
|
|
4432
|
+
}
|
|
4433
|
+
const entryPreview = (entry) => argumentPreview(partialJSONParse(entry.toolCall.function.arguments));
|
|
4434
|
+
/** "run_command ×2, read_file" */
|
|
4435
|
+
function toolNames(calls) {
|
|
4436
|
+
const counts = /* @__PURE__ */ new Map();
|
|
4437
|
+
for (const { toolCall } of calls) {
|
|
4438
|
+
const name = toolCall.function.name;
|
|
4439
|
+
counts.set(name, (counts.get(name) ?? 0) + 1);
|
|
4440
|
+
}
|
|
4441
|
+
return [...counts].map(([name, count]) => count > 1 ? `${name} ×${count}` : name).join(", ");
|
|
4442
|
+
}
|
|
4443
|
+
const pluralize = (count, noun) => `${count} ${noun}${count === 1 ? "" : "s"}`;
|
|
4444
|
+
/**
|
|
4445
|
+
* Height transition between closed and its content's height. Closed content
|
|
4446
|
+
* stays mounted (so its state survives) but is inert.
|
|
4447
|
+
* @internal
|
|
4448
|
+
*/
|
|
4449
|
+
function Collapsible({ open, id, className, children }) {
|
|
4450
|
+
const ref = useRef(null);
|
|
4451
|
+
useLayoutEffect(() => {
|
|
4452
|
+
ref.current?.toggleAttribute("inert", !open);
|
|
4453
|
+
}, [open]);
|
|
4454
|
+
return /* @__PURE__ */ jsx("div", {
|
|
4455
|
+
ref,
|
|
4456
|
+
id,
|
|
4457
|
+
className: twMerge("cpk:grid cpk:transition-[grid-template-rows] cpk:duration-300 cpk:ease-[cubic-bezier(0.16,1,0.3,1)] cpk:motion-reduce:transition-none", className),
|
|
4458
|
+
style: { gridTemplateRows: open ? "1fr" : "0fr" },
|
|
4459
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
4460
|
+
className: "cpk:min-h-0 cpk:overflow-hidden",
|
|
4461
|
+
children
|
|
4462
|
+
})
|
|
4463
|
+
});
|
|
4464
|
+
}
|
|
4465
|
+
function StatusIcon({ status, className }) {
|
|
4466
|
+
const Icon = {
|
|
4467
|
+
running: Loader2,
|
|
4468
|
+
done: Check,
|
|
4469
|
+
failed: X,
|
|
4470
|
+
stopped: Circle
|
|
4471
|
+
}[status];
|
|
4472
|
+
return /* @__PURE__ */ jsx(Icon, {
|
|
4473
|
+
"aria-hidden": "true",
|
|
4474
|
+
className: twMerge("cpk:size-3.5 cpk:shrink-0 cpk:text-muted-foreground", status === "running" && "cpk:animate-spin", status === "failed" && "cpk:text-destructive", className)
|
|
4475
|
+
});
|
|
4476
|
+
}
|
|
4477
|
+
function Chevron({ open, className }) {
|
|
4478
|
+
return /* @__PURE__ */ jsx(ChevronRight, {
|
|
4479
|
+
"aria-hidden": "true",
|
|
4480
|
+
className: twMerge("cpk:size-3.5 cpk:shrink-0 cpk:transition-transform cpk:duration-200", open && "cpk:rotate-90", className)
|
|
4481
|
+
});
|
|
4482
|
+
}
|
|
4483
|
+
function FailedCount({ calls }) {
|
|
4484
|
+
const failed = calls.filter((call) => call.toolMessage?.error).length;
|
|
4485
|
+
if (!failed) return null;
|
|
4486
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
4487
|
+
className: "cpk:shrink-0 cpk:text-destructive",
|
|
4488
|
+
children: [failed, " failed"]
|
|
4489
|
+
});
|
|
4490
|
+
}
|
|
4491
|
+
/**
|
|
4492
|
+
* Guarded JSON.stringify for the payload blocks. A circular reference would
|
|
4493
|
+
* otherwise crash the entire React tree on render.
|
|
4494
|
+
*/
|
|
4495
|
+
function stringifyPayload(value) {
|
|
4496
|
+
if (typeof value === "string") return value;
|
|
4497
|
+
try {
|
|
4498
|
+
return JSON.stringify(value, null, 2);
|
|
4499
|
+
} catch (err) {
|
|
4500
|
+
console.warn("[CopilotKit] Failed to JSON.stringify tool-call payload; falling back to String():", err);
|
|
4501
|
+
try {
|
|
4502
|
+
return String(value);
|
|
4503
|
+
} catch {
|
|
4504
|
+
return "[unserializable]";
|
|
4505
|
+
}
|
|
4506
|
+
}
|
|
4507
|
+
}
|
|
4508
|
+
function Payload({ label, value }) {
|
|
4509
|
+
return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
|
|
4510
|
+
className: "cpk:text-[11px] cpk:font-medium cpk:uppercase cpk:tracking-wide cpk:text-muted-foreground",
|
|
4511
|
+
children: label
|
|
4512
|
+
}), /* @__PURE__ */ jsx("pre", {
|
|
4513
|
+
className: "cpk:m-0 cpk:mt-1.5 cpk:max-h-[200px] cpk:overflow-auto cpk:rounded-lg cpk:bg-muted cpk:p-2.5 cpk:font-mono cpk:text-xs cpk:leading-relaxed cpk:text-foreground cpk:whitespace-pre-wrap cpk:break-words",
|
|
4514
|
+
children: stringifyPayload(value)
|
|
4515
|
+
})] });
|
|
4516
|
+
}
|
|
4517
|
+
/**
|
|
4518
|
+
* A tool call's arguments and, once it has one, its result.
|
|
4519
|
+
* @internal
|
|
4520
|
+
*/
|
|
4521
|
+
function ToolCallPayloads({ parameters, result, className }) {
|
|
4522
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
4523
|
+
className: twMerge("cpk:grid cpk:gap-3", className),
|
|
4524
|
+
children: [/* @__PURE__ */ jsx(Payload, {
|
|
4525
|
+
label: "Arguments",
|
|
4526
|
+
value: parameters ?? {}
|
|
4527
|
+
}), result !== void 0 && /* @__PURE__ */ jsx(Payload, {
|
|
4528
|
+
label: "Result",
|
|
4529
|
+
value: result
|
|
4530
|
+
})]
|
|
4531
|
+
});
|
|
4532
|
+
}
|
|
4533
|
+
/**
|
|
4534
|
+
* The built-in tool card drawn as a row inside a group: status, name and main
|
|
4535
|
+
* argument, opening to the payloads.
|
|
4536
|
+
* @internal
|
|
4537
|
+
*/
|
|
4538
|
+
function ToolCallRow({ name, parameters, result, status, appearance, className, ...props }) {
|
|
4539
|
+
const [open, setOpen] = useState(false);
|
|
4540
|
+
const detailsId = useId();
|
|
4541
|
+
const preview = argumentPreview(parameters);
|
|
4542
|
+
const line = appearance === "line";
|
|
4543
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
4544
|
+
"data-copilotkit": true,
|
|
4545
|
+
className: twMerge(!line && "cpk:border-t cpk:border-border", className),
|
|
4546
|
+
...props,
|
|
4547
|
+
children: [/* @__PURE__ */ jsxs("button", {
|
|
4548
|
+
type: "button",
|
|
4549
|
+
"aria-expanded": open,
|
|
4550
|
+
"aria-controls": detailsId,
|
|
4551
|
+
onClick: () => setOpen((value) => !value),
|
|
4552
|
+
className: twMerge("cpk:group/row cpk:m-0 cpk:flex cpk:min-w-0 cpk:cursor-pointer cpk:items-center cpk:gap-2 cpk:border-none cpk:bg-transparent cpk:text-left cpk:text-[13px] cpk:text-inherit cpk:transition-colors cpk:hover:bg-accent/60 cpk:focus-visible:outline-2 cpk:focus-visible:-outline-offset-2 cpk:focus-visible:outline-ring", line ? "cpk:-mx-1.5 cpk:w-[calc(100%+0.75rem)] cpk:rounded-md cpk:px-1.5 cpk:py-1" : "cpk:w-full cpk:px-3.5 cpk:py-2"),
|
|
4553
|
+
children: [
|
|
4554
|
+
/* @__PURE__ */ jsx(StatusIcon, { status }),
|
|
4555
|
+
/* @__PURE__ */ jsx("span", {
|
|
4556
|
+
"data-testid": "copilot-tool-render-name",
|
|
4557
|
+
className: twMerge("cpk:shrink-0 cpk:font-mono cpk:text-[13px] cpk:font-medium cpk:text-foreground", status === "running" && "cpk-shimmer"),
|
|
4558
|
+
children: name
|
|
4559
|
+
}),
|
|
4560
|
+
preview && /* @__PURE__ */ jsx("span", {
|
|
4561
|
+
className: "cpk:min-w-0 cpk:truncate cpk:font-mono cpk:text-[13px] cpk:text-muted-foreground",
|
|
4562
|
+
children: preview
|
|
4563
|
+
}),
|
|
4564
|
+
/* @__PURE__ */ jsx("span", {
|
|
4565
|
+
"data-testid": "copilot-tool-render-status",
|
|
4566
|
+
className: "cpk:sr-only",
|
|
4567
|
+
children: statusLabels[status]
|
|
4568
|
+
}),
|
|
4569
|
+
/* @__PURE__ */ jsx(Chevron, {
|
|
4570
|
+
open,
|
|
4571
|
+
className: twMerge("cpk:ml-auto cpk:text-muted-foreground", !open && "cpk:opacity-0 cpk:group-hover/row:opacity-100 cpk:group-focus-visible/row:opacity-100")
|
|
4572
|
+
})
|
|
4573
|
+
]
|
|
4574
|
+
}), /* @__PURE__ */ jsx(Collapsible, {
|
|
4575
|
+
open,
|
|
4576
|
+
id: detailsId,
|
|
4577
|
+
children: /* @__PURE__ */ jsx(ToolCallPayloads, {
|
|
4578
|
+
parameters,
|
|
4579
|
+
result,
|
|
4580
|
+
className: line ? "cpk:mt-1 cpk:mb-2 cpk:ml-5.5" : "cpk:px-3.5 cpk:pt-1 cpk:pb-3"
|
|
4581
|
+
})
|
|
4582
|
+
})]
|
|
4583
|
+
});
|
|
4584
|
+
}
|
|
4585
|
+
/**
|
|
4586
|
+
* Tool calls made in a row, collapsed into one summary. While a call runs the
|
|
4587
|
+
* summary names it ("Running read_file src/app.ts"); once they're all done it
|
|
4588
|
+
* reads "Used 3 tools" and opens to the calls.
|
|
4589
|
+
*
|
|
4590
|
+
* Each call is drawn by its registered renderer. CopilotKit's built-in card
|
|
4591
|
+
* (`useDefaultRenderTool`) draws a compact row inside the card and line
|
|
4592
|
+
* appearances; a custom wildcard renderer draws whatever it draws.
|
|
4593
|
+
*/
|
|
4594
|
+
function CopilotChatToolCallGroup({ calls, renderCall, appearance = "card", isActive = false, className, ...props }) {
|
|
4595
|
+
const [open, setOpen] = useState(false);
|
|
4596
|
+
const bodyId = useId();
|
|
4597
|
+
const latest = calls[calls.length - 1];
|
|
4598
|
+
if (!latest) return null;
|
|
4599
|
+
const current = isActive ? calls.find((call) => !call.toolMessage) ?? latest : void 0;
|
|
4600
|
+
const preview = current ? entryPreview(current) : void 0;
|
|
4601
|
+
const done = calls.filter((call) => call.toolMessage).length;
|
|
4602
|
+
const statuses = calls.map((call) => entryStatus(call, isActive));
|
|
4603
|
+
const failedIds = new Set(calls.filter((_, index) => statuses[index] === "failed").map((call) => call.toolCall.id));
|
|
4604
|
+
const status = current ? "running" : failedIds.size > 0 ? "failed" : statuses.includes("stopped") ? "stopped" : "done";
|
|
4605
|
+
const rows = (rowAppearance) => /* @__PURE__ */ jsx(ToolCallGroupContext.Provider, {
|
|
4606
|
+
value: {
|
|
4607
|
+
appearance: rowAppearance,
|
|
4608
|
+
failedIds,
|
|
4609
|
+
active: isActive
|
|
4610
|
+
},
|
|
4611
|
+
children: calls.map((call) => /* @__PURE__ */ jsx(React.Fragment, { children: renderCall(call) }, call.toolCall.id))
|
|
4612
|
+
});
|
|
4613
|
+
const groupProps = {
|
|
4614
|
+
"data-copilotkit": true,
|
|
4615
|
+
"data-testid": "copilot-tool-call-group",
|
|
4616
|
+
"data-appearance": appearance,
|
|
4617
|
+
"data-state": status,
|
|
4618
|
+
...props
|
|
4619
|
+
};
|
|
4620
|
+
const runningLabel = current && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("span", {
|
|
4621
|
+
className: "cpk:shrink-0 cpk:font-medium cpk-shimmer",
|
|
4622
|
+
children: ["Running ", current.toolCall.function.name]
|
|
4623
|
+
}), preview && /* @__PURE__ */ jsx("span", {
|
|
4624
|
+
className: "cpk:min-w-0 cpk:truncate cpk:font-mono cpk:text-xs cpk:opacity-70",
|
|
4625
|
+
children: preview
|
|
4626
|
+
})] });
|
|
4627
|
+
if (appearance === "line") {
|
|
4628
|
+
if (calls.length === 1 && !current) return /* @__PURE__ */ jsx("div", {
|
|
4629
|
+
...groupProps,
|
|
4630
|
+
className: twMerge("cpk:my-2", className),
|
|
4631
|
+
children: /* @__PURE__ */ jsx(ToolCallGroupContext.Provider, {
|
|
4632
|
+
value: {
|
|
4633
|
+
appearance: "line",
|
|
4634
|
+
failedIds,
|
|
4635
|
+
active: isActive
|
|
4636
|
+
},
|
|
4637
|
+
children: renderCall(latest)
|
|
4638
|
+
})
|
|
4639
|
+
});
|
|
4640
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
4641
|
+
...groupProps,
|
|
4642
|
+
className: twMerge("cpk:my-3", className),
|
|
4643
|
+
children: [/* @__PURE__ */ jsxs("button", {
|
|
4644
|
+
type: "button",
|
|
4645
|
+
"aria-expanded": open,
|
|
4646
|
+
"aria-controls": bodyId,
|
|
4647
|
+
onClick: () => setOpen((value) => !value),
|
|
4648
|
+
className: "cpk:m-0 cpk:inline-flex cpk:max-w-full cpk:min-w-0 cpk:cursor-pointer cpk:items-center cpk:gap-1.5 cpk:rounded-md cpk:border-none cpk:bg-transparent cpk:p-0 cpk:py-0.5 cpk:text-sm cpk:text-muted-foreground cpk:transition-colors cpk:hover:text-foreground cpk:focus-visible:outline-2 cpk:focus-visible:outline-ring",
|
|
4649
|
+
children: [runningLabel || /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
4650
|
+
/* @__PURE__ */ jsxs("span", {
|
|
4651
|
+
className: "cpk:shrink-0 cpk:font-medium",
|
|
4652
|
+
children: ["Used ", pluralize(calls.length, "tool")]
|
|
4653
|
+
}),
|
|
4654
|
+
/* @__PURE__ */ jsx("span", {
|
|
4655
|
+
className: "cpk:min-w-0 cpk:truncate cpk:font-mono cpk:text-xs cpk:opacity-70",
|
|
4656
|
+
children: toolNames(calls)
|
|
4657
|
+
}),
|
|
4658
|
+
/* @__PURE__ */ jsx(FailedCount, { calls })
|
|
4659
|
+
] }), /* @__PURE__ */ jsx(Chevron, { open })]
|
|
4660
|
+
}), /* @__PURE__ */ jsx(Collapsible, {
|
|
4661
|
+
open,
|
|
4662
|
+
id: bodyId,
|
|
4663
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
4664
|
+
className: "cpk:mt-1 cpk:ml-1 cpk:border-l-2 cpk:border-border cpk:py-0.5 cpk:pl-3",
|
|
4665
|
+
children: rows("line")
|
|
4666
|
+
})
|
|
4667
|
+
})]
|
|
4668
|
+
});
|
|
4669
|
+
}
|
|
4670
|
+
if (appearance === "stack") {
|
|
4671
|
+
if (calls.length === 1) return /* @__PURE__ */ jsx("div", {
|
|
4672
|
+
...groupProps,
|
|
4673
|
+
className: twMerge("cpk:py-1", className),
|
|
4674
|
+
children: renderCall(latest)
|
|
4675
|
+
});
|
|
4676
|
+
const behind = open ? 0 : Math.min(calls.length - 1, 2);
|
|
4677
|
+
const layer = "cpk:rounded-xl cpk:border cpk:border-border cpk:bg-card cpk:text-card-foreground";
|
|
4678
|
+
const latestStatus = entryStatus(latest, isActive);
|
|
4679
|
+
const latestPreview = entryPreview(latest);
|
|
4680
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
4681
|
+
...groupProps,
|
|
4682
|
+
className: twMerge("cpk:my-3", className),
|
|
4683
|
+
style: {
|
|
4684
|
+
paddingBottom: behind * 6,
|
|
4685
|
+
...props.style
|
|
4686
|
+
},
|
|
4687
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
4688
|
+
className: "cpk:relative cpk:isolate",
|
|
4689
|
+
children: [Array.from({ length: behind }, (_, index) => /* @__PURE__ */ jsx("div", {
|
|
4690
|
+
"aria-hidden": "true",
|
|
4691
|
+
className: twMerge(layer, "cpk:absolute cpk:inset-0"),
|
|
4692
|
+
style: {
|
|
4693
|
+
transform: `translateY(${(index + 1) * 6}px) scaleX(${1 - (index + 1) * .045})`,
|
|
4694
|
+
zIndex: -1 - index,
|
|
4695
|
+
opacity: 1 - (index + 1) * .28
|
|
4696
|
+
}
|
|
4697
|
+
}, index)), /* @__PURE__ */ jsx("button", {
|
|
4698
|
+
type: "button",
|
|
4699
|
+
"aria-expanded": open,
|
|
4700
|
+
"aria-controls": open ? bodyId : void 0,
|
|
4701
|
+
onClick: () => setOpen((value) => !value),
|
|
4702
|
+
className: twMerge("cpk:relative cpk:m-0 cpk:flex cpk:min-w-0 cpk:cursor-pointer cpk:items-center cpk:text-left cpk:transition-colors cpk:focus-visible:outline-2 cpk:focus-visible:outline-ring", open ? "cpk:mb-1 cpk:gap-1.5 cpk:rounded-md cpk:border-none cpk:bg-transparent cpk:p-0 cpk:py-0.5 cpk:text-xs cpk:text-muted-foreground cpk:hover:text-foreground" : twMerge(layer, "cpk:w-full cpk:gap-2 cpk:px-3.5 cpk:py-2.5 cpk:text-[13px] cpk:shadow-[0_1px_2px_rgb(0_0_0/0.04)] cpk:hover:bg-accent")),
|
|
4703
|
+
children: open ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
4704
|
+
pluralize(calls.length, "tool call"),
|
|
4705
|
+
/* @__PURE__ */ jsx(FailedCount, { calls }),
|
|
4706
|
+
/* @__PURE__ */ jsx(Chevron, {
|
|
4707
|
+
open: true,
|
|
4708
|
+
className: "cpk:-rotate-90"
|
|
4709
|
+
}),
|
|
4710
|
+
"Collapse"
|
|
4711
|
+
] }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("span", {
|
|
4712
|
+
className: "cpk:flex cpk:min-w-0 cpk:flex-1 cpk:items-center cpk:gap-2 cpk:animate-[cpk-stack-drop_260ms_cubic-bezier(0.16,1,0.3,1)] cpk:motion-reduce:animate-none",
|
|
4713
|
+
children: [
|
|
4714
|
+
/* @__PURE__ */ jsx(StatusIcon, { status: latestStatus }),
|
|
4715
|
+
/* @__PURE__ */ jsx("span", {
|
|
4716
|
+
className: twMerge("cpk:shrink-0 cpk:font-mono cpk:font-medium cpk:text-foreground", latestStatus === "running" && "cpk-shimmer"),
|
|
4717
|
+
children: latest.toolCall.function.name
|
|
4718
|
+
}),
|
|
4719
|
+
latestPreview && /* @__PURE__ */ jsx("span", {
|
|
4720
|
+
className: "cpk:min-w-0 cpk:truncate cpk:font-mono cpk:text-muted-foreground",
|
|
4721
|
+
children: latestPreview
|
|
4722
|
+
})
|
|
4723
|
+
]
|
|
4724
|
+
}, latest.toolCall.id), /* @__PURE__ */ jsxs("span", {
|
|
4725
|
+
className: "cpk:ml-2 cpk:inline-flex cpk:shrink-0 cpk:items-center cpk:gap-2 cpk:text-xs cpk:text-muted-foreground",
|
|
4726
|
+
children: [
|
|
4727
|
+
/* @__PURE__ */ jsx(FailedCount, { calls }),
|
|
4728
|
+
/* @__PURE__ */ jsx("span", {
|
|
4729
|
+
className: "cpk:tabular-nums",
|
|
4730
|
+
children: pluralize(calls.length, "call")
|
|
4731
|
+
}),
|
|
4732
|
+
/* @__PURE__ */ jsx(Chevron, {
|
|
4733
|
+
open: false,
|
|
4734
|
+
className: "cpk:rotate-90"
|
|
4735
|
+
})
|
|
4736
|
+
]
|
|
4737
|
+
})] })
|
|
4738
|
+
})]
|
|
4739
|
+
}), open && /* @__PURE__ */ jsx("div", {
|
|
4740
|
+
id: bodyId,
|
|
4741
|
+
className: "cpk:[&>*]:animate-[cpk-stack-fan_300ms_cubic-bezier(0.16,1,0.3,1)_both] cpk:motion-reduce:[&>*]:animate-none",
|
|
4742
|
+
children: calls.map((call) => /* @__PURE__ */ jsx(React.Fragment, { children: renderCall(call) }, call.toolCall.id))
|
|
4743
|
+
})]
|
|
4744
|
+
});
|
|
4745
|
+
}
|
|
4746
|
+
if (calls.length === 1) return /* @__PURE__ */ jsx("div", {
|
|
4747
|
+
...groupProps,
|
|
4748
|
+
className: twMerge("cpk:py-1", className),
|
|
4749
|
+
children: renderCall(latest)
|
|
4750
|
+
});
|
|
4751
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
4752
|
+
...groupProps,
|
|
4753
|
+
className: twMerge("cpk:my-3 cpk:overflow-hidden cpk:rounded-xl cpk:border cpk:border-border cpk:bg-card cpk:text-card-foreground", className),
|
|
4754
|
+
children: [/* @__PURE__ */ jsxs("button", {
|
|
4755
|
+
type: "button",
|
|
4756
|
+
"aria-expanded": open,
|
|
4757
|
+
"aria-controls": bodyId,
|
|
4758
|
+
onClick: () => setOpen((value) => !value),
|
|
4759
|
+
className: "cpk:m-0 cpk:flex cpk:w-full cpk:min-w-0 cpk:cursor-pointer cpk:items-center cpk:gap-2.5 cpk:border-none cpk:bg-transparent cpk:px-3.5 cpk:py-2.5 cpk:text-left cpk:text-[13px] cpk:text-inherit cpk:transition-colors cpk:hover:bg-accent/60 cpk:focus-visible:outline-2 cpk:focus-visible:-outline-offset-2 cpk:focus-visible:outline-ring",
|
|
4760
|
+
children: [
|
|
4761
|
+
/* @__PURE__ */ jsx(StatusIcon, { status }),
|
|
4762
|
+
runningLabel || /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("span", {
|
|
4763
|
+
className: "cpk:shrink-0 cpk:font-medium cpk:text-foreground",
|
|
4764
|
+
children: ["Used ", pluralize(calls.length, "tool")]
|
|
4765
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
4766
|
+
className: "cpk:min-w-0 cpk:truncate cpk:font-mono cpk:text-xs cpk:text-muted-foreground",
|
|
4767
|
+
children: toolNames(calls)
|
|
4768
|
+
})] }),
|
|
4769
|
+
/* @__PURE__ */ jsxs("span", {
|
|
4770
|
+
className: "cpk:ml-auto cpk:flex cpk:shrink-0 cpk:items-center cpk:gap-2 cpk:pl-2 cpk:text-xs cpk:text-muted-foreground",
|
|
4771
|
+
children: [status === "failed" ? /* @__PURE__ */ jsx(FailedCount, { calls }) : /* @__PURE__ */ jsx("span", {
|
|
4772
|
+
className: "cpk:tabular-nums",
|
|
4773
|
+
children: status === "running" ? `${done} done` : statusLabels[status]
|
|
4774
|
+
}), /* @__PURE__ */ jsx(Chevron, { open })]
|
|
4775
|
+
})
|
|
4776
|
+
]
|
|
4777
|
+
}), /* @__PURE__ */ jsx(Collapsible, {
|
|
4778
|
+
open,
|
|
4779
|
+
id: bodyId,
|
|
4780
|
+
children: /* @__PURE__ */ jsx("div", { children: rows("card") })
|
|
4781
|
+
})]
|
|
4782
|
+
});
|
|
4783
|
+
}
|
|
4784
|
+
|
|
4348
4785
|
//#endregion
|
|
4349
4786
|
//#region src/v2/hooks/use-default-render-tool.tsx
|
|
4350
4787
|
/**
|
|
@@ -4428,7 +4865,8 @@ function useDefaultRenderTool(config, deps) {
|
|
|
4428
4865
|
const userRender = config?.render;
|
|
4429
4866
|
useRenderTool({
|
|
4430
4867
|
name: "*",
|
|
4431
|
-
render: userRender ? (raw) => userRender(adaptRendererProps(raw)) : (raw) => /* @__PURE__ */ jsx(DefaultToolCallRenderer, { ...adaptRendererProps(raw) })
|
|
4868
|
+
render: userRender ? (raw) => userRender(adaptRendererProps(raw)) : (raw) => /* @__PURE__ */ jsx(DefaultToolCallRenderer, { ...adaptRendererProps(raw) }),
|
|
4869
|
+
group: userRender ? config?.group === true : true
|
|
4432
4870
|
}, deps);
|
|
4433
4871
|
}
|
|
4434
4872
|
/**
|
|
@@ -4449,9 +4887,23 @@ function safeStringifyForPre(value) {
|
|
|
4449
4887
|
}
|
|
4450
4888
|
}
|
|
4451
4889
|
function DefaultToolCallRenderer({ name, toolCallId, parameters, status, result }) {
|
|
4890
|
+
const group = useContext(ToolCallGroupContext);
|
|
4452
4891
|
const [isExpanded, setIsExpanded] = useState(false);
|
|
4453
4892
|
const isActive = status === "inProgress" || status === "executing";
|
|
4454
4893
|
const isComplete = status === "complete";
|
|
4894
|
+
if (group) return /* @__PURE__ */ jsx(ToolCallRow, {
|
|
4895
|
+
"data-testid": "copilot-tool-render",
|
|
4896
|
+
"data-tool-name": name,
|
|
4897
|
+
"data-tool-call-id": toolCallId,
|
|
4898
|
+
"data-status": status,
|
|
4899
|
+
"data-args": safeStringifyForAttr(parameters),
|
|
4900
|
+
"data-result": safeStringifyForAttr(result),
|
|
4901
|
+
name,
|
|
4902
|
+
parameters,
|
|
4903
|
+
result,
|
|
4904
|
+
status: isComplete ? group.failedIds.has(toolCallId) ? "failed" : "done" : group.active ? "running" : "stopped",
|
|
4905
|
+
appearance: group.appearance
|
|
4906
|
+
});
|
|
4455
4907
|
const statusLabel = isActive ? "Running" : isComplete ? "Done" : status;
|
|
4456
4908
|
const dotClassName = isActive ? "cpk:bg-amber-500" : isComplete ? "cpk:bg-emerald-500" : "cpk:bg-zinc-400";
|
|
4457
4909
|
const badgeClassName = isActive ? "cpk:bg-amber-100 cpk:text-amber-800 cpk:dark:bg-amber-500/15 cpk:dark:text-amber-400" : isComplete ? "cpk:bg-emerald-100 cpk:text-emerald-800 cpk:dark:bg-emerald-500/15 cpk:dark:text-emerald-400" : "cpk:bg-zinc-100 cpk:text-zinc-800 cpk:dark:bg-zinc-700/40 cpk:dark:text-zinc-300";
|
|
@@ -6148,38 +6600,227 @@ function useLearningContainersInCurrentThread({ learningContainers }) {
|
|
|
6148
6600
|
});
|
|
6149
6601
|
}
|
|
6150
6602
|
|
|
6603
|
+
//#endregion
|
|
6604
|
+
//#region src/v2/components/chat/tool-call-display-context.ts
|
|
6605
|
+
/** @internal */
|
|
6606
|
+
const ToolCallDisplayContext = createContext(null);
|
|
6607
|
+
|
|
6608
|
+
//#endregion
|
|
6609
|
+
//#region src/v2/components/chat/tool-call-layout.ts
|
|
6610
|
+
function contentLength(content) {
|
|
6611
|
+
return typeof content === "string" ? content.length : JSON.stringify(content ?? "").length;
|
|
6612
|
+
}
|
|
6613
|
+
const entrySignature = ({ toolCall, toolMessage }) => [
|
|
6614
|
+
toolCall.id,
|
|
6615
|
+
toolCall.function.name,
|
|
6616
|
+
toolCall.function.arguments.length,
|
|
6617
|
+
toolMessage ? `${contentLength(toolMessage.content)}${toolMessage.error ? "!" : ""}` : "-"
|
|
6618
|
+
].join(":");
|
|
6619
|
+
function signatureOf(segments) {
|
|
6620
|
+
return segments.map((segment) => segment.kind === "call" ? `c(${entrySignature(segment.call)})` : `g${segment.trailing ? "*" : ""}(${segment.calls.map(entrySignature).join(",")})`).join("|");
|
|
6621
|
+
}
|
|
6622
|
+
/** Index of tool results by the call they answer. */
|
|
6623
|
+
function getToolResults(messages) {
|
|
6624
|
+
const results = /* @__PURE__ */ new Map();
|
|
6625
|
+
for (const message of messages) if (message.role === "tool") results.set(message.toolCallId, message);
|
|
6626
|
+
return results;
|
|
6627
|
+
}
|
|
6628
|
+
/**
|
|
6629
|
+
* Lays out the tool calls of every assistant message in `rendered`.
|
|
6630
|
+
*
|
|
6631
|
+
* Calls drawn by a renderer that opted into grouping join the group that's
|
|
6632
|
+
* open; anything else that shows between them closes it: assistant text, a
|
|
6633
|
+
* user, reasoning or activity message, or a call drawn by any other renderer. A group belongs to
|
|
6634
|
+
* the message where it starts, so later messages whose calls joined it render
|
|
6635
|
+
* no tool calls themselves.
|
|
6636
|
+
*
|
|
6637
|
+
* @param rendered - The messages as the chat renders them, in order.
|
|
6638
|
+
* @param all - Every message, for finding tool results (a transform may hide them).
|
|
6639
|
+
* @param renderers - The registered renderers.
|
|
6640
|
+
*/
|
|
6641
|
+
function getToolCallLayouts(rendered, all, renderers) {
|
|
6642
|
+
const results = getToolResults(all);
|
|
6643
|
+
const layouts = /* @__PURE__ */ new Map();
|
|
6644
|
+
let open;
|
|
6645
|
+
for (const message of rendered) {
|
|
6646
|
+
if (message.role === "tool") continue;
|
|
6647
|
+
if (message.role !== "assistant") {
|
|
6648
|
+
open = void 0;
|
|
6649
|
+
continue;
|
|
6650
|
+
}
|
|
6651
|
+
if (typeof message.content === "string" && message.content.trim()) open = void 0;
|
|
6652
|
+
const segments = [];
|
|
6653
|
+
layouts.set(message.id, segments);
|
|
6654
|
+
const toolCalls = /* @__PURE__ */ new Map();
|
|
6655
|
+
for (const toolCall of message.toolCalls ?? []) toolCalls.set(toolCall.id, toolCall);
|
|
6656
|
+
for (const toolCall of toolCalls.values()) {
|
|
6657
|
+
const entry = {
|
|
6658
|
+
toolCall,
|
|
6659
|
+
toolMessage: results.get(toolCall.id)
|
|
6660
|
+
};
|
|
6661
|
+
const name = toolCall.function.name;
|
|
6662
|
+
const named = renderers.named.has(name);
|
|
6663
|
+
const rendered = named || renderers.wildcard;
|
|
6664
|
+
const groups = named ? renderers.groupedNames.has(name) : renderers.wildcardGroups;
|
|
6665
|
+
if (!rendered || !groups) {
|
|
6666
|
+
if (rendered) open = void 0;
|
|
6667
|
+
segments.push({
|
|
6668
|
+
kind: "call",
|
|
6669
|
+
id: toolCall.id,
|
|
6670
|
+
call: entry,
|
|
6671
|
+
rendered
|
|
6672
|
+
});
|
|
6673
|
+
} else if (open) open.calls.push(entry);
|
|
6674
|
+
else {
|
|
6675
|
+
open = {
|
|
6676
|
+
kind: "group",
|
|
6677
|
+
id: toolCall.id,
|
|
6678
|
+
calls: [entry],
|
|
6679
|
+
trailing: false
|
|
6680
|
+
};
|
|
6681
|
+
segments.push(open);
|
|
6682
|
+
}
|
|
6683
|
+
}
|
|
6684
|
+
}
|
|
6685
|
+
if (open) open.trailing = true;
|
|
6686
|
+
const layout = /* @__PURE__ */ new Map();
|
|
6687
|
+
for (const [id, segments] of layouts) layout.set(id, {
|
|
6688
|
+
segments,
|
|
6689
|
+
signature: signatureOf(segments)
|
|
6690
|
+
});
|
|
6691
|
+
return layout;
|
|
6692
|
+
}
|
|
6693
|
+
/**
|
|
6694
|
+
* Finds the working phase of every reply in `rendered`: its messages up to the
|
|
6695
|
+
* last one that calls a tool. Text in there was narration; what follows is the
|
|
6696
|
+
* reply itself. Replies that called no tools are omitted, except the latest,
|
|
6697
|
+
* which may be about to.
|
|
6698
|
+
*/
|
|
6699
|
+
function getTurnWork(rendered, layouts) {
|
|
6700
|
+
const turns = /* @__PURE__ */ new Map();
|
|
6701
|
+
let start = 0;
|
|
6702
|
+
while (start < rendered.length) {
|
|
6703
|
+
let end = start;
|
|
6704
|
+
while (end < rendered.length && rendered[end].role !== "user") end++;
|
|
6705
|
+
const key = start > 0 ? rendered[start - 1].id : "start";
|
|
6706
|
+
const visible = rendered.slice(start, end).filter((message) => message.role !== "tool");
|
|
6707
|
+
const isLatest = end === rendered.length;
|
|
6708
|
+
const calls = [];
|
|
6709
|
+
for (const message of visible) for (const segment of layouts.get(message.id)?.segments ?? []) if (segment.kind === "group") calls.push(...segment.calls);
|
|
6710
|
+
else if (segment.rendered) calls.push(segment.call);
|
|
6711
|
+
const shown = new Set(calls.map((entry) => entry.toolCall.id));
|
|
6712
|
+
let lastWork = -1;
|
|
6713
|
+
visible.forEach((message, index) => {
|
|
6714
|
+
if (message.role === "assistant" && message.toolCalls?.some((call) => shown.has(call.id))) lastWork = index;
|
|
6715
|
+
});
|
|
6716
|
+
const first = visible[0];
|
|
6717
|
+
if (first && (calls.length > 0 || isLatest)) {
|
|
6718
|
+
let lastAssistant = -1;
|
|
6719
|
+
visible.forEach((message, index) => {
|
|
6720
|
+
if (message.role === "assistant") lastAssistant = index;
|
|
6721
|
+
});
|
|
6722
|
+
const replyText = visible[lastAssistant]?.content;
|
|
6723
|
+
const endsWithWork = lastAssistant >= 0 && lastAssistant <= lastWork && typeof replyText === "string" && replyText.trim().length > 0;
|
|
6724
|
+
turns.set(key, {
|
|
6725
|
+
key,
|
|
6726
|
+
firstMessageId: first.id,
|
|
6727
|
+
workMessageIds: new Set(visible.slice(0, lastWork + 1).map((message) => message.id)),
|
|
6728
|
+
replyTextMessageId: endsWithWork ? visible[lastAssistant].id : void 0,
|
|
6729
|
+
calls,
|
|
6730
|
+
isLatest
|
|
6731
|
+
});
|
|
6732
|
+
}
|
|
6733
|
+
start = end + 1;
|
|
6734
|
+
}
|
|
6735
|
+
return turns;
|
|
6736
|
+
}
|
|
6737
|
+
|
|
6151
6738
|
//#endregion
|
|
6152
6739
|
//#region src/v2/components/chat/CopilotChatToolCallsView.tsx
|
|
6153
|
-
|
|
6740
|
+
const appearances = {
|
|
6741
|
+
grouped: "card",
|
|
6742
|
+
line: "line",
|
|
6743
|
+
stacked: "stack"
|
|
6744
|
+
};
|
|
6745
|
+
function CopilotChatToolCallsView({ message, messages = [], display: displayProp, group }) {
|
|
6154
6746
|
const renderToolCall = useRenderToolCall();
|
|
6747
|
+
const rendererNames = useToolCallRendererNames();
|
|
6155
6748
|
const { copilotkit } = useCopilotKit();
|
|
6156
6749
|
const subscribe = useCallback((onChange) => copilotkit.ɵsubscribeToLearningConfigured(onChange), [copilotkit]);
|
|
6157
6750
|
const getSnapshot = () => copilotkit.ɵlearningConfigured;
|
|
6158
6751
|
const learningConfigured = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
6752
|
+
const context = useContext(ToolCallDisplayContext);
|
|
6753
|
+
const display = displayProp ?? context?.display ?? "grouped";
|
|
6754
|
+
const viewLayout = context?.layouts.get(message.id);
|
|
6755
|
+
const layout = useMemo(() => {
|
|
6756
|
+
if (display === "separate") return void 0;
|
|
6757
|
+
return viewLayout ?? getToolCallLayouts([message], messages, rendererNames).get(message.id);
|
|
6758
|
+
}, [
|
|
6759
|
+
display,
|
|
6760
|
+
viewLayout,
|
|
6761
|
+
message,
|
|
6762
|
+
messages,
|
|
6763
|
+
rendererNames
|
|
6764
|
+
]);
|
|
6159
6765
|
if (!message.toolCalls || message.toolCalls.length === 0) return null;
|
|
6160
|
-
|
|
6766
|
+
const renderCall = (entry) => {
|
|
6161
6767
|
const rendered = renderToolCall({
|
|
6162
|
-
toolCall,
|
|
6163
|
-
toolMessage:
|
|
6768
|
+
toolCall: entry.toolCall,
|
|
6769
|
+
toolMessage: entry.toolMessage
|
|
6164
6770
|
});
|
|
6165
|
-
if (rendered === null) return
|
|
6166
|
-
if (!learningConfigured) return rendered;
|
|
6771
|
+
if (rendered === null || !learningConfigured) return rendered;
|
|
6167
6772
|
return /* @__PURE__ */ jsx("div", {
|
|
6168
|
-
"data-tool-call-id": toolCall.id,
|
|
6773
|
+
"data-tool-call-id": entry.toolCall.id,
|
|
6169
6774
|
style: { display: "contents" },
|
|
6170
6775
|
children: rendered
|
|
6171
|
-
}
|
|
6776
|
+
});
|
|
6777
|
+
};
|
|
6778
|
+
if (!layout) return /* @__PURE__ */ jsx(Fragment$1, { children: message.toolCalls.map((toolCall) => {
|
|
6779
|
+
const toolMessage = messages.find((m) => m.role === "tool" && m.toolCallId === toolCall.id);
|
|
6780
|
+
return /* @__PURE__ */ jsx(React.Fragment, { children: renderCall({
|
|
6781
|
+
toolCall,
|
|
6782
|
+
toolMessage
|
|
6783
|
+
}) }, toolCall.id);
|
|
6784
|
+
}) });
|
|
6785
|
+
const workOpen = context?.workOpen.get(message.id);
|
|
6786
|
+
const groupActive = (trailing) => trailing && (context ? context.isRunning : true);
|
|
6787
|
+
return /* @__PURE__ */ jsx(Fragment$1, { children: layout.segments.map((segment) => {
|
|
6788
|
+
if (segment.kind === "call") return /* @__PURE__ */ jsx(React.Fragment, { children: renderCall(segment.call) }, segment.id);
|
|
6789
|
+
if (display === "turn") {
|
|
6790
|
+
const failedIds = new Set(segment.calls.filter((call) => call.toolMessage?.error).map((call) => call.toolCall.id));
|
|
6791
|
+
return /* @__PURE__ */ jsx(Collapsible, {
|
|
6792
|
+
open: workOpen ?? true,
|
|
6793
|
+
className: "cpk:-mx-2",
|
|
6794
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
6795
|
+
className: "cpk:px-2 cpk:py-1.5",
|
|
6796
|
+
children: /* @__PURE__ */ jsx(ToolCallGroupContext.Provider, {
|
|
6797
|
+
value: {
|
|
6798
|
+
appearance: "line",
|
|
6799
|
+
failedIds,
|
|
6800
|
+
active: groupActive(segment.trailing)
|
|
6801
|
+
},
|
|
6802
|
+
children: segment.calls.map((call) => /* @__PURE__ */ jsx(React.Fragment, { children: renderCall(call) }, call.toolCall.id))
|
|
6803
|
+
})
|
|
6804
|
+
})
|
|
6805
|
+
}, segment.id);
|
|
6806
|
+
}
|
|
6807
|
+
return /* @__PURE__ */ jsx(React.Fragment, { children: renderSlot(group, CopilotChatToolCallGroup, {
|
|
6808
|
+
calls: segment.calls,
|
|
6809
|
+
renderCall,
|
|
6810
|
+
appearance: appearances[display] ?? "card",
|
|
6811
|
+
isActive: groupActive(segment.trailing)
|
|
6812
|
+
}) }, segment.id);
|
|
6172
6813
|
}) });
|
|
6173
6814
|
}
|
|
6174
6815
|
|
|
6175
6816
|
//#endregion
|
|
6176
6817
|
//#region src/v2/components/chat/CopilotChatInspectorButton.tsx
|
|
6177
6818
|
let shortcutsHidden = false;
|
|
6178
|
-
const listeners = /* @__PURE__ */ new Set();
|
|
6819
|
+
const listeners$1 = /* @__PURE__ */ new Set();
|
|
6179
6820
|
const subscribe = (listener) => {
|
|
6180
|
-
listeners.add(listener);
|
|
6821
|
+
listeners$1.add(listener);
|
|
6181
6822
|
return () => {
|
|
6182
|
-
listeners.delete(listener);
|
|
6823
|
+
listeners$1.delete(listener);
|
|
6183
6824
|
};
|
|
6184
6825
|
};
|
|
6185
6826
|
const getSnapshot = () => shortcutsHidden;
|
|
@@ -6189,7 +6830,7 @@ function useInspectorShortcutsHidden() {
|
|
|
6189
6830
|
}
|
|
6190
6831
|
function hideShortcuts() {
|
|
6191
6832
|
shortcutsHidden = true;
|
|
6192
|
-
listeners.forEach((listener) => listener());
|
|
6833
|
+
listeners$1.forEach((listener) => listener());
|
|
6193
6834
|
}
|
|
6194
6835
|
function InspectorKiteIcon({ className, ...props }) {
|
|
6195
6836
|
const id = useId();
|
|
@@ -6456,47 +7097,544 @@ function CopilotChatInspectorButton({ title, className, onClick, onPointerDown,
|
|
|
6456
7097
|
}
|
|
6457
7098
|
|
|
6458
7099
|
//#endregion
|
|
6459
|
-
//#region src/v2/components/
|
|
7100
|
+
//#region src/v2/components/ui/popover.tsx
|
|
7101
|
+
function Popover({ ...props }) {
|
|
7102
|
+
return /* @__PURE__ */ jsx(PopoverPrimitive.Root, {
|
|
7103
|
+
"data-slot": "popover",
|
|
7104
|
+
...props
|
|
7105
|
+
});
|
|
7106
|
+
}
|
|
7107
|
+
function PopoverAnchor({ ...props }) {
|
|
7108
|
+
return /* @__PURE__ */ jsx(PopoverPrimitive.Anchor, {
|
|
7109
|
+
"data-slot": "popover-anchor",
|
|
7110
|
+
...props
|
|
7111
|
+
});
|
|
7112
|
+
}
|
|
6460
7113
|
/**
|
|
6461
|
-
*
|
|
6462
|
-
*
|
|
7114
|
+
* Popover content in a portal, so it floats over the page instead of taking
|
|
7115
|
+
* room in the layout, with the CopilotKit style scope on it.
|
|
6463
7116
|
*/
|
|
6464
|
-
|
|
6465
|
-
|
|
6466
|
-
|
|
6467
|
-
|
|
6468
|
-
|
|
6469
|
-
|
|
6470
|
-
|
|
6471
|
-
|
|
6472
|
-
|
|
6473
|
-
|
|
7117
|
+
const PopoverContent = React$1.forwardRef(({ className, align = "start", sideOffset = 6, ...props }, ref) => /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(PopoverPrimitive.Content, {
|
|
7118
|
+
ref,
|
|
7119
|
+
"data-copilotkit": true,
|
|
7120
|
+
"data-copilotkit-popover": true,
|
|
7121
|
+
"data-slot": "popover-content",
|
|
7122
|
+
align,
|
|
7123
|
+
sideOffset,
|
|
7124
|
+
className: cn("cpk:z-50 cpk:outline-none cpk:data-[state=open]:animate-in cpk:data-[state=open]:fade-in-0 cpk:data-[state=open]:zoom-in-95 cpk:data-[side=bottom]:slide-in-from-top-1 cpk:data-[side=top]:slide-in-from-bottom-1", className),
|
|
7125
|
+
...props
|
|
7126
|
+
}) }));
|
|
7127
|
+
PopoverContent.displayName = "PopoverContent";
|
|
7128
|
+
|
|
7129
|
+
//#endregion
|
|
7130
|
+
//#region src/v2/lib/message-feedback.ts
|
|
7131
|
+
/** Trajectory event name for a rating of one assistant message. */
|
|
7132
|
+
const MESSAGE_FEEDBACK_EVENT_NAME = "message.feedback";
|
|
7133
|
+
/** Longest comment kept, in characters; the rest is cut so the event stays small. */
|
|
7134
|
+
const MESSAGE_FEEDBACK_MAX_COMMENT_LENGTH = 1e3;
|
|
7135
|
+
/** Longest excerpt of the rated response sent with the rating, in characters. */
|
|
7136
|
+
const RESPONSE_EXCERPT_LENGTH = 500;
|
|
7137
|
+
const ratings = /* @__PURE__ */ new Map();
|
|
7138
|
+
const listeners = /* @__PURE__ */ new Map();
|
|
7139
|
+
const threadKey = (agentId, threadId) => JSON.stringify([agentId, threadId]);
|
|
7140
|
+
const messageKey = (agentId, threadId, messageId) => JSON.stringify([
|
|
7141
|
+
agentId,
|
|
7142
|
+
threadId,
|
|
7143
|
+
messageId
|
|
7144
|
+
]);
|
|
7145
|
+
/** Cuts `text` to `max` characters without splitting a surrogate pair. */
|
|
7146
|
+
const clip = (text, max) => {
|
|
7147
|
+
const characters = Array.from(text);
|
|
7148
|
+
return characters.length > max ? characters.slice(0, max).join("") : text;
|
|
7149
|
+
};
|
|
7150
|
+
/** The comment as kept and sent: trimmed and capped, or none. */
|
|
7151
|
+
const normalizeComment = (comment) => {
|
|
7152
|
+
if (typeof comment !== "string") return void 0;
|
|
7153
|
+
const text = clip(comment.trim(), MESSAGE_FEEDBACK_MAX_COMMENT_LENGTH);
|
|
7154
|
+
return text === "" ? void 0 : text;
|
|
7155
|
+
};
|
|
7156
|
+
/** The rating this page gave one message, if any. */
|
|
7157
|
+
function getMessageFeedback(agentId, threadId, messageId) {
|
|
7158
|
+
return ratings.get(messageKey(agentId, threadId, messageId));
|
|
7159
|
+
}
|
|
7160
|
+
/** Calls `listener` whenever a rating in this Thread changes. */
|
|
7161
|
+
function subscribeToMessageFeedback(agentId, threadId, listener) {
|
|
7162
|
+
const key = threadKey(agentId, threadId);
|
|
7163
|
+
let set = listeners.get(key);
|
|
7164
|
+
if (set === void 0) {
|
|
7165
|
+
set = /* @__PURE__ */ new Set();
|
|
7166
|
+
listeners.set(key, set);
|
|
7167
|
+
}
|
|
7168
|
+
set.add(listener);
|
|
7169
|
+
return () => {
|
|
7170
|
+
set.delete(listener);
|
|
7171
|
+
if (set.size === 0) listeners.delete(key);
|
|
7172
|
+
};
|
|
6474
7173
|
}
|
|
6475
|
-
|
|
6476
|
-
|
|
6477
|
-
|
|
6478
|
-
|
|
6479
|
-
|
|
6480
|
-
|
|
6481
|
-
|
|
6482
|
-
|
|
6483
|
-
|
|
6484
|
-
|
|
6485
|
-
const
|
|
6486
|
-
|
|
6487
|
-
|
|
7174
|
+
/**
|
|
7175
|
+
* Sets (or, with `null`, clears) this page's rating of one message and sends
|
|
7176
|
+
* it to the active Trajectory. Every change is a new event; the newest event
|
|
7177
|
+
* for a `feedbackId` is the current one. Like any Trajectory event, a change
|
|
7178
|
+
* made while no Trajectory captures, for example during a reconnect, is not
|
|
7179
|
+
* sent; the page still shows it.
|
|
7180
|
+
*/
|
|
7181
|
+
function setMessageFeedback(params) {
|
|
7182
|
+
const { copilotkit, agentId, threadId, message } = params;
|
|
7183
|
+
const comment = normalizeComment(params.feedback?.comment);
|
|
7184
|
+
const feedback = params.feedback && {
|
|
7185
|
+
rating: params.feedback.rating,
|
|
7186
|
+
...comment ? { comment } : {}
|
|
7187
|
+
};
|
|
7188
|
+
const key = messageKey(agentId, threadId, message.id);
|
|
7189
|
+
if (feedback) ratings.set(key, feedback);
|
|
7190
|
+
else ratings.delete(key);
|
|
7191
|
+
for (const listener of listeners.get(threadKey(agentId, threadId)) ?? []) listener();
|
|
7192
|
+
const runId = copilotkit.getRunIdForMessage(agentId, threadId, message.id);
|
|
7193
|
+
copilotkit.emitTrajectoryEvent(MESSAGE_FEEDBACK_EVENT_NAME, {
|
|
7194
|
+
feedbackId: `${threadId}:${message.id}`,
|
|
7195
|
+
threadId,
|
|
6488
7196
|
messageId: message.id,
|
|
6489
|
-
|
|
6490
|
-
|
|
6491
|
-
|
|
6492
|
-
|
|
6493
|
-
|
|
6494
|
-
|
|
6495
|
-
|
|
7197
|
+
agentId,
|
|
7198
|
+
...runId ? { runId } : {},
|
|
7199
|
+
rating: feedback?.rating ?? null,
|
|
7200
|
+
...feedback?.comment ? { comment: feedback.comment } : {},
|
|
7201
|
+
...copilotkit.ɵlearningCapturesAgentText ? { response: clip(message.content ?? "", RESPONSE_EXCERPT_LENGTH) } : {}
|
|
7202
|
+
});
|
|
7203
|
+
}
|
|
7204
|
+
|
|
7205
|
+
//#endregion
|
|
7206
|
+
//#region src/v2/components/chat/message-feedback.tsx
|
|
7207
|
+
/**
|
|
7208
|
+
* Set by the message view while Learning is on for this chat. Assistant
|
|
7209
|
+
* messages without it show thumbs only when the app passes its own handlers
|
|
7210
|
+
* or thumb slots.
|
|
7211
|
+
*/
|
|
7212
|
+
const MessageFeedbackScopeContext = createContext(null);
|
|
7213
|
+
const capturedCores = /* @__PURE__ */ new WeakSet();
|
|
7214
|
+
const rememberCapture = (copilotkit) => {
|
|
7215
|
+
if (capturedCores.has(copilotkit)) return;
|
|
7216
|
+
capturedCores.add(copilotkit);
|
|
7217
|
+
const unsubscribe = copilotkit.ɵsubscribeToLearningConfigured(() => {
|
|
7218
|
+
if (copilotkit.ɵlearningConfigured) return;
|
|
7219
|
+
capturedCores.delete(copilotkit);
|
|
7220
|
+
unsubscribe();
|
|
7221
|
+
});
|
|
7222
|
+
};
|
|
7223
|
+
/**
|
|
7224
|
+
* Whether the thumbs record feedback for Learning. True once a Trajectory of
|
|
7225
|
+
* this Core has started and as long as Learning stays configured, also while
|
|
7226
|
+
* capture reconnects or is stopped, so the buttons do not flicker. Ratings
|
|
7227
|
+
* given meanwhile still show but, like any Trajectory event, are not
|
|
7228
|
+
* sent. A capture that never starts (for example without a license) leaves it
|
|
7229
|
+
* false.
|
|
7230
|
+
*/
|
|
7231
|
+
function useLearningFeedbackEnabled(copilotkit) {
|
|
7232
|
+
const configured = useSyncExternalStore(useCallback((onChange) => copilotkit.ɵsubscribeToLearningConfigured(onChange), [copilotkit]), () => copilotkit.ɵlearningConfigured, () => false);
|
|
7233
|
+
const capturing = useSyncExternalStore(useCallback((onChange) => copilotkit.subscribe({ onTrajectoryChanged: onChange }).unsubscribe, [copilotkit]), () => copilotkit.trajectoryId !== null, () => false);
|
|
7234
|
+
useEffect(() => {
|
|
7235
|
+
if (capturing) rememberCapture(copilotkit);
|
|
7236
|
+
}, [capturing, copilotkit]);
|
|
7237
|
+
return configured && (capturing || capturedCores.has(copilotkit));
|
|
7238
|
+
}
|
|
7239
|
+
const noSubscription = () => () => {};
|
|
7240
|
+
/** Feedback controls for `message`, or `null` when this chat collects none. */
|
|
7241
|
+
function useMessageFeedback(message) {
|
|
7242
|
+
const scope = useContext(MessageFeedbackScopeContext);
|
|
7243
|
+
const subscribe = useCallback((onChange) => scope ? subscribeToMessageFeedback(scope.agentId, scope.threadId, onChange) : noSubscription(), [scope]);
|
|
7244
|
+
const getSnapshot = () => scope ? getMessageFeedback(scope.agentId, scope.threadId, message.id) : void 0;
|
|
7245
|
+
const feedback = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
7246
|
+
if (!scope) return null;
|
|
7247
|
+
const save = (next) => setMessageFeedback({
|
|
7248
|
+
...scope,
|
|
7249
|
+
message,
|
|
7250
|
+
feedback: next
|
|
7251
|
+
});
|
|
7252
|
+
return {
|
|
7253
|
+
feedback,
|
|
7254
|
+
rate: (rating) => {
|
|
7255
|
+
if (feedback?.rating !== rating) save({ rating });
|
|
7256
|
+
},
|
|
7257
|
+
clear: () => {
|
|
7258
|
+
if (feedback) save(null);
|
|
7259
|
+
},
|
|
7260
|
+
comment: (comment) => {
|
|
7261
|
+
if (feedback) save({
|
|
7262
|
+
rating: feedback.rating,
|
|
7263
|
+
comment
|
|
7264
|
+
});
|
|
7265
|
+
}
|
|
7266
|
+
};
|
|
7267
|
+
}
|
|
7268
|
+
/**
|
|
7269
|
+
* How long the pointer may be away from the rating and its comment before the
|
|
7270
|
+
* comment closes: enough to cross the gap between them, short enough that
|
|
7271
|
+
* passing over a rating does not leave it open.
|
|
7272
|
+
*/
|
|
7273
|
+
const FEEDBACK_COMMENT_CLOSE_DELAY_MS = 150;
|
|
7274
|
+
/**
|
|
7275
|
+
* Drives the comment popover of a rated message.
|
|
7276
|
+
*
|
|
7277
|
+
* It opens when a rating is given and whenever the pointer or keyboard focus
|
|
7278
|
+
* reaches the chosen thumb, with the saved comment in the field. It closes by
|
|
7279
|
+
* itself shortly after the pointer leaves the thumb and the popover, unless
|
|
7280
|
+
* focus is in the field: then it stays until focus moves away, Enter, or
|
|
7281
|
+
* Escape. Closing saves a changed comment; Escape, a click on a thumb, and
|
|
7282
|
+
* removing the rating discard it.
|
|
7283
|
+
*/
|
|
7284
|
+
function useFeedbackComment(controls) {
|
|
7285
|
+
const [open, setOpen] = useState(false);
|
|
7286
|
+
const [draft, setDraft] = useState("");
|
|
7287
|
+
const [focusRequest, setFocusRequest] = useState(0);
|
|
7288
|
+
const inputRef = useRef(null);
|
|
7289
|
+
const timer = useRef(void 0);
|
|
7290
|
+
const editing = useRef(false);
|
|
7291
|
+
const focusWaiting = useRef(false);
|
|
7292
|
+
const pointerOver = useRef(false);
|
|
7293
|
+
const returning = useRef(false);
|
|
7294
|
+
const latest = useRef({
|
|
7295
|
+
controls,
|
|
7296
|
+
draft,
|
|
7297
|
+
open
|
|
7298
|
+
});
|
|
7299
|
+
latest.current = {
|
|
7300
|
+
...latest.current,
|
|
7301
|
+
controls,
|
|
7302
|
+
draft,
|
|
7303
|
+
open
|
|
7304
|
+
};
|
|
7305
|
+
const takeFocusRequest = useCallback(() => {
|
|
7306
|
+
const waiting = focusWaiting.current;
|
|
7307
|
+
focusWaiting.current = false;
|
|
7308
|
+
return waiting;
|
|
7309
|
+
}, []);
|
|
7310
|
+
const cancelClose = useCallback(() => {
|
|
7311
|
+
if (timer.current === void 0) return;
|
|
7312
|
+
clearTimeout(timer.current);
|
|
7313
|
+
timer.current = void 0;
|
|
7314
|
+
}, []);
|
|
7315
|
+
useEffect(() => cancelClose, [cancelClose]);
|
|
7316
|
+
const savedComment = useCallback(() => latest.current.controls?.feedback?.comment ?? "", []);
|
|
7317
|
+
useEffect(() => () => {
|
|
7318
|
+
const { open: wasOpen, controls: current, draft: text } = latest.current;
|
|
7319
|
+
if (wasOpen && current?.feedback && text.trim() !== savedComment()) current.comment(text);
|
|
7320
|
+
}, []);
|
|
7321
|
+
const close = useCallback(({ save = true } = {}) => {
|
|
7322
|
+
cancelClose();
|
|
7323
|
+
focusWaiting.current = false;
|
|
7324
|
+
pointerOver.current = false;
|
|
7325
|
+
if (!latest.current.open) return;
|
|
7326
|
+
const current = latest.current.controls;
|
|
7327
|
+
if (save && current?.feedback && latest.current.draft.trim() !== savedComment()) current.comment(latest.current.draft);
|
|
7328
|
+
editing.current = false;
|
|
7329
|
+
latest.current = {
|
|
7330
|
+
...latest.current,
|
|
7331
|
+
open: false
|
|
7332
|
+
};
|
|
7333
|
+
setOpen(false);
|
|
7334
|
+
}, [cancelClose, savedComment]);
|
|
7335
|
+
const show = ({ comment, focus }) => {
|
|
7336
|
+
cancelClose();
|
|
7337
|
+
latest.current = {
|
|
7338
|
+
...latest.current,
|
|
7339
|
+
open: true,
|
|
7340
|
+
draft: comment
|
|
7341
|
+
};
|
|
7342
|
+
setDraft(comment);
|
|
7343
|
+
if (focus) {
|
|
7344
|
+
focusWaiting.current = true;
|
|
7345
|
+
setFocusRequest((request) => request + 1);
|
|
7346
|
+
}
|
|
7347
|
+
setOpen(true);
|
|
7348
|
+
};
|
|
7349
|
+
return {
|
|
7350
|
+
open,
|
|
7351
|
+
draft,
|
|
7352
|
+
setDraft,
|
|
7353
|
+
focusRequest,
|
|
7354
|
+
takeFocusRequest,
|
|
7355
|
+
inputRef,
|
|
7356
|
+
show,
|
|
7357
|
+
enter: (via = "focus") => {
|
|
7358
|
+
cancelClose();
|
|
7359
|
+
if (via === "pointer") pointerOver.current = true;
|
|
7360
|
+
if (returning.current) return;
|
|
7361
|
+
if (!latest.current.open && latest.current.controls?.feedback) show({
|
|
7362
|
+
comment: savedComment(),
|
|
7363
|
+
focus: false
|
|
7364
|
+
});
|
|
7365
|
+
},
|
|
7366
|
+
leave: (via = "focus") => {
|
|
7367
|
+
if (via === "pointer") pointerOver.current = false;
|
|
7368
|
+
else if (pointerOver.current) return;
|
|
7369
|
+
cancelClose();
|
|
7370
|
+
timer.current = setTimeout(() => {
|
|
7371
|
+
timer.current = void 0;
|
|
7372
|
+
if (!editing.current) close();
|
|
7373
|
+
}, FEEDBACK_COMMENT_CLOSE_DELAY_MS);
|
|
7374
|
+
},
|
|
7375
|
+
setEditing: (value) => {
|
|
7376
|
+
editing.current = value;
|
|
7377
|
+
},
|
|
7378
|
+
close,
|
|
7379
|
+
returnFocus: (target) => {
|
|
7380
|
+
returning.current = true;
|
|
7381
|
+
try {
|
|
7382
|
+
target?.focus();
|
|
7383
|
+
} finally {
|
|
7384
|
+
returning.current = false;
|
|
7385
|
+
}
|
|
7386
|
+
}
|
|
7387
|
+
};
|
|
7388
|
+
}
|
|
7389
|
+
|
|
7390
|
+
//#endregion
|
|
7391
|
+
//#region src/v2/components/chat/CopilotChatAssistantMessage.tsx
|
|
7392
|
+
/**
|
|
7393
|
+
* In the `"turn"` tool-call display, text in a reply's working phase was
|
|
7394
|
+
* narration: it fades to muted once a call follows it, and folds away with the
|
|
7395
|
+
* rest of the work when the reply is done. The wrapper is there for every
|
|
7396
|
+
* message in that display, so text that turns into narration keeps its node
|
|
7397
|
+
* (and its place) rather than remounting.
|
|
7398
|
+
*/
|
|
7399
|
+
function WorkText({ messageId, children }) {
|
|
7400
|
+
const context = useContext(ToolCallDisplayContext);
|
|
7401
|
+
if (context?.display !== "turn") return children;
|
|
7402
|
+
const open = context.workTextOpen.get(messageId);
|
|
7403
|
+
return /* @__PURE__ */ jsx(Collapsible, {
|
|
7404
|
+
open: open ?? true,
|
|
7405
|
+
className: "cpk:-mx-2",
|
|
7406
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
7407
|
+
className: "cpk:px-2",
|
|
7408
|
+
"data-work-text": open === void 0 ? "reply" : "narration",
|
|
7409
|
+
children
|
|
7410
|
+
})
|
|
7411
|
+
});
|
|
7412
|
+
}
|
|
7413
|
+
/**
|
|
7414
|
+
* Binds the Inspector action to the active chat without making the full
|
|
7415
|
+
* assistant message subscribe to chat configuration changes.
|
|
7416
|
+
*/
|
|
7417
|
+
function BoundInspectorButton({ inspectorButton, messageId, openInspector, ...props }) {
|
|
7418
|
+
const chatConfiguration = useCopilotChatConfiguration();
|
|
7419
|
+
return renderSlot(inspectorButton, CopilotChatAssistantMessage.InspectorButton, {
|
|
7420
|
+
...props,
|
|
7421
|
+
onClick: () => openInspector({
|
|
7422
|
+
messageId,
|
|
7423
|
+
threadId: chatConfiguration?.threadId,
|
|
7424
|
+
agentId: chatConfiguration?.agentId
|
|
7425
|
+
})
|
|
7426
|
+
});
|
|
7427
|
+
}
|
|
7428
|
+
/** Whether focus came from the keyboard; a pointer click also focuses buttons. */
|
|
7429
|
+
function isFocusVisible(element) {
|
|
7430
|
+
try {
|
|
7431
|
+
return element.matches(":focus-visible");
|
|
7432
|
+
} catch {
|
|
7433
|
+
return false;
|
|
7434
|
+
}
|
|
7435
|
+
}
|
|
7436
|
+
const HIDDEN_TOO = {
|
|
7437
|
+
checkVisibilityCSS: true,
|
|
7438
|
+
visibilityProperty: true
|
|
7439
|
+
};
|
|
7440
|
+
const FOCUSABLE = [
|
|
7441
|
+
"a[href]",
|
|
7442
|
+
"button:not([disabled])",
|
|
7443
|
+
"input:not([disabled])",
|
|
7444
|
+
"select:not([disabled])",
|
|
7445
|
+
"textarea:not([disabled])",
|
|
7446
|
+
"[tabindex]"
|
|
7447
|
+
].map((selector) => `${selector}:not([tabindex="-1"]):not([data-radix-focus-guard])`).join(", ");
|
|
7448
|
+
/** Approximately the element Tab reaches after `element`, outside `skip`. */
|
|
7449
|
+
function nextFocusable(element, skip) {
|
|
7450
|
+
const all = Array.from(element.ownerDocument.querySelectorAll(FOCUSABLE)).filter((candidate) => candidate === element || !skip?.contains(candidate) && !candidate.closest("[hidden], [inert]"));
|
|
7451
|
+
const index = all.indexOf(element);
|
|
7452
|
+
return index === -1 ? null : all[index + 1] ?? null;
|
|
7453
|
+
}
|
|
7454
|
+
/**
|
|
7455
|
+
* The comment popover of a rated message, pointing at the chosen thumb. Kept
|
|
7456
|
+
* apart so only it, not the whole message, follows chat configuration.
|
|
7457
|
+
*
|
|
7458
|
+
* The popover lives in a portal, so it keeps keyboard order by hand: Shift+Tab
|
|
7459
|
+
* from its start returns to the thumb, Tab from its end moves on to the
|
|
7460
|
+
* control after the thumb, and Enter or Escape inside it returns to the thumb.
|
|
7461
|
+
*/
|
|
7462
|
+
function FeedbackCommentPopover({ feedbackComment, comment, savedComment, rating, anchor, messageId }) {
|
|
7463
|
+
const labels = useCopilotChatConfiguration()?.labels ?? CopilotChatDefaultLabels;
|
|
7464
|
+
const contentRef = useRef(null);
|
|
7465
|
+
const focusInside = () => contentRef.current?.contains(document.activeElement) ?? false;
|
|
7466
|
+
const { focusRequest, takeFocusRequest, inputRef } = comment;
|
|
7467
|
+
const focusField = useCallback(() => {
|
|
7468
|
+
if (inputRef.current && takeFocusRequest()) inputRef.current.focus();
|
|
7469
|
+
}, [inputRef, takeFocusRequest]);
|
|
7470
|
+
useEffect(() => focusField(), [focusRequest, focusField]);
|
|
7471
|
+
/** Whether `target` is a thumb of this message, whose click decides itself. */
|
|
7472
|
+
const isOwnThumb = (target) => {
|
|
7473
|
+
return (target instanceof Element ? target.closest("[data-copilotkit-rating]") : null)?.closest("[data-message-id]")?.getAttribute("data-message-id") === messageId;
|
|
7474
|
+
};
|
|
7475
|
+
return /* @__PURE__ */ jsxs(Popover, {
|
|
7476
|
+
open: comment.open,
|
|
7477
|
+
onOpenChange: (open) => {
|
|
7478
|
+
if (!open) comment.close();
|
|
7479
|
+
},
|
|
7480
|
+
children: [/* @__PURE__ */ jsx(PopoverAnchor, { virtualRef: anchor }), /* @__PURE__ */ jsx(PopoverContent, {
|
|
7481
|
+
ref: contentRef,
|
|
7482
|
+
side: "bottom",
|
|
7483
|
+
collisionPadding: 8,
|
|
7484
|
+
hideWhenDetached: true,
|
|
7485
|
+
"aria-label": labels.assistantMessageFeedbackCommentPlaceholder,
|
|
7486
|
+
"data-copilotkit-ignore": true,
|
|
7487
|
+
onOpenAutoFocus: (event) => {
|
|
7488
|
+
event.preventDefault();
|
|
7489
|
+
focusField();
|
|
7490
|
+
},
|
|
7491
|
+
onCloseAutoFocus: (event) => event.preventDefault(),
|
|
7492
|
+
onInteractOutside: (event) => {
|
|
7493
|
+
if (isOwnThumb(event.target)) event.preventDefault();
|
|
7494
|
+
},
|
|
7495
|
+
onEscapeKeyDown: (event) => {
|
|
7496
|
+
const returnFocus = focusInside();
|
|
7497
|
+
if (returnFocus) event.stopPropagation();
|
|
7498
|
+
comment.close({ save: false });
|
|
7499
|
+
if (returnFocus) comment.returnFocus(anchor.current);
|
|
7500
|
+
},
|
|
7501
|
+
onKeyDown: (event) => {
|
|
7502
|
+
if (event.key !== "Tab") return;
|
|
7503
|
+
const focusables = Array.from(contentRef.current?.querySelectorAll(FOCUSABLE) ?? []);
|
|
7504
|
+
if (!(event.shiftKey ? document.activeElement === focusables[0] : document.activeElement === focusables[focusables.length - 1]) || !anchor.current?.isConnected) return;
|
|
7505
|
+
event.preventDefault();
|
|
7506
|
+
const target = event.shiftKey ? anchor.current : nextFocusable(anchor.current, contentRef.current) ?? anchor.current;
|
|
7507
|
+
comment.close();
|
|
7508
|
+
if (target === anchor.current) comment.returnFocus(target);
|
|
7509
|
+
else target.focus();
|
|
7510
|
+
},
|
|
7511
|
+
onPointerEnter: () => comment.enter("pointer"),
|
|
7512
|
+
onPointerLeave: () => comment.leave("pointer"),
|
|
7513
|
+
className: "cpk:z-[1300]",
|
|
7514
|
+
children: /* @__PURE__ */ jsx(Fragment, { children: renderSlot(feedbackComment, CopilotChatAssistantMessage.FeedbackComment, {
|
|
7515
|
+
value: comment.draft,
|
|
7516
|
+
savedComment,
|
|
7517
|
+
inputRef: comment.inputRef,
|
|
7518
|
+
onChange: comment.setDraft,
|
|
7519
|
+
onSubmit: () => {
|
|
7520
|
+
comment.close();
|
|
7521
|
+
comment.returnFocus(anchor.current);
|
|
7522
|
+
},
|
|
7523
|
+
onEditingChange: comment.setEditing,
|
|
7524
|
+
onLeave: (next) => {
|
|
7525
|
+
if (next && (contentRef.current?.contains(next) || isOwnThumb(next))) return;
|
|
7526
|
+
comment.leave();
|
|
7527
|
+
}
|
|
7528
|
+
}) }, rating)
|
|
7529
|
+
})]
|
|
7530
|
+
});
|
|
7531
|
+
}
|
|
7532
|
+
function CopilotChatAssistantMessage({ message, messages, isRunning, isLatest, onThumbsUp, onThumbsDown, onReadAloud, onRegenerate, additionalToolbarItems, toolbarVisible = true, markdownRenderer, toolbar, copyButton, inspectorButton, thumbsUpButton, thumbsDownButton, readAloudButton, regenerateButton, feedbackComment: feedbackCommentSlot, toolCallsView, children, className, ...props }) {
|
|
7533
|
+
useKatexStyles();
|
|
7534
|
+
const { isInspectorEnabled, openInspector } = useCopilotKitInspector();
|
|
7535
|
+
const shortcutsHidden = useInspectorShortcutsHidden();
|
|
7536
|
+
const showInspectorShortcut = isInspectorEnabled && !shortcutsHidden;
|
|
7537
|
+
const feedback = useMessageFeedback(message);
|
|
7538
|
+
const comment = useFeedbackComment(feedback);
|
|
7539
|
+
const rating = feedback?.feedback?.rating;
|
|
7540
|
+
const root = useRef(null);
|
|
7541
|
+
const commentAnchor = useRef(null);
|
|
7542
|
+
const commentRating = useRef(rating);
|
|
7543
|
+
useLayoutEffect(() => {
|
|
7544
|
+
if (comment.open && !commentAnchor.current?.isConnected && rating) commentAnchor.current = root.current?.querySelector(`[data-copilotkit-rating="${rating}"]`) ?? root.current?.querySelector("button[aria-pressed=\"true\"]") ?? null;
|
|
7545
|
+
});
|
|
7546
|
+
/**
|
|
7547
|
+
* Thumbs are toggles: a new rating is saved and opens its comment, and
|
|
7548
|
+
* clicking the chosen thumb again removes the rating. A keyboard click
|
|
7549
|
+
* (`detail` 0) moves focus into the comment, as there is no pointer.
|
|
7550
|
+
* Custom thumb slots may call `onClick` without an event.
|
|
7551
|
+
*
|
|
7552
|
+
* @returns Whether the app's handler should run: true for a new rating and
|
|
7553
|
+
* whenever this chat does not record ratings, false when one is removed.
|
|
7554
|
+
*/
|
|
7555
|
+
const rate = (value, event) => {
|
|
7556
|
+
if (!feedback) return true;
|
|
7557
|
+
if (rating === value) {
|
|
7558
|
+
comment.close({ save: false });
|
|
7559
|
+
feedback.clear();
|
|
7560
|
+
return false;
|
|
7561
|
+
}
|
|
7562
|
+
feedback.rate(value);
|
|
7563
|
+
commentRating.current = value;
|
|
7564
|
+
commentAnchor.current = event?.currentTarget ?? null;
|
|
7565
|
+
comment.show({
|
|
7566
|
+
comment: "",
|
|
7567
|
+
focus: event?.detail === 0
|
|
7568
|
+
});
|
|
7569
|
+
return true;
|
|
7570
|
+
};
|
|
7571
|
+
/** Props that let the chosen thumb open and point at its comment. */
|
|
7572
|
+
const thumbFeedbackProps = (value) => {
|
|
7573
|
+
if (!feedback) return {};
|
|
7574
|
+
const thumb = { "data-copilotkit-rating": value };
|
|
7575
|
+
if (rating !== value) return {
|
|
7576
|
+
...thumb,
|
|
7577
|
+
"aria-pressed": false
|
|
7578
|
+
};
|
|
7579
|
+
const enter = (target, via) => {
|
|
7580
|
+
if (!comment.open) commentRating.current = value;
|
|
7581
|
+
commentAnchor.current = target;
|
|
7582
|
+
comment.enter(via);
|
|
7583
|
+
};
|
|
7584
|
+
return {
|
|
7585
|
+
...thumb,
|
|
7586
|
+
"aria-pressed": true,
|
|
7587
|
+
"aria-haspopup": "dialog",
|
|
7588
|
+
"aria-expanded": comment.open,
|
|
7589
|
+
onPointerEnter: (event) => {
|
|
7590
|
+
if (event.pointerType !== "touch") enter(event.currentTarget, "pointer");
|
|
7591
|
+
},
|
|
7592
|
+
onPointerLeave: (event) => {
|
|
7593
|
+
if (event.pointerType !== "touch") comment.leave("pointer");
|
|
7594
|
+
},
|
|
7595
|
+
onFocus: (event) => {
|
|
7596
|
+
if (isFocusVisible(event.currentTarget)) enter(event.currentTarget, "focus");
|
|
7597
|
+
},
|
|
7598
|
+
onBlur: () => comment.leave(),
|
|
7599
|
+
onKeyDown: (event) => {
|
|
7600
|
+
const input = comment.inputRef.current;
|
|
7601
|
+
if (event.key === "Tab" && !event.shiftKey && comment.open && input && input.checkVisibility?.(HIDDEN_TOO) !== false) {
|
|
7602
|
+
event.preventDefault();
|
|
7603
|
+
input.focus();
|
|
7604
|
+
}
|
|
7605
|
+
}
|
|
7606
|
+
};
|
|
7607
|
+
};
|
|
7608
|
+
const boundMarkdownRenderer = renderSlot(markdownRenderer, CopilotChatAssistantMessage.MarkdownRenderer, { content: message.content || "" });
|
|
7609
|
+
const boundCopyButton = renderSlot(copyButton, CopilotChatAssistantMessage.CopyButton, { onClick: async () => {
|
|
7610
|
+
if (message.content) return await copyToClipboard(message.content);
|
|
7611
|
+
return false;
|
|
7612
|
+
} });
|
|
7613
|
+
const boundThumbsUpButton = renderSlot(thumbsUpButton, CopilotChatAssistantMessage.ThumbsUpButton, {
|
|
7614
|
+
onClick: onThumbsUp || feedback ? (event) => {
|
|
7615
|
+
if (rate("up", event)) onThumbsUp?.(message);
|
|
7616
|
+
} : void 0,
|
|
7617
|
+
...thumbFeedbackProps("up")
|
|
7618
|
+
});
|
|
7619
|
+
const boundInspectorButton = showInspectorShortcut ? /* @__PURE__ */ jsx(BoundInspectorButton, {
|
|
7620
|
+
inspectorButton,
|
|
7621
|
+
messageId: message.id,
|
|
7622
|
+
openInspector
|
|
7623
|
+
}) : /* @__PURE__ */ jsx(Fragment$1, {});
|
|
7624
|
+
const boundThumbsDownButton = renderSlot(thumbsDownButton, CopilotChatAssistantMessage.ThumbsDownButton, {
|
|
7625
|
+
onClick: onThumbsDown || feedback ? (event) => {
|
|
7626
|
+
if (rate("down", event)) onThumbsDown?.(message);
|
|
7627
|
+
} : void 0,
|
|
7628
|
+
...thumbFeedbackProps("down")
|
|
7629
|
+
});
|
|
7630
|
+
const boundReadAloudButton = renderSlot(readAloudButton, CopilotChatAssistantMessage.ReadAloudButton, { onClick: onReadAloud ? () => onReadAloud(message) : void 0 });
|
|
7631
|
+
const boundRegenerateButton = renderSlot(regenerateButton, CopilotChatAssistantMessage.RegenerateButton, { onClick: onRegenerate ? () => onRegenerate(message) : void 0 });
|
|
7632
|
+
const boundToolbar = renderSlot(toolbar, CopilotChatAssistantMessage.Toolbar, { children: /* @__PURE__ */ jsxs("div", {
|
|
7633
|
+
className: "cpk:flex cpk:w-full cpk:items-center cpk:gap-1",
|
|
6496
7634
|
children: [
|
|
6497
7635
|
boundCopyButton,
|
|
6498
|
-
(onThumbsUp || thumbsUpButton) && boundThumbsUpButton,
|
|
6499
|
-
(onThumbsDown || thumbsDownButton) && boundThumbsDownButton,
|
|
7636
|
+
(onThumbsUp || thumbsUpButton || feedback) && boundThumbsUpButton,
|
|
7637
|
+
(onThumbsDown || thumbsDownButton || feedback) && boundThumbsDownButton,
|
|
6500
7638
|
(onReadAloud || readAloudButton) && boundReadAloudButton,
|
|
6501
7639
|
(onRegenerate || regenerateButton) && boundRegenerateButton,
|
|
6502
7640
|
additionalToolbarItems,
|
|
@@ -6510,11 +7648,31 @@ function CopilotChatAssistantMessage({ message, messages, isRunning, isLatest, o
|
|
|
6510
7648
|
const hasContent = !!(message.content && message.content.trim().length > 0);
|
|
6511
7649
|
const isLatestAssistantMessage = message.role === "assistant" && (isLatest ?? messages?.[messages.length - 1]?.id === message.id);
|
|
6512
7650
|
const shouldShowToolbar = toolbarVisible && (hasContent || showInspectorShortcut) && !(isRunning && isLatestAssistantMessage);
|
|
6513
|
-
|
|
7651
|
+
const { open: commentOpen, close: closeComment } = comment;
|
|
7652
|
+
useEffect(() => {
|
|
7653
|
+
if (!commentOpen) return;
|
|
7654
|
+
if (rating !== commentRating.current) closeComment({ save: false });
|
|
7655
|
+
else if (!shouldShowToolbar) closeComment();
|
|
7656
|
+
}, [
|
|
7657
|
+
commentOpen,
|
|
7658
|
+
shouldShowToolbar,
|
|
7659
|
+
rating,
|
|
7660
|
+
closeComment
|
|
7661
|
+
]);
|
|
7662
|
+
const feedbackComment = feedback?.feedback && shouldShowToolbar && /* @__PURE__ */ jsx(FeedbackCommentPopover, {
|
|
7663
|
+
feedbackComment: feedbackCommentSlot,
|
|
7664
|
+
comment,
|
|
7665
|
+
savedComment: feedback.feedback.comment ?? "",
|
|
7666
|
+
rating: feedback.feedback.rating,
|
|
7667
|
+
anchor: commentAnchor,
|
|
7668
|
+
messageId: message.id
|
|
7669
|
+
});
|
|
7670
|
+
if (children) return /* @__PURE__ */ jsxs("div", {
|
|
7671
|
+
ref: root,
|
|
6514
7672
|
"data-copilotkit": true,
|
|
6515
7673
|
"data-message-id": message.id,
|
|
6516
7674
|
style: { display: "contents" },
|
|
6517
|
-
children: children({
|
|
7675
|
+
children: [children({
|
|
6518
7676
|
markdownRenderer: boundMarkdownRenderer,
|
|
6519
7677
|
toolbar: boundToolbar,
|
|
6520
7678
|
toolCallsView: boundToolCallsView,
|
|
@@ -6533,21 +7691,26 @@ function CopilotChatAssistantMessage({ message, messages, isRunning, isLatest, o
|
|
|
6533
7691
|
onRegenerate,
|
|
6534
7692
|
additionalToolbarItems,
|
|
6535
7693
|
toolbarVisible: shouldShowToolbar
|
|
6536
|
-
})
|
|
7694
|
+
}), feedbackComment]
|
|
6537
7695
|
});
|
|
6538
7696
|
return /* @__PURE__ */ jsxs("div", {
|
|
7697
|
+
ref: root,
|
|
6539
7698
|
"data-copilotkit": true,
|
|
6540
7699
|
"data-testid": "copilot-assistant-message",
|
|
6541
7700
|
className: twMerge("copilotKitMessage copilotKitAssistantMessage", className),
|
|
6542
7701
|
...props,
|
|
6543
7702
|
"data-message-id": message.id,
|
|
6544
7703
|
children: [
|
|
6545
|
-
/* @__PURE__ */ jsx(
|
|
6546
|
-
|
|
6547
|
-
children:
|
|
7704
|
+
/* @__PURE__ */ jsx(WorkText, {
|
|
7705
|
+
messageId: message.id,
|
|
7706
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
7707
|
+
className: "cpk:prose cpk:max-w-full cpk:break-words cpk:dark:prose-invert",
|
|
7708
|
+
children: boundMarkdownRenderer
|
|
7709
|
+
})
|
|
6548
7710
|
}),
|
|
6549
7711
|
boundToolCallsView,
|
|
6550
|
-
shouldShowToolbar && boundToolbar
|
|
7712
|
+
shouldShowToolbar && boundToolbar,
|
|
7713
|
+
feedbackComment
|
|
6551
7714
|
]
|
|
6552
7715
|
});
|
|
6553
7716
|
}
|
|
@@ -6563,20 +7726,27 @@ function CopilotChatAssistantMessage({ message, messages, isRunning, isLatest, o
|
|
|
6563
7726
|
...props
|
|
6564
7727
|
});
|
|
6565
7728
|
const ToolbarButton = _CopilotChatAssistantMessage.ToolbarButton = ({ title, tooltip, tooltipClassName, children, ...props }) => {
|
|
6566
|
-
|
|
6567
|
-
|
|
6568
|
-
|
|
6569
|
-
|
|
6570
|
-
|
|
6571
|
-
|
|
6572
|
-
|
|
6573
|
-
|
|
6574
|
-
|
|
6575
|
-
|
|
6576
|
-
|
|
6577
|
-
|
|
6578
|
-
|
|
6579
|
-
|
|
7729
|
+
const [tooltipOpen, setTooltipOpen] = useState(false);
|
|
7730
|
+
const popupOpen = props["aria-expanded"] === true;
|
|
7731
|
+
if (popupOpen && tooltipOpen) setTooltipOpen(false);
|
|
7732
|
+
return /* @__PURE__ */ jsxs(Tooltip, {
|
|
7733
|
+
open: tooltipOpen && !popupOpen,
|
|
7734
|
+
onOpenChange: (open) => setTooltipOpen(open && !popupOpen),
|
|
7735
|
+
children: [/* @__PURE__ */ jsx(TooltipTrigger, {
|
|
7736
|
+
asChild: true,
|
|
7737
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
7738
|
+
type: "button",
|
|
7739
|
+
variant: "assistantMessageToolbarButton",
|
|
7740
|
+
"aria-label": title,
|
|
7741
|
+
...props,
|
|
7742
|
+
children
|
|
7743
|
+
})
|
|
7744
|
+
}), /* @__PURE__ */ jsx(TooltipContent, {
|
|
7745
|
+
side: "bottom",
|
|
7746
|
+
className: tooltipClassName,
|
|
7747
|
+
children: tooltip ?? /* @__PURE__ */ jsx("p", { children: title })
|
|
7748
|
+
})]
|
|
7749
|
+
});
|
|
6580
7750
|
};
|
|
6581
7751
|
_CopilotChatAssistantMessage.CopyButton = ({ className, title, onClick, ...props }) => {
|
|
6582
7752
|
const labels = useCopilotChatConfiguration()?.labels ?? CopilotChatDefaultLabels;
|
|
@@ -6615,7 +7785,10 @@ function CopilotChatAssistantMessage({ message, messages, isRunning, isLatest, o
|
|
|
6615
7785
|
"data-testid": "copilot-thumbs-up-button",
|
|
6616
7786
|
title: title || labels.assistantMessageToolbarThumbsUpLabel,
|
|
6617
7787
|
...props,
|
|
6618
|
-
children: /* @__PURE__ */ jsx(ThumbsUp, {
|
|
7788
|
+
children: /* @__PURE__ */ jsx(ThumbsUp, {
|
|
7789
|
+
className: "cpk:size-[18px]",
|
|
7790
|
+
fill: props["aria-pressed"] === true ? "currentColor" : "none"
|
|
7791
|
+
})
|
|
6619
7792
|
});
|
|
6620
7793
|
};
|
|
6621
7794
|
_CopilotChatAssistantMessage.ThumbsDownButton = ({ title, ...props }) => {
|
|
@@ -6624,7 +7797,45 @@ function CopilotChatAssistantMessage({ message, messages, isRunning, isLatest, o
|
|
|
6624
7797
|
"data-testid": "copilot-thumbs-down-button",
|
|
6625
7798
|
title: title || labels.assistantMessageToolbarThumbsDownLabel,
|
|
6626
7799
|
...props,
|
|
6627
|
-
children: /* @__PURE__ */ jsx(ThumbsDown, {
|
|
7800
|
+
children: /* @__PURE__ */ jsx(ThumbsDown, {
|
|
7801
|
+
className: "cpk:size-[18px]",
|
|
7802
|
+
fill: props["aria-pressed"] === true ? "currentColor" : "none"
|
|
7803
|
+
})
|
|
7804
|
+
});
|
|
7805
|
+
};
|
|
7806
|
+
_CopilotChatAssistantMessage.FeedbackComment = ({ value, savedComment, inputRef, onChange, onSubmit, onEditingChange, onLeave, className }) => {
|
|
7807
|
+
const labels = useCopilotChatConfiguration()?.labels ?? CopilotChatDefaultLabels;
|
|
7808
|
+
const changed = value.trim() !== savedComment;
|
|
7809
|
+
return /* @__PURE__ */ jsxs("form", {
|
|
7810
|
+
"data-testid": "copilot-feedback-comment",
|
|
7811
|
+
className: twMerge("cpk:flex cpk:w-80 cpk:max-w-[calc(100vw-1rem)] cpk:items-center cpk:gap-1 cpk:rounded-full cpk:border cpk:border-border cpk:bg-background cpk:py-0.5 cpk:pl-3 cpk:pr-0.5 cpk:text-sm cpk:shadow-md", className),
|
|
7812
|
+
onSubmit: (event) => {
|
|
7813
|
+
event.preventDefault();
|
|
7814
|
+
onSubmit();
|
|
7815
|
+
},
|
|
7816
|
+
onFocus: () => onEditingChange?.(true),
|
|
7817
|
+
onBlur: (event) => {
|
|
7818
|
+
const next = event.relatedTarget instanceof Element ? event.relatedTarget : null;
|
|
7819
|
+
if (event.currentTarget.contains(next)) return;
|
|
7820
|
+
if (typeof document !== "undefined" && !document.hasFocus()) return;
|
|
7821
|
+
onEditingChange?.(false);
|
|
7822
|
+
onLeave?.(next);
|
|
7823
|
+
},
|
|
7824
|
+
children: [/* @__PURE__ */ jsx("input", {
|
|
7825
|
+
ref: inputRef,
|
|
7826
|
+
value,
|
|
7827
|
+
maxLength: MESSAGE_FEEDBACK_MAX_COMMENT_LENGTH,
|
|
7828
|
+
onChange: (event) => onChange(event.target.value),
|
|
7829
|
+
placeholder: labels.assistantMessageFeedbackCommentPlaceholder,
|
|
7830
|
+
"aria-label": labels.assistantMessageFeedbackCommentPlaceholder,
|
|
7831
|
+
className: "cpk:min-w-0 cpk:flex-1 cpk:bg-transparent cpk:py-1 cpk:text-foreground cpk:outline-none cpk:placeholder:text-muted-foreground"
|
|
7832
|
+
}), changed && /* @__PURE__ */ jsx(Button, {
|
|
7833
|
+
type: "submit",
|
|
7834
|
+
variant: "assistantMessageToolbarButton",
|
|
7835
|
+
"aria-label": labels.assistantMessageFeedbackCommentSubmitLabel,
|
|
7836
|
+
title: labels.assistantMessageFeedbackCommentSubmitLabel,
|
|
7837
|
+
children: /* @__PURE__ */ jsx(ArrowUp, { className: "cpk:size-[16px]" })
|
|
7838
|
+
})]
|
|
6628
7839
|
});
|
|
6629
7840
|
};
|
|
6630
7841
|
_CopilotChatAssistantMessage.ReadAloudButton = ({ title, ...props }) => {
|
|
@@ -6652,6 +7863,7 @@ CopilotChatAssistantMessage.CopyButton.displayName = "CopilotChatAssistantMessag
|
|
|
6652
7863
|
CopilotChatAssistantMessage.InspectorButton.displayName = "CopilotChatAssistantMessage.InspectorButton";
|
|
6653
7864
|
CopilotChatAssistantMessage.ThumbsUpButton.displayName = "CopilotChatAssistantMessage.ThumbsUpButton";
|
|
6654
7865
|
CopilotChatAssistantMessage.ThumbsDownButton.displayName = "CopilotChatAssistantMessage.ThumbsDownButton";
|
|
7866
|
+
CopilotChatAssistantMessage.FeedbackComment.displayName = "CopilotChatAssistantMessage.FeedbackComment";
|
|
6655
7867
|
CopilotChatAssistantMessage.ReadAloudButton.displayName = "CopilotChatAssistantMessage.ReadAloudButton";
|
|
6656
7868
|
CopilotChatAssistantMessage.RegenerateButton.displayName = "CopilotChatAssistantMessage.RegenerateButton";
|
|
6657
7869
|
var CopilotChatAssistantMessage_default = CopilotChatAssistantMessage;
|
|
@@ -6957,6 +8169,7 @@ function CopilotChatUserMessage({ message, onEditMessage, branchIndex, numberOfB
|
|
|
6957
8169
|
});
|
|
6958
8170
|
};
|
|
6959
8171
|
_CopilotChatUserMessage.BranchNavigation = ({ className, currentBranch = 0, numberOfBranches = 1, onSwitchToBranch, message, ...props }) => {
|
|
8172
|
+
const labels = useCopilotChatConfiguration()?.labels ?? CopilotChatDefaultLabels;
|
|
6960
8173
|
if (!numberOfBranches || numberOfBranches <= 1 || !onSwitchToBranch) return null;
|
|
6961
8174
|
const canGoPrev = currentBranch > 0;
|
|
6962
8175
|
const canGoNext = currentBranch < numberOfBranches - 1;
|
|
@@ -6975,6 +8188,7 @@ function CopilotChatUserMessage({ message, onEditMessage, branchIndex, numberOfB
|
|
|
6975
8188
|
}),
|
|
6976
8189
|
disabled: !canGoPrev,
|
|
6977
8190
|
className: "cpk:h-6 cpk:w-6 cpk:p-0",
|
|
8191
|
+
"aria-label": labels.userMessageToolbarPreviousBranchLabel,
|
|
6978
8192
|
children: /* @__PURE__ */ jsx(ChevronLeft, { className: "cpk:size-[20px]" })
|
|
6979
8193
|
}),
|
|
6980
8194
|
/* @__PURE__ */ jsxs("span", {
|
|
@@ -6995,6 +8209,7 @@ function CopilotChatUserMessage({ message, onEditMessage, branchIndex, numberOfB
|
|
|
6995
8209
|
}),
|
|
6996
8210
|
disabled: !canGoNext,
|
|
6997
8211
|
className: "cpk:h-6 cpk:w-6 cpk:p-0",
|
|
8212
|
+
"aria-label": labels.userMessageToolbarNextBranchLabel,
|
|
6998
8213
|
children: /* @__PURE__ */ jsx(ChevronRight, { className: "cpk:size-[20px]" })
|
|
6999
8214
|
})
|
|
7000
8215
|
]
|
|
@@ -7015,7 +8230,7 @@ var CopilotChatUserMessage_default = CopilotChatUserMessage;
|
|
|
7015
8230
|
/**
|
|
7016
8231
|
* Formats an elapsed duration (in seconds) to a human-readable string.
|
|
7017
8232
|
*/
|
|
7018
|
-
function formatDuration(seconds) {
|
|
8233
|
+
function formatDuration$1(seconds) {
|
|
7019
8234
|
if (seconds < 1) return "a few seconds";
|
|
7020
8235
|
if (seconds < 60) return `${Math.round(seconds)} seconds`;
|
|
7021
8236
|
const mins = Math.floor(seconds / 60);
|
|
@@ -7053,7 +8268,7 @@ function CopilotChatReasoningMessage({ message, messages, isRunning, isLatest: i
|
|
|
7053
8268
|
userToggledRef.current = true;
|
|
7054
8269
|
setIsOpen((prev) => !prev);
|
|
7055
8270
|
} : void 0;
|
|
7056
|
-
const label = isStreaming ? "Thinking…" : `Thought for ${formatDuration(elapsed)}`;
|
|
8271
|
+
const label = isStreaming ? "Thinking…" : `Thought for ${formatDuration$1(elapsed)}`;
|
|
7057
8272
|
const boundHeader = renderSlot(header, CopilotChatReasoningMessage.Header, {
|
|
7058
8273
|
isOpen,
|
|
7059
8274
|
label,
|
|
@@ -7275,6 +8490,71 @@ const ScrollElementContext = React.createContext(null);
|
|
|
7275
8490
|
*/
|
|
7276
8491
|
const ScrollPinnedContext = React.createContext(false);
|
|
7277
8492
|
|
|
8493
|
+
//#endregion
|
|
8494
|
+
//#region src/v2/components/chat/CopilotChatWorkSummary.tsx
|
|
8495
|
+
/** "45s", "1m 5s", "2m". Used for the live timer and the final duration. */
|
|
8496
|
+
function formatDuration(ms) {
|
|
8497
|
+
const seconds = Math.max(0, Math.floor(ms / 1e3));
|
|
8498
|
+
if (seconds < 60) return `${seconds}s`;
|
|
8499
|
+
const minutes = Math.floor(seconds / 60);
|
|
8500
|
+
const rest = seconds % 60;
|
|
8501
|
+
return rest ? `${minutes}m ${rest}s` : `${minutes}m`;
|
|
8502
|
+
}
|
|
8503
|
+
/** Re-renders every second while `active`, returning the current time. */
|
|
8504
|
+
function useNow(active) {
|
|
8505
|
+
const [now, setNow] = useState(() => Date.now());
|
|
8506
|
+
useEffect(() => {
|
|
8507
|
+
if (!active) return;
|
|
8508
|
+
setNow(Date.now());
|
|
8509
|
+
const timer = setInterval(() => setNow(Date.now()), 1e3);
|
|
8510
|
+
return () => clearInterval(timer);
|
|
8511
|
+
}, [active]);
|
|
8512
|
+
return now;
|
|
8513
|
+
}
|
|
8514
|
+
/**
|
|
8515
|
+
* The line at the top of a reply in the `"turn"` tool-call display. While the
|
|
8516
|
+
* agent works it reads "Working 4s"; once the reply is done it reads "Worked
|
|
8517
|
+
* for 9s · 7 tools" and toggles the work it folded away.
|
|
8518
|
+
*/
|
|
8519
|
+
function CopilotChatWorkSummary({ isWorking, isOpen, calls, elapsedMs, workingSince, className, ...props }) {
|
|
8520
|
+
const now = useNow(isWorking);
|
|
8521
|
+
const failed = calls.filter((call) => call.toolMessage?.error).length;
|
|
8522
|
+
const liveMs = elapsedMs !== void 0 && workingSince !== void 0 ? elapsedMs + Math.max(0, now - workingSince) : void 0;
|
|
8523
|
+
const duration = elapsedMs !== void 0 ? formatDuration(Math.max(1e3, elapsedMs)) : void 0;
|
|
8524
|
+
return /* @__PURE__ */ jsxs("button", {
|
|
8525
|
+
type: "button",
|
|
8526
|
+
"data-copilotkit": true,
|
|
8527
|
+
"data-testid": "copilot-work-summary",
|
|
8528
|
+
"data-state": isWorking ? "working" : "done",
|
|
8529
|
+
"aria-expanded": isOpen,
|
|
8530
|
+
className: twMerge("cpk:m-0 cpk:inline-flex cpk:max-w-full cpk:cursor-pointer cpk:items-center cpk:gap-1.5 cpk:rounded-md cpk:border-none cpk:bg-transparent cpk:p-0 cpk:py-0.5 cpk:text-sm cpk:text-muted-foreground cpk:transition-colors cpk:hover:text-foreground cpk:focus-visible:outline-2 cpk:focus-visible:outline-ring", className),
|
|
8531
|
+
...props,
|
|
8532
|
+
children: [isWorking ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
|
|
8533
|
+
className: "cpk:font-medium cpk-shimmer",
|
|
8534
|
+
children: "Working"
|
|
8535
|
+
}), liveMs !== void 0 && /* @__PURE__ */ jsx("span", {
|
|
8536
|
+
className: "cpk:text-xs cpk:tabular-nums cpk:opacity-70",
|
|
8537
|
+
children: formatDuration(liveMs)
|
|
8538
|
+
})] }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
8539
|
+
/* @__PURE__ */ jsx("span", {
|
|
8540
|
+
className: "cpk:font-medium",
|
|
8541
|
+
children: duration ? `Worked for ${duration}` : `Used ${pluralize(calls.length, "tool")}`
|
|
8542
|
+
}),
|
|
8543
|
+
duration && /* @__PURE__ */ jsx("span", {
|
|
8544
|
+
className: "cpk:text-xs cpk:opacity-70",
|
|
8545
|
+
children: pluralize(calls.length, "tool")
|
|
8546
|
+
}),
|
|
8547
|
+
failed > 0 && /* @__PURE__ */ jsxs("span", {
|
|
8548
|
+
className: "cpk:text-destructive",
|
|
8549
|
+
children: [failed, " failed"]
|
|
8550
|
+
})
|
|
8551
|
+
] }), /* @__PURE__ */ jsx(ChevronRight, {
|
|
8552
|
+
"aria-hidden": "true",
|
|
8553
|
+
className: twMerge("cpk:size-3.5 cpk:shrink-0 cpk:transition-transform cpk:duration-200", isOpen && "cpk:rotate-90")
|
|
8554
|
+
})]
|
|
8555
|
+
});
|
|
8556
|
+
}
|
|
8557
|
+
|
|
7278
8558
|
//#endregion
|
|
7279
8559
|
//#region src/v2/components/intelligence-indicator/IntelligenceIndicatorView.tsx
|
|
7280
8560
|
/**
|
|
@@ -7761,7 +9041,7 @@ function messageGroup(group) {
|
|
|
7761
9041
|
}
|
|
7762
9042
|
const GROUP_ROW_KEY_PREFIX = "copilotkit-group:";
|
|
7763
9043
|
const VIRTUALIZE_THRESHOLD = 50;
|
|
7764
|
-
function CopilotChatMessageView({ messages = [], assistantMessage, userMessage, reasoningMessage, cursor, intelligenceIndicator, isRunning = false, transformMessages, groupMessages, children, className, ...props }) {
|
|
9044
|
+
function CopilotChatMessageView({ messages = [], assistantMessage, userMessage, reasoningMessage, cursor, intelligenceIndicator, workSummary, isRunning = false, transformMessages, groupMessages, messageFeedback = true, toolCallDisplay = "grouped", children, className, ...props }) {
|
|
7765
9045
|
const isPinnedToBottom = useContext(ScrollPinnedContext);
|
|
7766
9046
|
const renderCustomMessage = useRenderCustomMessages();
|
|
7767
9047
|
const { renderActivityMessage } = useRenderActivityMessage();
|
|
@@ -7802,6 +9082,100 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
|
|
|
7802
9082
|
transformedMessages
|
|
7803
9083
|
]);
|
|
7804
9084
|
const latestRenderedId = renderedMessages[renderedMessages.length - 1]?.id;
|
|
9085
|
+
const rendererNames = useToolCallRendererNames();
|
|
9086
|
+
const toolCallLayouts = useMemo(() => toolCallDisplay === "separate" ? /* @__PURE__ */ new Map() : getToolCallLayouts(renderedMessages, messages, rendererNames), [
|
|
9087
|
+
toolCallDisplay,
|
|
9088
|
+
renderedMessages,
|
|
9089
|
+
messages,
|
|
9090
|
+
rendererNames
|
|
9091
|
+
]);
|
|
9092
|
+
const turnWork = useMemo(() => toolCallDisplay === "turn" ? getTurnWork(renderedMessages, toolCallLayouts) : void 0, [
|
|
9093
|
+
toolCallDisplay,
|
|
9094
|
+
renderedMessages,
|
|
9095
|
+
toolCallLayouts
|
|
9096
|
+
]);
|
|
9097
|
+
const turnByFirstMessage = useMemo(() => {
|
|
9098
|
+
const byFirst = /* @__PURE__ */ new Map();
|
|
9099
|
+
for (const turn of turnWork?.values() ?? []) byFirst.set(turn.firstMessageId, turn);
|
|
9100
|
+
return byFirst;
|
|
9101
|
+
}, [turnWork]);
|
|
9102
|
+
let latestTurnKey = "start";
|
|
9103
|
+
for (let i = renderedMessages.length - 1; i >= 0; i--) if (renderedMessages[i].role === "user") {
|
|
9104
|
+
latestTurnKey = renderedMessages[i].id;
|
|
9105
|
+
break;
|
|
9106
|
+
}
|
|
9107
|
+
const isWorkingOn = (turnKey) => isRunning && turnKey === latestTurnKey;
|
|
9108
|
+
const [toggledTurns, setToggledTurns] = useState(() => /* @__PURE__ */ new Map());
|
|
9109
|
+
const isWorkOpen = (turnKey) => toggledTurns.get(turnKey) ?? isWorkingOn(turnKey);
|
|
9110
|
+
const workTimesRef = useRef(/* @__PURE__ */ new Map());
|
|
9111
|
+
if (toolCallDisplay === "turn") {
|
|
9112
|
+
const now = Date.now();
|
|
9113
|
+
const workTimes = workTimesRef.current;
|
|
9114
|
+
if (isRunning) {
|
|
9115
|
+
const times = workTimes.get(latestTurnKey);
|
|
9116
|
+
if (times) times.workingSince ??= now;
|
|
9117
|
+
else if (renderedMessages[renderedMessages.length - 1]?.role === "user") workTimes.set(latestTurnKey, {
|
|
9118
|
+
elapsedMs: 0,
|
|
9119
|
+
workingSince: now
|
|
9120
|
+
});
|
|
9121
|
+
} else for (const times of workTimes.values()) {
|
|
9122
|
+
if (times.workingSince === void 0) continue;
|
|
9123
|
+
times.elapsedMs += now - times.workingSince;
|
|
9124
|
+
times.workingSince = void 0;
|
|
9125
|
+
}
|
|
9126
|
+
}
|
|
9127
|
+
const { workOpen, workTextOpen } = useMemo(() => {
|
|
9128
|
+
const open = /* @__PURE__ */ new Map();
|
|
9129
|
+
const textOpen = /* @__PURE__ */ new Map();
|
|
9130
|
+
for (const turn of turnWork?.values() ?? []) {
|
|
9131
|
+
const turnOpen = toggledTurns.get(turn.key) ?? (isRunning && turn.key === latestTurnKey);
|
|
9132
|
+
for (const id of turn.workMessageIds) {
|
|
9133
|
+
open.set(id, turnOpen);
|
|
9134
|
+
if (id !== turn.replyTextMessageId) textOpen.set(id, turnOpen);
|
|
9135
|
+
}
|
|
9136
|
+
}
|
|
9137
|
+
return {
|
|
9138
|
+
workOpen: open,
|
|
9139
|
+
workTextOpen: textOpen
|
|
9140
|
+
};
|
|
9141
|
+
}, [
|
|
9142
|
+
turnWork,
|
|
9143
|
+
toggledTurns,
|
|
9144
|
+
isRunning,
|
|
9145
|
+
latestTurnKey
|
|
9146
|
+
]);
|
|
9147
|
+
const toolCallDisplayContext = useMemo(() => ({
|
|
9148
|
+
display: toolCallDisplay,
|
|
9149
|
+
isRunning,
|
|
9150
|
+
layouts: toolCallLayouts,
|
|
9151
|
+
workOpen,
|
|
9152
|
+
workTextOpen
|
|
9153
|
+
}), [
|
|
9154
|
+
toolCallDisplay,
|
|
9155
|
+
isRunning,
|
|
9156
|
+
toolCallLayouts,
|
|
9157
|
+
workOpen,
|
|
9158
|
+
workTextOpen
|
|
9159
|
+
]);
|
|
9160
|
+
const renderWorkSummary = (turnKey, calls) => {
|
|
9161
|
+
const working = isWorkingOn(turnKey);
|
|
9162
|
+
const open = isWorkOpen(turnKey);
|
|
9163
|
+
const times = workTimesRef.current.get(turnKey);
|
|
9164
|
+
return /* @__PURE__ */ jsx(Collapsible, {
|
|
9165
|
+
open: working || calls.length > 0,
|
|
9166
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
9167
|
+
className: "cpk:pt-1 cpk:pb-2",
|
|
9168
|
+
children: renderSlot(workSummary, CopilotChatWorkSummary, {
|
|
9169
|
+
isWorking: working,
|
|
9170
|
+
isOpen: open,
|
|
9171
|
+
calls,
|
|
9172
|
+
elapsedMs: times?.elapsedMs,
|
|
9173
|
+
workingSince: times?.workingSince,
|
|
9174
|
+
onClick: () => setToggledTurns((toggled) => new Map(toggled).set(turnKey, !open))
|
|
9175
|
+
})
|
|
9176
|
+
})
|
|
9177
|
+
}, `work-summary-${turnKey}`);
|
|
9178
|
+
};
|
|
7805
9179
|
const transformDuplicateId = useMemo(() => {
|
|
7806
9180
|
if (process.env.NODE_ENV === "production" || !transformMessages && !groupMessages) return;
|
|
7807
9181
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -7839,8 +9213,6 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
|
|
|
7839
9213
|
commitRowKeyStore(rowKeyStore, renderedMessages);
|
|
7840
9214
|
}, [rowKeyStore, renderedMessages]);
|
|
7841
9215
|
const stableGroupKey = (key) => rowRenderKeys.get(key) ?? key;
|
|
7842
|
-
const rowKey = (row) => row.type === "group" ? `${GROUP_ROW_KEY_PREFIX}${stableGroupKey(row.key)}` : rowRenderKeys.get(row.message.id) ?? row.message.id;
|
|
7843
|
-
const rowKeys = useMemo(() => rows.map(rowKey), [rows, rowRenderKeys]);
|
|
7844
9216
|
const groupStateRef = useRef(/* @__PURE__ */ new Map());
|
|
7845
9217
|
const groupSettersRef = useRef(/* @__PURE__ */ new Map());
|
|
7846
9218
|
const groupStateThreadRef = useRef(config?.threadId);
|
|
@@ -7869,6 +9241,18 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
|
|
|
7869
9241
|
const { Component: AssistantComponent, slotProps: assistantSlotProps } = useMemo(() => resolveSlotComponent(assistantMessage, CopilotChatAssistantMessage_default), [assistantMessage]);
|
|
7870
9242
|
const agentId = config?.agentId;
|
|
7871
9243
|
const threadId = config?.threadId;
|
|
9244
|
+
const learningFeedbackEnabled = useLearningFeedbackEnabled(copilotkit);
|
|
9245
|
+
const feedbackScope = useMemo(() => messageFeedback && learningFeedbackEnabled && agentId !== void 0 && threadId !== void 0 ? {
|
|
9246
|
+
copilotkit,
|
|
9247
|
+
agentId,
|
|
9248
|
+
threadId
|
|
9249
|
+
} : null, [
|
|
9250
|
+
messageFeedback,
|
|
9251
|
+
learningFeedbackEnabled,
|
|
9252
|
+
copilotkit,
|
|
9253
|
+
agentId,
|
|
9254
|
+
threadId
|
|
9255
|
+
]);
|
|
7872
9256
|
const assistantSlotPropsWithFeedback = useMemo(() => {
|
|
7873
9257
|
const onThumbsUp = assistantSlotProps?.onThumbsUp;
|
|
7874
9258
|
const onThumbsDown = assistantSlotProps?.onThumbsDown;
|
|
@@ -7914,8 +9298,6 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
|
|
|
7914
9298
|
total: 0,
|
|
7915
9299
|
sizes: /* @__PURE__ */ new Map()
|
|
7916
9300
|
});
|
|
7917
|
-
const rowKeysRef = React.useRef(rowKeys);
|
|
7918
|
-
rowKeysRef.current = rowKeys;
|
|
7919
9301
|
const firstMessageId = deduplicatedMessages[0]?.id;
|
|
7920
9302
|
const measuredThreadRef = React.useRef(firstMessageId);
|
|
7921
9303
|
if (measuredThreadRef.current !== firstMessageId) {
|
|
@@ -7925,16 +9307,6 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
|
|
|
7925
9307
|
sizes: /* @__PURE__ */ new Map()
|
|
7926
9308
|
};
|
|
7927
9309
|
}
|
|
7928
|
-
const measuredKeysRef = React.useRef(rowKeys);
|
|
7929
|
-
if (measuredKeysRef.current !== rowKeys) {
|
|
7930
|
-
measuredKeysRef.current = rowKeys;
|
|
7931
|
-
const live = new Set(rowKeys);
|
|
7932
|
-
const measured = measuredRef.current;
|
|
7933
|
-
for (const [key, height] of measured.sizes) if (!live.has(key)) {
|
|
7934
|
-
measured.sizes.delete(key);
|
|
7935
|
-
measured.total -= height;
|
|
7936
|
-
}
|
|
7937
|
-
}
|
|
7938
9310
|
const estimateRowSize = React.useCallback(() => {
|
|
7939
9311
|
const { total, sizes } = measuredRef.current;
|
|
7940
9312
|
return sizes.size > 0 ? Math.max(1, Math.round(total / sizes.size)) : 100;
|
|
@@ -7942,15 +9314,13 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
|
|
|
7942
9314
|
const measureRowElement = React.useCallback((el) => {
|
|
7943
9315
|
const height = el?.getBoundingClientRect().height ?? 0;
|
|
7944
9316
|
const index = Number(el?.dataset?.index);
|
|
7945
|
-
|
|
7946
|
-
if (height > 0 && key !== void 0) {
|
|
9317
|
+
if (height > 0 && Number.isInteger(index)) {
|
|
7947
9318
|
const { total, sizes } = measuredRef.current;
|
|
7948
|
-
measuredRef.current.total = total - (sizes.get(
|
|
7949
|
-
sizes.set(
|
|
9319
|
+
measuredRef.current.total = total - (sizes.get(index) ?? 0) + height;
|
|
9320
|
+
sizes.set(index, height);
|
|
7950
9321
|
}
|
|
7951
|
-
return height;
|
|
9322
|
+
return height > 0 ? height : measuredRef.current.sizes.get(index) ?? 100;
|
|
7952
9323
|
}, []);
|
|
7953
|
-
const getRowKey = React.useCallback((index) => rowKeys[index] ?? index, [rowKeys]);
|
|
7954
9324
|
const isPinnedToBottomRef = React.useRef(isPinnedToBottom);
|
|
7955
9325
|
const shouldAdjustScrollOnResize = React.useCallback((item, _delta, instance) => {
|
|
7956
9326
|
if (isPinnedToBottomRef.current) return false;
|
|
@@ -7959,9 +9329,8 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
|
|
|
7959
9329
|
}, []);
|
|
7960
9330
|
const virtualizer = useVirtualizer({
|
|
7961
9331
|
count: shouldVirtualize ? rows.length : 0,
|
|
7962
|
-
getScrollElement: () => scrollElement,
|
|
9332
|
+
getScrollElement: () => shouldVirtualize ? scrollElement : null,
|
|
7963
9333
|
estimateSize: estimateRowSize,
|
|
7964
|
-
getItemKey: getRowKey,
|
|
7965
9334
|
overscan: 5,
|
|
7966
9335
|
measureElement: measureRowElement,
|
|
7967
9336
|
initialRect: {
|
|
@@ -7971,8 +9340,11 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
|
|
|
7971
9340
|
});
|
|
7972
9341
|
isPinnedToBottomRef.current = isPinnedToBottom;
|
|
7973
9342
|
virtualizer.shouldAdjustScrollPositionOnItemSizeChange = shouldAdjustScrollOnResize;
|
|
9343
|
+
const lastEndAlignedFirstMessageRef = React.useRef(void 0);
|
|
7974
9344
|
useLayoutEffect(() => {
|
|
7975
9345
|
if (!shouldVirtualize || !rows.length) return;
|
|
9346
|
+
if (lastEndAlignedFirstMessageRef.current === firstMessageId) return;
|
|
9347
|
+
lastEndAlignedFirstMessageRef.current = firstMessageId;
|
|
7976
9348
|
virtualizer.scrollToIndex(rows.length - 1, { align: "end" });
|
|
7977
9349
|
}, [shouldVirtualize, firstMessageId]);
|
|
7978
9350
|
const intelligenceTurnAnchors = useMemo(() => getIntelligenceTurnAnchors(deduplicatedMessages, renderedMessages), [deduplicatedMessages, renderedMessages]);
|
|
@@ -7980,6 +9352,8 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
|
|
|
7980
9352
|
const elements = [];
|
|
7981
9353
|
const stateSnapshot = renderCustomMessage ? getStateSnapshotForMessage(message.id) : void 0;
|
|
7982
9354
|
const rowKey = rowRenderKeys.get(message.id) ?? message.id;
|
|
9355
|
+
const turn = turnByFirstMessage.get(message.id);
|
|
9356
|
+
if (turn) elements.push(renderWorkSummary(turn.key, turn.calls));
|
|
7983
9357
|
if (renderCustomMessage) elements.push(/* @__PURE__ */ jsx(MemoizedCustomMessage, {
|
|
7984
9358
|
message,
|
|
7985
9359
|
position: "before",
|
|
@@ -8003,14 +9377,20 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
|
|
|
8003
9377
|
message,
|
|
8004
9378
|
renderActivityMessage
|
|
8005
9379
|
}, rowKey));
|
|
8006
|
-
else if (message.role === "reasoning")
|
|
8007
|
-
|
|
8008
|
-
|
|
8009
|
-
|
|
8010
|
-
|
|
8011
|
-
|
|
8012
|
-
|
|
8013
|
-
|
|
9380
|
+
else if (message.role === "reasoning") {
|
|
9381
|
+
const reasoning = /* @__PURE__ */ jsx(MemoizedReasoningMessage, {
|
|
9382
|
+
message,
|
|
9383
|
+
messages,
|
|
9384
|
+
isRunning,
|
|
9385
|
+
isLatest: message.id === latestRenderedId,
|
|
9386
|
+
ReasoningMessageComponent: ReasoningComponent,
|
|
9387
|
+
slotProps: reasoningSlotProps
|
|
9388
|
+
}, rowKey);
|
|
9389
|
+
elements.push(toolCallDisplay === "turn" ? /* @__PURE__ */ jsx(Collapsible, {
|
|
9390
|
+
open: workOpen.get(message.id) ?? true,
|
|
9391
|
+
children: reasoning
|
|
9392
|
+
}, rowKey) : reasoning);
|
|
9393
|
+
}
|
|
8014
9394
|
if (renderCustomMessage) elements.push(/* @__PURE__ */ jsx(MemoizedCustomMessage, {
|
|
8015
9395
|
message,
|
|
8016
9396
|
position: "after",
|
|
@@ -8025,6 +9405,7 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
|
|
|
8025
9405
|
}, `intelligence-${intelligenceTurnId}`));
|
|
8026
9406
|
return elements.filter(Boolean);
|
|
8027
9407
|
};
|
|
9408
|
+
const rowKey = (row) => row.type === "group" ? `${GROUP_ROW_KEY_PREFIX}${stableGroupKey(row.key)}` : rowRenderKeys.get(row.message.id) ?? row.message.id;
|
|
8028
9409
|
const renderRow = (row) => {
|
|
8029
9410
|
if (row.type === "message") return renderMessageBlock(row.message);
|
|
8030
9411
|
const Wrapper = row.wrapper;
|
|
@@ -8037,52 +9418,157 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
|
|
|
8037
9418
|
children: row.messages.flatMap(renderMessageBlock)
|
|
8038
9419
|
}, rowKey(row))];
|
|
8039
9420
|
};
|
|
9421
|
+
const rowKeysRef = useRef([]);
|
|
9422
|
+
rowKeysRef.current = rows.map(rowKey);
|
|
9423
|
+
const virtualModeRef = useRef(shouldVirtualize);
|
|
9424
|
+
virtualModeRef.current = shouldVirtualize;
|
|
9425
|
+
useEffect(() => {
|
|
9426
|
+
const element = scrollElementFromCtx;
|
|
9427
|
+
if (!element) return;
|
|
9428
|
+
let anchor = null;
|
|
9429
|
+
let suspended = false;
|
|
9430
|
+
let frame = 0;
|
|
9431
|
+
const visibleRows = () => Array.from(element.querySelectorAll("[data-scroll-anchor]"));
|
|
9432
|
+
const remember = () => {
|
|
9433
|
+
if (suspended || element.clientHeight === 0 || !virtualModeRef.current) return;
|
|
9434
|
+
if (isPinnedToBottomRef.current) {
|
|
9435
|
+
anchor = null;
|
|
9436
|
+
return;
|
|
9437
|
+
}
|
|
9438
|
+
const viewport = element.getBoundingClientRect();
|
|
9439
|
+
const row = visibleRows().find((row) => {
|
|
9440
|
+
const bounds = row.getBoundingClientRect();
|
|
9441
|
+
return bounds.bottom > viewport.top && bounds.top < viewport.bottom;
|
|
9442
|
+
});
|
|
9443
|
+
if (row) anchor = {
|
|
9444
|
+
key: row.dataset.scrollAnchor,
|
|
9445
|
+
offset: row.getBoundingClientRect().top - viewport.top
|
|
9446
|
+
};
|
|
9447
|
+
};
|
|
9448
|
+
const observer = new ResizeObserver(() => {
|
|
9449
|
+
if (element.clientHeight === 0) {
|
|
9450
|
+
suspended = true;
|
|
9451
|
+
cancelAnimationFrame(frame);
|
|
9452
|
+
return;
|
|
9453
|
+
}
|
|
9454
|
+
if (!suspended || !anchor) {
|
|
9455
|
+
suspended = false;
|
|
9456
|
+
remember();
|
|
9457
|
+
return;
|
|
9458
|
+
}
|
|
9459
|
+
let attempts = 0;
|
|
9460
|
+
let stableFrames = 0;
|
|
9461
|
+
const restore = () => {
|
|
9462
|
+
if (!anchor || element.clientHeight === 0) return;
|
|
9463
|
+
const index = rowKeysRef.current.indexOf(anchor.key);
|
|
9464
|
+
if (index < 0) {
|
|
9465
|
+
anchor = null;
|
|
9466
|
+
suspended = false;
|
|
9467
|
+
return;
|
|
9468
|
+
}
|
|
9469
|
+
const row = visibleRows().find((row) => row.dataset.scrollAnchor === anchor.key);
|
|
9470
|
+
if (row) {
|
|
9471
|
+
const delta = row.getBoundingClientRect().top - element.getBoundingClientRect().top - anchor.offset;
|
|
9472
|
+
element.scrollTop += delta;
|
|
9473
|
+
stableFrames = Math.abs(delta) < 1 ? stableFrames + 1 : 0;
|
|
9474
|
+
} else {
|
|
9475
|
+
const offset = virtualizer.getOffsetForIndex(index, "start")?.[0];
|
|
9476
|
+
if (offset !== void 0) virtualizer.scrollToOffset(offset - anchor.offset);
|
|
9477
|
+
stableFrames = 0;
|
|
9478
|
+
}
|
|
9479
|
+
if (++attempts < 60 && stableFrames < 3) frame = requestAnimationFrame(restore);
|
|
9480
|
+
else {
|
|
9481
|
+
suspended = false;
|
|
9482
|
+
remember();
|
|
9483
|
+
}
|
|
9484
|
+
};
|
|
9485
|
+
frame = requestAnimationFrame(restore);
|
|
9486
|
+
});
|
|
9487
|
+
const interrupt = () => {
|
|
9488
|
+
cancelAnimationFrame(frame);
|
|
9489
|
+
anchor = null;
|
|
9490
|
+
suspended = false;
|
|
9491
|
+
};
|
|
9492
|
+
element.addEventListener("scroll", remember, { passive: true });
|
|
9493
|
+
element.addEventListener("wheel", interrupt, { passive: true });
|
|
9494
|
+
element.addEventListener("touchstart", interrupt, { passive: true });
|
|
9495
|
+
element.addEventListener("keydown", interrupt);
|
|
9496
|
+
observer.observe(element);
|
|
9497
|
+
remember();
|
|
9498
|
+
return () => {
|
|
9499
|
+
cancelAnimationFrame(frame);
|
|
9500
|
+
observer.disconnect();
|
|
9501
|
+
element.removeEventListener("scroll", remember);
|
|
9502
|
+
element.removeEventListener("wheel", interrupt);
|
|
9503
|
+
element.removeEventListener("touchstart", interrupt);
|
|
9504
|
+
element.removeEventListener("keydown", interrupt);
|
|
9505
|
+
};
|
|
9506
|
+
}, [
|
|
9507
|
+
scrollElementFromCtx,
|
|
9508
|
+
virtualizer,
|
|
9509
|
+
firstMessageId
|
|
9510
|
+
]);
|
|
8040
9511
|
const messageElements = shouldVirtualize ? [] : rows.flatMap(renderRow);
|
|
8041
|
-
if (children) return /* @__PURE__ */ jsx(
|
|
8042
|
-
|
|
8043
|
-
|
|
8044
|
-
|
|
8045
|
-
|
|
8046
|
-
|
|
8047
|
-
|
|
8048
|
-
|
|
9512
|
+
if (children) return /* @__PURE__ */ jsx(MessageFeedbackScopeContext.Provider, {
|
|
9513
|
+
value: feedbackScope,
|
|
9514
|
+
children: /* @__PURE__ */ jsx(ToolCallDisplayContext.Provider, {
|
|
9515
|
+
value: toolCallDisplayContext,
|
|
9516
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
9517
|
+
"data-copilotkit": true,
|
|
9518
|
+
style: { display: "contents" },
|
|
9519
|
+
children: children({
|
|
9520
|
+
messageElements,
|
|
9521
|
+
messages,
|
|
9522
|
+
isRunning,
|
|
9523
|
+
interruptElement
|
|
9524
|
+
})
|
|
9525
|
+
})
|
|
8049
9526
|
})
|
|
8050
9527
|
});
|
|
8051
9528
|
const lastMessage = renderedMessages[renderedMessages.length - 1];
|
|
8052
|
-
const showCursor = isRunning && lastMessage?.role !== "reasoning";
|
|
8053
|
-
|
|
8054
|
-
|
|
8055
|
-
|
|
8056
|
-
|
|
8057
|
-
|
|
8058
|
-
|
|
8059
|
-
|
|
8060
|
-
|
|
8061
|
-
|
|
8062
|
-
|
|
8063
|
-
|
|
8064
|
-
|
|
8065
|
-
const row = rows[virtualItem.index];
|
|
8066
|
-
return /* @__PURE__ */ jsx("div", {
|
|
8067
|
-
"data-index": virtualItem.index,
|
|
8068
|
-
ref: virtualizer.measureElement,
|
|
9529
|
+
const showCursor = isRunning && lastMessage?.role !== "reasoning" && toolCallDisplay !== "turn";
|
|
9530
|
+
const pendingWorkSummary = toolCallDisplay === "turn" && isRunning && lastMessage?.role === "user";
|
|
9531
|
+
return /* @__PURE__ */ jsx(MessageFeedbackScopeContext.Provider, {
|
|
9532
|
+
value: feedbackScope,
|
|
9533
|
+
children: /* @__PURE__ */ jsx(ToolCallDisplayContext.Provider, {
|
|
9534
|
+
value: toolCallDisplayContext,
|
|
9535
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
9536
|
+
"data-copilotkit": true,
|
|
9537
|
+
"data-testid": "copilot-message-list",
|
|
9538
|
+
className: twMerge("copilotKitMessages cpk:flex cpk:flex-col", className),
|
|
9539
|
+
...props,
|
|
9540
|
+
children: [
|
|
9541
|
+
shouldVirtualize ? /* @__PURE__ */ jsx("div", {
|
|
8069
9542
|
style: {
|
|
8070
|
-
|
|
8071
|
-
|
|
8072
|
-
left: 0,
|
|
8073
|
-
width: "100%",
|
|
8074
|
-
transform: `translateY(${virtualItem.start}px)`
|
|
9543
|
+
height: virtualizer.getTotalSize(),
|
|
9544
|
+
position: "relative"
|
|
8075
9545
|
},
|
|
8076
|
-
children:
|
|
8077
|
-
|
|
8078
|
-
|
|
8079
|
-
|
|
8080
|
-
|
|
8081
|
-
|
|
8082
|
-
|
|
8083
|
-
|
|
9546
|
+
children: virtualizer.getVirtualItems().map((virtualItem) => {
|
|
9547
|
+
const row = rows[virtualItem.index];
|
|
9548
|
+
return /* @__PURE__ */ jsx("div", {
|
|
9549
|
+
"data-index": virtualItem.index,
|
|
9550
|
+
"data-scroll-anchor": rowKey(row),
|
|
9551
|
+
ref: virtualizer.measureElement,
|
|
9552
|
+
style: {
|
|
9553
|
+
position: "absolute",
|
|
9554
|
+
top: 0,
|
|
9555
|
+
left: 0,
|
|
9556
|
+
width: "100%",
|
|
9557
|
+
transform: `translateY(${virtualItem.start}px)`
|
|
9558
|
+
},
|
|
9559
|
+
children: renderRow(row)
|
|
9560
|
+
}, rowKey(row));
|
|
9561
|
+
})
|
|
9562
|
+
}) : messageElements,
|
|
9563
|
+
interruptElement,
|
|
9564
|
+
pendingWorkSummary && renderWorkSummary(latestTurnKey, []),
|
|
9565
|
+
showCursor && /* @__PURE__ */ jsx("div", {
|
|
9566
|
+
className: "cpk:mt-2",
|
|
9567
|
+
children: renderSlot(cursor, CopilotChatMessageView.Cursor, {})
|
|
9568
|
+
})
|
|
9569
|
+
]
|
|
8084
9570
|
})
|
|
8085
|
-
|
|
9571
|
+
})
|
|
8086
9572
|
});
|
|
8087
9573
|
}
|
|
8088
9574
|
CopilotChatMessageView.Cursor = function Cursor({ className, ...props }) {
|
|
@@ -8467,6 +9953,16 @@ function DropOverlay() {
|
|
|
8467
9953
|
});
|
|
8468
9954
|
}
|
|
8469
9955
|
function CopilotChatView({ messageView, input, scrollView, suggestionView, welcomeScreen, messages = [], autoScroll = true, isRunning = false, suggestions, suggestionLoadingIndexes, onSelectSuggestion, onSubmitMessage, onStop, inputMode, inputValue, onInputChange, onStartTranscribe, onCancelTranscribe, onFinishTranscribe, onFinishTranscribeWithAudio, attachments, onRemoveAttachment, onAddFile, dragOver, onDragOver, onDragLeave, onDrop, isConnecting = false, hasExplicitThreadId = false, disclaimer, intelligenceIndicator, children, className, ...props }) {
|
|
9956
|
+
const configuredThreadId = useCopilotChatConfiguration()?.threadId;
|
|
9957
|
+
const [fallbackThreadId, setFallbackThreadId] = useState(messages[0]?.id);
|
|
9958
|
+
const previousMessageIds = useRef(/* @__PURE__ */ new Set());
|
|
9959
|
+
useEffect(() => {
|
|
9960
|
+
if (messages.length === 0) return;
|
|
9961
|
+
const overlaps = messages.some((message) => previousMessageIds.current.has(message.id));
|
|
9962
|
+
previousMessageIds.current = new Set(messages.map((message) => message.id));
|
|
9963
|
+
if (!overlaps) setFallbackThreadId(messages[0].id);
|
|
9964
|
+
}, [messages]);
|
|
9965
|
+
const scrollThreadId = configuredThreadId ?? fallbackThreadId;
|
|
8470
9966
|
const [inputContainerEl, setInputContainerEl] = useState(null);
|
|
8471
9967
|
const [inputContainerHeight, setInputContainerHeight] = useState(0);
|
|
8472
9968
|
const [isResizing, setIsResizing] = useState(false);
|
|
@@ -8533,6 +10029,7 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
8533
10029
|
}) : null;
|
|
8534
10030
|
const BoundScrollView = renderSlot(scrollView, CopilotChatView.ScrollView, {
|
|
8535
10031
|
autoScroll,
|
|
10032
|
+
scrollThreadId,
|
|
8536
10033
|
inputContainerHeight,
|
|
8537
10034
|
isResizing,
|
|
8538
10035
|
children: /* @__PURE__ */ jsx("div", {
|
|
@@ -8628,12 +10125,102 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
8628
10125
|
});
|
|
8629
10126
|
}
|
|
8630
10127
|
(function(_CopilotChatView) {
|
|
8631
|
-
const ScrollContent = ({ children, scrollToBottomButton, feather, inputContainerHeight, isResizing }) => {
|
|
8632
|
-
const { isAtBottom, scrollToBottom, scrollRef, state } = useStickToBottomContext();
|
|
10128
|
+
const ScrollContent = ({ children, scrollToBottomButton, feather, inputContainerHeight, isResizing, scrollThreadId }) => {
|
|
10129
|
+
const { isAtBottom, scrollToBottom, stopScroll, scrollRef, state } = useStickToBottomContext();
|
|
8633
10130
|
const [scrollEl, setScrollEl] = useState(null);
|
|
10131
|
+
const readingOffsetRef = useRef(null);
|
|
10132
|
+
const pinIntentRef = useRef(false);
|
|
10133
|
+
const stateRef = useRef(state);
|
|
10134
|
+
stateRef.current = state;
|
|
8634
10135
|
useLayoutEffect(() => {
|
|
8635
10136
|
setScrollEl(scrollRef.current ?? null);
|
|
8636
10137
|
}, []);
|
|
10138
|
+
useEffect(() => {
|
|
10139
|
+
if (!scrollEl) return;
|
|
10140
|
+
let hidden = false;
|
|
10141
|
+
let resumeBottom = false;
|
|
10142
|
+
let pendingFrame = 0;
|
|
10143
|
+
let resumeFrame = 0;
|
|
10144
|
+
let settleFrame = 0;
|
|
10145
|
+
readingOffsetRef.current = null;
|
|
10146
|
+
const rememberScroll = () => {
|
|
10147
|
+
if (hidden || scrollEl.clientHeight === 0) return;
|
|
10148
|
+
if (resumeBottom) {
|
|
10149
|
+
readingOffsetRef.current = null;
|
|
10150
|
+
return;
|
|
10151
|
+
}
|
|
10152
|
+
if (pinIntentRef.current) if (stateRef.current.escapedFromLock) pinIntentRef.current = false;
|
|
10153
|
+
else {
|
|
10154
|
+
readingOffsetRef.current = null;
|
|
10155
|
+
if (!stateRef.current.isNearBottom) return;
|
|
10156
|
+
pinIntentRef.current = false;
|
|
10157
|
+
}
|
|
10158
|
+
readingOffsetRef.current = !stateRef.current.isAtBottom && (stateRef.current.escapedFromLock || !stateRef.current.isNearBottom) ? scrollEl.scrollTop : null;
|
|
10159
|
+
};
|
|
10160
|
+
const onScroll = () => {
|
|
10161
|
+
rememberScroll();
|
|
10162
|
+
cancelAnimationFrame(pendingFrame);
|
|
10163
|
+
pendingFrame = requestAnimationFrame(rememberScroll);
|
|
10164
|
+
};
|
|
10165
|
+
const onWheel = (event) => {
|
|
10166
|
+
if (event.deltaY < 0) {
|
|
10167
|
+
pinIntentRef.current = false;
|
|
10168
|
+
resumeBottom = false;
|
|
10169
|
+
}
|
|
10170
|
+
};
|
|
10171
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
10172
|
+
if (scrollEl.clientHeight === 0) {
|
|
10173
|
+
hidden = true;
|
|
10174
|
+
resumeBottom = pinIntentRef.current || readingOffsetRef.current === null;
|
|
10175
|
+
if (!resumeBottom) stopScroll();
|
|
10176
|
+
} else if (hidden) {
|
|
10177
|
+
hidden = false;
|
|
10178
|
+
if (resumeBottom) {
|
|
10179
|
+
stopScroll();
|
|
10180
|
+
resumeFrame = requestAnimationFrame(() => {
|
|
10181
|
+
settleFrame = requestAnimationFrame(() => {
|
|
10182
|
+
if (scrollEl.clientHeight > 0 && resumeBottom) {
|
|
10183
|
+
resumeBottom = false;
|
|
10184
|
+
pinIntentRef.current = true;
|
|
10185
|
+
scrollToBottom({ animation: "instant" });
|
|
10186
|
+
}
|
|
10187
|
+
});
|
|
10188
|
+
});
|
|
10189
|
+
} else if (readingOffsetRef.current !== null) {
|
|
10190
|
+
stopScroll();
|
|
10191
|
+
scrollEl.scrollTop = readingOffsetRef.current;
|
|
10192
|
+
}
|
|
10193
|
+
}
|
|
10194
|
+
});
|
|
10195
|
+
rememberScroll();
|
|
10196
|
+
scrollEl.addEventListener("scroll", onScroll);
|
|
10197
|
+
scrollEl.addEventListener("wheel", onWheel, { passive: true });
|
|
10198
|
+
resizeObserver.observe(scrollEl);
|
|
10199
|
+
return () => {
|
|
10200
|
+
scrollEl.removeEventListener("scroll", onScroll);
|
|
10201
|
+
scrollEl.removeEventListener("wheel", onWheel);
|
|
10202
|
+
cancelAnimationFrame(pendingFrame);
|
|
10203
|
+
cancelAnimationFrame(resumeFrame);
|
|
10204
|
+
cancelAnimationFrame(settleFrame);
|
|
10205
|
+
resizeObserver.disconnect();
|
|
10206
|
+
};
|
|
10207
|
+
}, [
|
|
10208
|
+
scrollEl,
|
|
10209
|
+
scrollToBottom,
|
|
10210
|
+
stopScroll,
|
|
10211
|
+
scrollThreadId
|
|
10212
|
+
]);
|
|
10213
|
+
const startBottomPin = useCallback((instant = false) => {
|
|
10214
|
+
readingOffsetRef.current = null;
|
|
10215
|
+
pinIntentRef.current = true;
|
|
10216
|
+
scrollToBottom(instant ? { animation: "instant" } : void 0);
|
|
10217
|
+
}, [scrollToBottom]);
|
|
10218
|
+
const previousScrollThreadId = useRef(scrollThreadId);
|
|
10219
|
+
useEffect(() => {
|
|
10220
|
+
if (previousScrollThreadId.current === scrollThreadId) return;
|
|
10221
|
+
previousScrollThreadId.current = scrollThreadId;
|
|
10222
|
+
startBottomPin(true);
|
|
10223
|
+
}, [scrollThreadId, startBottomPin]);
|
|
8637
10224
|
const BoundFeather = renderSlot(feather, CopilotChatView.Feather, {});
|
|
8638
10225
|
return /* @__PURE__ */ jsx(ScrollElementContext.Provider, {
|
|
8639
10226
|
value: scrollEl,
|
|
@@ -8655,7 +10242,7 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
8655
10242
|
!isAtBottom && !isResizing && /* @__PURE__ */ jsx("div", {
|
|
8656
10243
|
className: "cpk:absolute cpk:inset-x-0 cpk:flex cpk:justify-center cpk:z-30 cpk:pointer-events-none",
|
|
8657
10244
|
style: { bottom: `${inputContainerHeight + SCROLL_BUTTON_OFFSET}px` },
|
|
8658
|
-
children: renderSlot(scrollToBottomButton, CopilotChatView.ScrollToBottomButton, { onClick: () =>
|
|
10245
|
+
children: renderSlot(scrollToBottomButton, CopilotChatView.ScrollToBottomButton, { onClick: () => startBottomPin() })
|
|
8659
10246
|
})
|
|
8660
10247
|
] })
|
|
8661
10248
|
})
|
|
@@ -8703,7 +10290,7 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
8703
10290
|
})
|
|
8704
10291
|
});
|
|
8705
10292
|
};
|
|
8706
|
-
_CopilotChatView.ScrollView = ({ children, autoScroll = "pin-to-bottom", scrollToBottomButton, feather, inputContainerHeight = 0, isResizing = false, className, ...props }) => {
|
|
10293
|
+
_CopilotChatView.ScrollView = ({ children, autoScroll = "pin-to-bottom", scrollThreadId, scrollToBottomButton, feather, inputContainerHeight = 0, isResizing = false, className, ...props }) => {
|
|
8707
10294
|
const mode = normalizeAutoScroll(autoScroll);
|
|
8708
10295
|
const [hasMounted, setHasMounted] = useState(false);
|
|
8709
10296
|
const scrollRef = useRef(null);
|
|
@@ -8792,6 +10379,7 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
8792
10379
|
initial: "smooth",
|
|
8793
10380
|
...props,
|
|
8794
10381
|
children: /* @__PURE__ */ jsx(ScrollContent, {
|
|
10382
|
+
scrollThreadId,
|
|
8795
10383
|
scrollToBottomButton,
|
|
8796
10384
|
feather,
|
|
8797
10385
|
inputContainerHeight,
|
|
@@ -8800,14 +10388,18 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
8800
10388
|
})
|
|
8801
10389
|
});
|
|
8802
10390
|
};
|
|
8803
|
-
_CopilotChatView.ScrollToBottomButton = ({ className, ...props }) =>
|
|
8804
|
-
|
|
8805
|
-
|
|
8806
|
-
|
|
8807
|
-
|
|
8808
|
-
|
|
8809
|
-
|
|
8810
|
-
|
|
10391
|
+
_CopilotChatView.ScrollToBottomButton = ({ className, ...props }) => {
|
|
10392
|
+
const labels = useCopilotChatConfiguration()?.labels ?? CopilotChatDefaultLabels;
|
|
10393
|
+
return /* @__PURE__ */ jsx(Button, {
|
|
10394
|
+
"data-testid": "copilot-scroll-to-bottom",
|
|
10395
|
+
variant: "outline",
|
|
10396
|
+
size: "sm",
|
|
10397
|
+
className: twMerge("cpk:rounded-full cpk:w-10 cpk:h-10 cpk:p-0 cpk:pointer-events-auto", "cpk:bg-white cpk:dark:bg-gray-900", "cpk:shadow-lg cpk:border cpk:border-gray-200 cpk:dark:border-gray-700", "cpk:hover:bg-gray-50 cpk:dark:hover:bg-gray-800", "cpk:flex cpk:items-center cpk:justify-center cpk:cursor-pointer", className),
|
|
10398
|
+
"aria-label": labels.chatScrollToBottomLabel,
|
|
10399
|
+
...props,
|
|
10400
|
+
children: /* @__PURE__ */ jsx(ChevronDown, { className: "cpk:w-4 cpk:h-4 cpk:text-gray-600 cpk:dark:text-white" })
|
|
10401
|
+
});
|
|
10402
|
+
};
|
|
8811
10403
|
_CopilotChatView.Feather = ({ className, ...props }) => /* @__PURE__ */ jsx("div", {
|
|
8812
10404
|
className,
|
|
8813
10405
|
...props
|
|
@@ -10190,6 +11782,7 @@ function CopilotPopupViewInternal({ header, toggleButton, width, height, clickOu
|
|
|
10190
11782
|
if (containerRef.current?.contains(target)) return;
|
|
10191
11783
|
const toggleButton = document.querySelector("[data-slot='chat-toggle-button']");
|
|
10192
11784
|
if (toggleButton && toggleButton.contains(target)) return;
|
|
11785
|
+
if (target instanceof Element && target.closest("[data-copilotkit-popover]")) return;
|
|
10193
11786
|
setModalOpen?.(false);
|
|
10194
11787
|
};
|
|
10195
11788
|
document.addEventListener("pointerdown", handlePointerDown);
|
|
@@ -10700,62 +12293,14 @@ CopilotThreadsDrawer.displayName = "CopilotThreadsDrawer";
|
|
|
10700
12293
|
|
|
10701
12294
|
//#endregion
|
|
10702
12295
|
//#region src/v2/components/WildcardToolCallRender.tsx
|
|
12296
|
+
/**
|
|
12297
|
+
* Catch-all (`"*"`) tool-call renderer that shows CopilotKit's default
|
|
12298
|
+
* tool-call card for any tool without a dedicated renderer.
|
|
12299
|
+
*/
|
|
10703
12300
|
const WildcardToolCallRender = defineToolCallRenderer({
|
|
10704
12301
|
name: "*",
|
|
10705
|
-
|
|
10706
|
-
|
|
10707
|
-
const statusString = String(status);
|
|
10708
|
-
return /* @__PURE__ */ jsx("div", {
|
|
10709
|
-
className: "cpk:mt-2 cpk:pb-2",
|
|
10710
|
-
children: /* @__PURE__ */ jsxs("div", {
|
|
10711
|
-
className: "cpk:rounded-xl cpk:border cpk:border-zinc-200/60 cpk:dark:border-zinc-800/60 cpk:bg-white/70 cpk:dark:bg-zinc-900/50 cpk:shadow-sm cpk:backdrop-blur cpk:p-4",
|
|
10712
|
-
children: [/* @__PURE__ */ jsxs("div", {
|
|
10713
|
-
className: "cpk:flex cpk:items-center cpk:justify-between cpk:gap-3 cpk:cursor-pointer",
|
|
10714
|
-
onClick: () => setIsExpanded(!isExpanded),
|
|
10715
|
-
children: [/* @__PURE__ */ jsxs("div", {
|
|
10716
|
-
className: "cpk:flex cpk:items-center cpk:gap-2 cpk:min-w-0",
|
|
10717
|
-
children: [
|
|
10718
|
-
/* @__PURE__ */ jsx("svg", {
|
|
10719
|
-
className: `cpk:h-4 cpk:w-4 cpk:text-zinc-500 cpk:dark:text-zinc-400 cpk:transition-transform ${isExpanded ? "cpk:rotate-90" : ""}`,
|
|
10720
|
-
fill: "none",
|
|
10721
|
-
viewBox: "0 0 24 24",
|
|
10722
|
-
strokeWidth: 2,
|
|
10723
|
-
stroke: "currentColor",
|
|
10724
|
-
children: /* @__PURE__ */ jsx("path", {
|
|
10725
|
-
strokeLinecap: "round",
|
|
10726
|
-
strokeLinejoin: "round",
|
|
10727
|
-
d: "M8.25 4.5l7.5 7.5-7.5 7.5"
|
|
10728
|
-
})
|
|
10729
|
-
}),
|
|
10730
|
-
/* @__PURE__ */ jsx("span", { className: "cpk:inline-block cpk:h-2 cpk:w-2 cpk:rounded-full cpk:bg-blue-500" }),
|
|
10731
|
-
/* @__PURE__ */ jsx("span", {
|
|
10732
|
-
className: "cpk:truncate cpk:text-sm cpk:font-medium cpk:text-zinc-900 cpk:dark:text-zinc-100",
|
|
10733
|
-
children: name
|
|
10734
|
-
})
|
|
10735
|
-
]
|
|
10736
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
10737
|
-
className: `cpk:inline-flex cpk:items-center cpk:rounded-full cpk:px-2 cpk:py-1 cpk:text-xs cpk:font-medium ${statusString === "inProgress" || statusString === "executing" ? "cpk:bg-amber-100 cpk:text-amber-800 cpk:dark:bg-amber-500/15 cpk:dark:text-amber-400" : statusString === "complete" ? "cpk:bg-emerald-100 cpk:text-emerald-800 cpk:dark:bg-emerald-500/15 cpk:dark:text-emerald-400" : "cpk:bg-zinc-100 cpk:text-zinc-800 cpk:dark:bg-zinc-700/40 cpk:dark:text-zinc-300"}`,
|
|
10738
|
-
children: String(status)
|
|
10739
|
-
})]
|
|
10740
|
-
}), isExpanded && /* @__PURE__ */ jsxs("div", {
|
|
10741
|
-
className: "cpk:mt-3 cpk:grid cpk:gap-4",
|
|
10742
|
-
children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
|
|
10743
|
-
className: "cpk:text-xs cpk:uppercase cpk:tracking-wide cpk:text-zinc-500 cpk:dark:text-zinc-400",
|
|
10744
|
-
children: "Arguments"
|
|
10745
|
-
}), /* @__PURE__ */ jsx("pre", {
|
|
10746
|
-
className: "cpk:mt-2 cpk:max-h-64 cpk:overflow-auto cpk:rounded-md cpk:bg-zinc-50 cpk:dark:bg-zinc-800/60 cpk:p-3 cpk:text-xs cpk:leading-relaxed cpk:text-zinc-800 cpk:dark:text-zinc-200 cpk:whitespace-pre-wrap cpk:break-words",
|
|
10747
|
-
children: JSON.stringify(args ?? {}, null, 2)
|
|
10748
|
-
})] }), result !== void 0 && /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
|
|
10749
|
-
className: "cpk:text-xs cpk:uppercase cpk:tracking-wide cpk:text-zinc-500 cpk:dark:text-zinc-400",
|
|
10750
|
-
children: "Result"
|
|
10751
|
-
}), /* @__PURE__ */ jsx("pre", {
|
|
10752
|
-
className: "cpk:mt-2 cpk:max-h-64 cpk:overflow-auto cpk:rounded-md cpk:bg-zinc-50 cpk:dark:bg-zinc-800/60 cpk:p-3 cpk:text-xs cpk:leading-relaxed cpk:text-zinc-800 cpk:dark:text-zinc-200 cpk:whitespace-pre-wrap cpk:break-words",
|
|
10753
|
-
children: typeof result === "string" ? result : JSON.stringify(result, null, 2)
|
|
10754
|
-
})] })]
|
|
10755
|
-
})]
|
|
10756
|
-
})
|
|
10757
|
-
});
|
|
10758
|
-
}
|
|
12302
|
+
group: true,
|
|
12303
|
+
render: (props) => /* @__PURE__ */ jsx(DefaultToolCallRenderer, { ...adaptRendererProps(props) })
|
|
10759
12304
|
});
|
|
10760
12305
|
|
|
10761
12306
|
//#endregion
|
|
@@ -12938,5 +14483,5 @@ function validateProps(props) {
|
|
|
12938
14483
|
}
|
|
12939
14484
|
|
|
12940
14485
|
//#endregion
|
|
12941
|
-
export {
|
|
12942
|
-
//# sourceMappingURL=copilotkit-
|
|
14486
|
+
export { INTERRUPT_EVENT_NAME as $, ɵselectMemoriesError$1 as $a, isRunCompletionAware$1 as $i, Middleware as $n, TextMessageChunkEventSchema as $r, AudioInputContentSchema as $t, CopilotChatMessageView as A, ɵcreateThreadSelectors as Aa, convertToLegacyEvents as Ai, FunctionCallSchema as An, RunFinishedOutcomeSchema as Ar, MCPAppsActivityType as At, CopilotChatReasoningMessage_default as B, ɵmemoryRestEvents as Ba, emitInspectorStopViewing as Bi, InputContentSchema as Bn, StepStartedEventSchema as Br, AGUIConnectNotImplementedError$1 as Bt, CopilotModalHeader as C, withAuthoritativeActivityTypes as Ca, aggregateTokenUsage as Ci, EventSchema as Cn, ResumeEntrySchema as Cr, OpenGenerativeUIActivityType as Ct, CopilotChat as D, ɵRUNTIME_PROBE_TIMEOUT_MS as Da, completePartialMarkdown as Di, ExecutionCapabilitiesSchema as Dn, RunFinishedCancelledOutcomeSchema as Dr, useSandboxFunctions as Dt, DefaultOpenIcon as E, ɵMAX_SOCKET_RETRIES as Ea, compactEvents as Ei, EventTypeSchema as En, RunErrorEventSchema as Er, SandboxFunctionsContext as Et, getIntelligenceTurnAnchors as F, ɵjoinPhoenixChannel$ as Fa, createReducer as Fi, IdentityCapabilitiesSchema as Fn, StateDeltaEventSchema as Fr, AudioRecorderError as Ft, useLearningContainersInCurrentThread as G, ɵphoenixChannel$ as Ga, enforceOutgoingInput as Gi, JsonPatchOperationSchema as Gn, SubagentFinishedSuspendedOutcomeSchema as Gr, ActivityMessageSchema as Gt, CopilotChatAttachmentRenderer as H, ɵobservePhoenixJoinOutcome$ as Ha, emitInspectorViewThreadResult$1 as Hi, InputContentUrlSourceSchema as Hn, SubagentFinishedEventSchema as Hr, AGUI_METADATA_KEY as Ht, IntelligenceIndicatorView as I, ɵmapMemoryMetadataEvent as Ia, createSelector as Ii, ImageInputContentSchema as In, StateManager as Ir, CopilotChatAudioRecorder as It, useLearnFromUserActionInCurrentThread as J, ɵselectHasNextPage$1 as Ja, getWebMCPModelContext as Ji, MEMORY_ERROR_REGISTRY as Jn, SubagentStartedEventSchema as Jr, AgentCapabilitiesSchema as Jt, useLearningContainers as K, ɵphoenixSocket$ as Ka, ensureObjectArgs as Ki, JsonPatchSchema as Kn, SubagentInfoSchema as Kr, ActivitySnapshotEventSchema as Kt, CopilotChatWorkSummary as L, ɵmemoryAdapterEvents as La, createStore as Li, ImageInputPartSchema as Ln, StateSchema as Lr, CopilotChatConfigurationProvider as Lt, messageRow as M, ɵisCopilotKitFeature as Ma, createDebugLogger as Mi, HttpAgent as Mn, RunHandler as Mr, CopilotKitInspector as Mt, INTELLIGENCE_TURN_HEAD as N, ɵisHttpAgent$1 as Na, createEffect as Ni, HumanInTheLoopCapabilitiesSchema as Nn, RunStartedEventSchema as Nr, useRenderToolCall as Nt, CopilotChatView_default as O, ɵTHREAD_REQUEST_TIMEOUT_MS as Oa, contentHasMedia as Oi, FileSourceSchema as On, RunFinishedEventSchema as Or, MCPAppsActivityContentSchema as Ot, IntelligenceIndicator as P, ɵisRetryableMemoryStatus as Pa, createInspectorThreadRequestId as Pi, INSPECTOR_THREAD_BRIDGE_PLUGIN_ID as Pn, StateCapabilitiesSchema as Pr, CopilotChatInput_default as Pt, useInterrupt as Q, ɵselectMemoriesAvailable$1 as Qa, isRecognizedEvent as Qi, MetadataSchema as Qn, TextInputContentSchema as Qr, AttributableSchema as Qt, CopilotChatSuggestionView as R, ɵmemoryDomainEvents as Ra, defaultApplyEvents as Ri, ImagePartSchema as Rn, StateSnapshotEventSchema as Rr, useCopilotChatConfiguration as Rt, CopilotSidebarView as S, verifyEvents as Sa, WebMCPRegistry as Si, DocumentPartSchema as Sn, ReplaceOperationSchema as Sr, OpenGenerativeUIActivityRenderer as St, DefaultCloseIcon as T, ɵInterruptState$1 as Ta, buildResumeArray as Ti, EventType as Tn, RunAgentInputSchema as Tr, OpenGenerativeUIToolRenderer as Tt, CopilotChatAssistantMessage_default as U, ɵobservePhoenixSocketHealth$ as Ua, empty as Ui, IntelligenceAgent as Un, SubagentFinishedOutcomeSchema as Ur, AbstractAgent$1 as Ut, CopilotChatUserMessage_default as V, ɵobservePhoenixEvent$ as Va, emitInspectorViewThread as Vi, InputContentSourceSchema as Vn, SubagentErrorEventSchema as Vr, AGUIError as Vt, CopilotChatToolCallsView as W, ɵobservePhoenixSocketSignals$ as Wa, enforceEvents as Wi, InterruptSchema as Wn, SubagentFinishedSuccessOutcomeSchema as Wr, ActivityDeltaEventSchema as Wt, useMemories as X, ɵselectIsMutating$1 as Xa, isInspectorThreadBridgeEnabled$1 as Xi, MessageSchema as Xn, SystemMessageSchema as Xr, AgentThreadLockedError as Xt, useLearnFromUserAction as Y, ɵselectIsFetchingNextPage$1 as Ya, isAbortError as Yi, MemoryError as Yn, SuggestionEngine as Yr, AgentRegistry as Yt, useThreads$1 as Z, ɵselectMemories$1 as Za, isInterruptExpired as Zi, MessagesSnapshotEventSchema as Zn, TestOperationSchema as Zr, AssistantMessageSchema as Zt, WildcardToolCallRender as _, structuredClone_ as _a, UrlSourceSchema as _i, DataSourceSchema as _n, ReasoningMessageEndEventSchema as _r, useLicenseContext$1 as _t, ThreadsProvider as a, onInspectorStopViewing$1 as aa, TokenUsageSchema as ai, BaseEventSchema as an, ɵselectThreadsIsLoading$1 as ao, OptionalMetadataSchema as ar, useAgent as at, CopilotSidebar as b, transformChunks as ba, VideoInputPartSchema as bi, DocumentInputContentSchema as bn, ReasoningStartEventSchema as br, createA2UIMessageRenderer as bt, CoAgentStateRendersProvider as c, parseProtoStream as ca, ToolCallEndEventSchema as ci, ContentPartSchema as cn, PartSourceSchema as cr, CopilotChatToolCallGroup as ct, shouldShowDevConsole as d, props as da, ToolCallStartEventSchema as di, CopilotKitCore$1 as dn, ReasoningCapabilitiesSchema as dr, useFrontendTools as dt, mergeMetadata as ea, TextMessageContentEventSchema as ei, AudioInputPartSchema as en, ɵselectMemoriesIsLoading$1 as eo, MoveOperationSchema as er, useConfigureSuggestions as et, useToast as f, randomUUID$2 as fa, ToolCallStatus$1 as fi, CopilotKitCoreErrorCode$1 as fn, ReasoningEncryptedValueEventSchema as fr, useFrontendTool as ft, useCopilotContext as g, select as ga, TransportCapabilitiesSchema as gi, CustomEventSchema as gn, ReasoningMessageContentEventSchema as gr, useCopilotKit$1 as gt, CopilotContext as h, runHttpRequest as ha, ToolsCapabilitiesSchema as hi, CopyOperationSchema as hn, ReasoningMessageChunkEventSchema as hr, CopilotKitProvider as ht, ThreadsContext as i, onInspectorActiveThread as ia, TextPartSchema as ii, BackwardCompatibility_0_0_57 as in, ɵselectThreadsError$1 as io, MultimodalOutputCapabilitiesSchema as ir, UseAgentUpdate as it, messageGroup as j, ɵcreateThreadStore$1 as ja, createActionGroup as ji, FunctionMiddleware as jn, RunFinishedSuccessOutcomeSchema as jr, ɵrunMcpFollowUp as jt, CopilotChatAttachmentQueue as k, ɵcreateMemoryStore as ka, contentToText$1 as ki, FilterToolCallsMiddleware as kn, RunFinishedInterruptOutcomeSchema as kr, MCPAppsActivityRenderer as kt, useCoAgentStateRenders as l, parseSSEStream as la, ToolCallResultEventSchema as li, ContextSchema as ln, ProxiedCopilotRuntimeAgent$1 as lr, useRenderTool as lt, useCopilotMessagesContext as m, resolveDebugLogger as ma, ToolSchema as mi, CopilotKitHeaderResolutionError as mn, ReasoningEndEventSchema as mr, useRenderCustomMessages as mt, defaultCopilotContextCategories as n, omitOptionalNulls as na, TextMessageRoleSchema as ni, BackwardCompatibility_0_0_39 as nn, ɵselectMemoriesRealtimeStatus$1 as no, MultimodalCapabilitiesSchema as nr, useAgentContext as nt, useThreads as o, onInspectorViewThread$1 as oa, ToolCallArgsEventSchema as oi, BaseMessageSchema as on, ɵthreadAdapterEvents as oo, OutputCapabilitiesSchema as or, useHumanInTheLoop as ot, CopilotMessagesContext as p, resolveAgentDebugConfig as pa, ToolMessageSchema as pi, CopilotKitCoreRuntimeConnectionStatus$1 as pn, ReasoningEncryptedValueSubtypeSchema as pr, useRenderActivityMessage as pt, useAttachments as q, ɵselectFetchMoreError$1 as qa, getRunOutcome as qi, JsonPointerSchema as qn, SubagentRunIdSchema as qr, AddOperationSchema as qt, CoAgentStateRenderBridge as r, on as ra, TextMessageStartEventSchema as ri, BackwardCompatibility_0_0_45 as rn, ɵselectThreads$1 as ro, MultimodalInputCapabilitiesSchema as rr, useCapabilities as rt, CoAgentStateRendersContext as s, onInspectorViewThreadResult as sa, ToolCallChunkEventSchema as si, CompatibilityBoundary as sn, ɵwithHeaderDefaults$1 as so, PROTOCOL_VERSION as sr, useDefaultRenderTool as st, CopilotKit as t, ofType as ta, TextMessageEndEventSchema as ti, AudioPartSchema as tn, ɵselectMemoriesIsMutating as to, MultiAgentCapabilitiesSchema as tr, useSuggestions as tt, useAsyncCallback as u, parseToolArguments as ua, ToolCallSchema as ui, ContextStore as un, RawEventSchema as ur, useComponent as ut, CopilotThreadsDrawer as v, tokenUsageFromAiSdkUsage as va, UserMessageSchema as vi, DebugLogger as vn, ReasoningMessageSchema as vr, CopilotKitCoreReact as vt, CopilotChatToggleButton as w, ɵCOPILOTKIT_FEATURES as wa, authoritativeActivityTypes as wi, EventSchemas as wn, RoleSchema as wr, OpenGenerativeUIContentSchema as wt, CopilotPopupView as x, transformHttpEventStream as xa, VideoPartSchema as xi, DocumentInputPartSchema as xn, RemoveOperationSchema as xr, GenerateSandboxedUiArgsSchema as xt, CopilotPopup as y, tokenUsageFromLangChainMetadata as ya, VideoInputContentSchema as yi, DeveloperMessageSchema as yn, ReasoningMessageStartEventSchema as yr, defineToolCallRenderer as yt, CopilotChatSuggestionPill as z, ɵmemoryReducer as za, emitInspectorActiveThread$1 as zi, InputContentDataSourceSchema as zn, StepFinishedEventSchema as zr, ACTIVITY_HISTORY_METADATA as zt };
|
|
14487
|
+
//# sourceMappingURL=copilotkit-BNLtgOyD.mjs.map
|