@copilotkit/react-core 1.80.0 → 1.82.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/MarkdownSurfaces-DGpjmPaB.mjs +3531 -0
- package/dist/MarkdownSurfaces-DGpjmPaB.mjs.map +1 -0
- package/dist/MarkdownSurfaces-FF5za2kU.cjs +3816 -0
- package/dist/MarkdownSurfaces-FF5za2kU.cjs.map +1 -0
- package/dist/{copilotkit-CWOSXhRO.d.mts → copilotkit-C765tOUi.d.mts} +70 -36
- package/dist/copilotkit-C765tOUi.d.mts.map +1 -0
- package/dist/{copilotkit-DKICi3nC.cjs → copilotkit-CVvbU9lV.cjs} +2162 -675
- package/dist/copilotkit-CVvbU9lV.cjs.map +1 -0
- package/dist/{copilotkit-BNLtgOyD.mjs → copilotkit-DDReN1Px.mjs} +2106 -568
- package/dist/copilotkit-DDReN1Px.mjs.map +1 -0
- package/dist/{copilotkit-Dfw9HzO9.d.cts → copilotkit-wqaNanhw.d.cts} +70 -36
- package/dist/copilotkit-wqaNanhw.d.cts.map +1 -0
- package/dist/index.cjs +8 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +2 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2 -1
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +4474 -11
- package/dist/index.umd.js.map +1 -1
- package/dist/runtime-context-CrHq-iTf.d.mts +924 -0
- package/dist/runtime-context-CrHq-iTf.d.mts.map +1 -0
- package/dist/runtime-context-D3NcP9oE.d.cts +924 -0
- package/dist/runtime-context-D3NcP9oE.d.cts.map +1 -0
- package/dist/v2/generative-ui.cjs +8154 -0
- package/dist/v2/generative-ui.cjs.map +1 -0
- package/dist/v2/generative-ui.d.cts +4950 -0
- package/dist/v2/generative-ui.d.cts.map +1 -0
- package/dist/v2/generative-ui.d.mts +4950 -0
- package/dist/v2/generative-ui.d.mts.map +1 -0
- package/dist/v2/generative-ui.mjs +8140 -0
- package/dist/v2/generative-ui.mjs.map +1 -0
- package/dist/v2/headless.cjs +10 -1
- package/dist/v2/headless.cjs.map +1 -1
- package/dist/v2/headless.d.cts +9 -0
- package/dist/v2/headless.d.cts.map +1 -1
- package/dist/v2/headless.d.mts +9 -0
- package/dist/v2/headless.d.mts.map +1 -1
- package/dist/v2/headless.mjs +10 -1
- package/dist/v2/headless.mjs.map +1 -1
- package/dist/v2/index.cjs +65 -4
- package/dist/v2/index.css +1 -1
- package/dist/v2/index.d.cts +3 -2
- package/dist/v2/index.d.mts +3 -2
- package/dist/v2/index.mjs +3 -2
- package/dist/v2/index.umd.js +4962 -236
- package/dist/v2/index.umd.js.map +1 -1
- package/package.json +21 -8
- package/dist/copilotkit-BNLtgOyD.mjs.map +0 -1
- package/dist/copilotkit-CWOSXhRO.d.mts.map +0 -1
- package/dist/copilotkit-DKICi3nC.cjs.map +0 -1
- package/dist/copilotkit-Dfw9HzO9.d.cts.map +0 -1
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
import { A as isRecord, B as useCopilotChatConfiguration, C as validateSchemaSync, D as BASIC_FUNCTIONS, E as getMarkdownSurfaceSource, F as defineToolCallRenderer, H as useShallowStableRef, I as useKatexStyles, L as ControlledModalOpenScope, M as componentCatalogIds, O as ExpressionError, P as toJsonSchema, R as CopilotChatConfigurationProvider, S as issueKey, T as containsDynamicValue, V as shallowEqual, _ as GenerativeUIRuntimeContext, a as createGenerativeUIActivityRenderer, b as formatIssues, i as GenerativeUIToolCallRenderer, j as catalogIdsOf, k as GenerativeUIError, o as createGenerativeUIFunctionCallActivityRenderer, r as GenerativeUIChatSlotContext, t as MarkdownSurfaces, v as useGenerativeUIRuntime, w as withoutRejectedNulls, x as isAsyncIssue, z as CopilotChatDefaultLabels } from "./MarkdownSurfaces-DGpjmPaB.mjs";
|
|
1
2
|
import * as React$1 from "react";
|
|
2
3
|
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
|
+
import { A2UI_FENCE_LANGUAGE, 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, classifySurfaceCards, completePartialMarkdown, createActionGroup, createEffect, createInspectorThreadRequestId, createReducer, createSelector, createStore, emitInspectorActiveThread, emitInspectorActiveThread as emitInspectorActiveThread$1, emitInspectorStopViewing, emitInspectorViewThread, emitInspectorViewThreadResult, emitInspectorViewThreadResult as emitInspectorViewThreadResult$1, empty, ensureObjectArgs, extractCompleteArrayItems, extractFenceOperations as extractFenceOperations$1, extractStringField, flattenInformationalCards as flattenInformationalCards$1, getMarkdownOperationSurfaceId as getMarkdownOperationSurfaceId$1, 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, prepareSurfaceOperations as prepareSurfaceOperations$1, props, segmentSurfaceProse as segmentSurfaceProse$1, select, splitA2UIMarkdown as splitA2UIMarkdown$1, ɵ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
5
|
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
6
|
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
7
|
import { extendTailwindMerge, twMerge } from "tailwind-merge";
|
|
7
8
|
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
|
-
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
|
+
import { A2UI_COMPONENT_ENVELOPE_KEYS, A2UI_DEFAULT_DESIGN_GUIDELINES, A2UI_DEFAULT_GENERATION_GUIDELINES, A2UI_VERSION, COPILOTKIT_FORWARDED_PROPS_KEY, COPILOTKIT_UI_ENVELOPE_FORMAT, 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, GENERATIVE_UI_ACTIVITY_TYPE, GENERATIVE_UI_AGENT_FUNCTION_CALLS, GENERATIVE_UI_AGENT_FUNCTION_CALLS_OFF_REASON, GENERATIVE_UI_CHAT_TARGET, GENERATIVE_UI_FUNCTIONS, GENERATIVE_UI_FUNCTION_CALL_ACTIVITY_TYPE, GENERATIVE_UI_MARKDOWN_GUIDELINES_DESCRIPTION, GENERATIVE_UI_MARKDOWN_SCHEMA_CONTEXT_DESCRIPTION, GENERATIVE_UI_MAX_REJECTION_LENGTH, GENERATIVE_UI_MAX_SUMMARY_REJECTIONS, MissingPublicApiKeyError, Severity, TranscriptionErrorCode, TranscriptionErrorCode as TranscriptionErrorCode$1, buildGenerativeUIMarkdownGuidelines, buildGenerativeUIPrompt, callerProblem, childRefKind, commitRowKeyStore, copyToClipboard, createAttachmentContent, createLicenseContextValue, createRowKeyStore, dataToUUID, envelopeToManifest, exceedsMaxSize, formatFileSize, functionCallers, generateVideoThumbnail, generativeUIGuideFeatures, getDocumentIcon, getModalityFromMimeType, getOperationKind, getOperationSurfaceId, getSourceUrl, matchesAcceptFilter, parseJson, partialJSONParse, randomId, randomUUID as randomUUID$1, readFileAsBase64, resolveRowRenderKeysById, schemaToJsonSchema, shouldEnableInspector, toA2UIActionMessage, validateOperation } from "@copilotkit/shared";
|
|
9
10
|
import { CopilotKitAgentIdContext, CopilotKitContext, LicenseContext, useCopilotKit, useCopilotKit as useCopilotKit$1, useDefaultAgentId, useLicenseContext, useLicenseContext as useLicenseContext$1 } from "@copilotkit/react-core/v2/context";
|
|
10
11
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
11
12
|
import { Slot } from "@radix-ui/react-slot";
|
|
@@ -19,6 +20,7 @@ import { z } from "zod";
|
|
|
19
20
|
import { MCPAppsActivityContentSchema, MCPAppsActivityType, ɵrunMcpFollowUp } from "@copilotkit/mcp-apps-renderer/activity";
|
|
20
21
|
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
22
|
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
23
|
+
import { Catalog as Catalog$1, ComponentModel, DataModel, SurfaceModel } from "@a2ui/web_core/v0_9";
|
|
22
24
|
import * as PopoverPrimitive from "@radix-ui/react-popover";
|
|
23
25
|
import { createPortal, flushSync } from "react-dom";
|
|
24
26
|
import { useVirtualizer } from "@tanstack/react-virtual";
|
|
@@ -26,342 +28,6 @@ import { StickToBottom, useStickToBottomContext } from "use-stick-to-bottom";
|
|
|
26
28
|
import { COPILOTKIT_THREADS_DRAWER_TAG, defineCopilotKitThreadsDrawer } from "@copilotkit/web-components/threads-drawer";
|
|
27
29
|
import ReactMarkdown from "react-markdown";
|
|
28
30
|
|
|
29
|
-
//#region src/v2/lib/shallow-stable-ref.ts
|
|
30
|
-
/**
|
|
31
|
-
* Shallow equality comparison for objects.
|
|
32
|
-
*/
|
|
33
|
-
function shallowEqual(obj1, obj2) {
|
|
34
|
-
const keys1 = Object.keys(obj1);
|
|
35
|
-
const keys2 = Object.keys(obj2);
|
|
36
|
-
if (keys1.length !== keys2.length) return false;
|
|
37
|
-
for (const key of keys1) if (obj1[key] !== obj2[key]) return false;
|
|
38
|
-
return true;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Returns true only for plain JS objects (`{}`), excluding arrays, Dates,
|
|
42
|
-
* class instances, and other exotic objects that happen to have typeof "object".
|
|
43
|
-
*/
|
|
44
|
-
function isPlainObject$1(obj) {
|
|
45
|
-
return obj !== null && typeof obj === "object" && Object.prototype.toString.call(obj) === "[object Object]";
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Returns the same reference as long as the value is shallowly equal to the
|
|
49
|
-
* previous render's value.
|
|
50
|
-
*
|
|
51
|
-
* - Identical references bail out immediately (O(1)).
|
|
52
|
-
* - Plain objects ({}) are shallow-compared key-by-key.
|
|
53
|
-
* - Arrays, Dates, class instances, functions, and primitives are compared by
|
|
54
|
-
* reference only — shallowEqual is never called on non-plain objects, which
|
|
55
|
-
* avoids incorrect equality for e.g. [1,2] vs [1,2] (different arrays).
|
|
56
|
-
*
|
|
57
|
-
* Typical use: stabilize inline slot props so MemoizedSlotWrapper's shallow
|
|
58
|
-
* equality check isn't defeated by a new object reference on every render.
|
|
59
|
-
*/
|
|
60
|
-
function useShallowStableRef(value) {
|
|
61
|
-
const ref = useRef(value);
|
|
62
|
-
if (ref.current === value) return ref.current;
|
|
63
|
-
if (isPlainObject$1(ref.current) && isPlainObject$1(value)) {
|
|
64
|
-
if (shallowEqual(ref.current, value)) return ref.current;
|
|
65
|
-
}
|
|
66
|
-
ref.current = value;
|
|
67
|
-
return ref.current;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
//#endregion
|
|
71
|
-
//#region src/v2/providers/CopilotChatConfigurationProvider.tsx
|
|
72
|
-
const CopilotChatDefaultLabels = {
|
|
73
|
-
chatInputPlaceholder: "Type a message...",
|
|
74
|
-
chatInputToolbarStartTranscribeButtonLabel: "Transcribe",
|
|
75
|
-
chatInputToolbarCancelTranscribeButtonLabel: "Cancel",
|
|
76
|
-
chatInputToolbarFinishTranscribeButtonLabel: "Finish",
|
|
77
|
-
chatInputToolbarAddButtonLabel: "Add attachments",
|
|
78
|
-
chatInputToolbarToolsButtonLabel: "Tools",
|
|
79
|
-
chatInputToolbarSendButtonLabel: "Send message",
|
|
80
|
-
chatInputToolbarStopButtonLabel: "Stop",
|
|
81
|
-
assistantMessageToolbarCopyCodeLabel: "Copy",
|
|
82
|
-
assistantMessageToolbarCopyCodeCopiedLabel: "Copied",
|
|
83
|
-
assistantMessageToolbarCopyMessageLabel: "Copy",
|
|
84
|
-
assistantMessageToolbarInspectorLabel: "View in Inspector",
|
|
85
|
-
assistantMessageToolbarInspectorDescription: "Open this message in the Inspector",
|
|
86
|
-
assistantMessageToolbarInspectorLocalOnlyLabel: "Local only",
|
|
87
|
-
assistantMessageToolbarInspectorLocalOnlyDescription: "Only visible on localhost or loopback hosts in development. Never shown in production.",
|
|
88
|
-
assistantMessageToolbarInspectorTitle: "CopilotKit Inspector",
|
|
89
|
-
assistantMessageToolbarInspectorHideLabel: "Hide this icon",
|
|
90
|
-
assistantMessageToolbarInspectorHideDescription: "Until you reload this page",
|
|
91
|
-
assistantMessageToolbarThumbsUpLabel: "Good response",
|
|
92
|
-
assistantMessageToolbarThumbsDownLabel: "Bad response",
|
|
93
|
-
assistantMessageFeedbackCommentPlaceholder: "Add a comment (optional)",
|
|
94
|
-
assistantMessageFeedbackCommentSubmitLabel: "Send comment",
|
|
95
|
-
assistantMessageToolbarReadAloudLabel: "Read aloud",
|
|
96
|
-
assistantMessageToolbarRegenerateLabel: "Regenerate",
|
|
97
|
-
userMessageToolbarCopyMessageLabel: "Copy",
|
|
98
|
-
userMessageToolbarEditMessageLabel: "Edit",
|
|
99
|
-
userMessageToolbarPreviousBranchLabel: "Previous branch",
|
|
100
|
-
userMessageToolbarNextBranchLabel: "Next branch",
|
|
101
|
-
chatDisclaimerText: "AI can make mistakes. Please verify important information.",
|
|
102
|
-
chatToggleOpenLabel: "Open chat",
|
|
103
|
-
chatToggleCloseLabel: "Close chat",
|
|
104
|
-
chatScrollToBottomLabel: "Scroll to bottom",
|
|
105
|
-
modalHeaderTitle: "CopilotKit Chat",
|
|
106
|
-
welcomeMessageText: "How can I help you today?"
|
|
107
|
-
};
|
|
108
|
-
/**
|
|
109
|
-
* Mobile breakpoint below which the chat modal and the thread-list drawer are
|
|
110
|
-
* mutually exclusive. At or above this width both surfaces may coexist. This
|
|
111
|
-
* mirrors the `(max-width: 767px)` / `(min-width: 768px)` split already used by
|
|
112
|
-
* CopilotChatInput and CopilotSidebarView.
|
|
113
|
-
*/
|
|
114
|
-
const MOBILE_MAX_WIDTH_PX = 767;
|
|
115
|
-
/**
|
|
116
|
-
* Reports whether the current viewport is in the mobile range (`<768px`), where
|
|
117
|
-
* the chat modal and drawer must not be open simultaneously. SSR-safe and
|
|
118
|
-
* defensive against environments without `matchMedia` (treated as desktop, so
|
|
119
|
-
* no mutual-exclusion constraint is applied).
|
|
120
|
-
*
|
|
121
|
-
* @returns `true` when the viewport is mobile-width, `false` otherwise.
|
|
122
|
-
*/
|
|
123
|
-
function isMobileViewport() {
|
|
124
|
-
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return false;
|
|
125
|
-
return window.matchMedia(`(max-width: ${MOBILE_MAX_WIDTH_PX}px)`).matches;
|
|
126
|
-
}
|
|
127
|
-
const CopilotChatConfiguration = createContext(null);
|
|
128
|
-
const CopilotChatConfigurationProvider = ({ children, labels, agentId, threadId, hasExplicitThreadId, isModalDefaultOpen }) => {
|
|
129
|
-
const parentConfig = useContext(CopilotChatConfiguration);
|
|
130
|
-
const stableLabels = useShallowStableRef(labels);
|
|
131
|
-
const mergedLabels = useMemo(() => ({
|
|
132
|
-
...CopilotChatDefaultLabels,
|
|
133
|
-
...parentConfig?.labels,
|
|
134
|
-
...stableLabels
|
|
135
|
-
}), [stableLabels, parentConfig?.labels]);
|
|
136
|
-
const providerAgentId = useDefaultAgentId();
|
|
137
|
-
const resolvedAgentId = agentId ?? parentConfig?.agentId ?? providerAgentId ?? DEFAULT_AGENT_ID;
|
|
138
|
-
const threadIdPropIsAuthoritative = threadId !== void 0 && hasExplicitThreadId !== false;
|
|
139
|
-
const isThreadIdControlled = threadIdPropIsAuthoritative;
|
|
140
|
-
const [activeThreadOverride, setActiveThreadOverride] = useState(null);
|
|
141
|
-
const resolvedThreadId = useMemo(() => {
|
|
142
|
-
if (threadIdPropIsAuthoritative) return threadId;
|
|
143
|
-
if (activeThreadOverride) return activeThreadOverride.threadId;
|
|
144
|
-
if (parentConfig?.threadId) return parentConfig.threadId;
|
|
145
|
-
if (threadId) return threadId;
|
|
146
|
-
return randomUUID$1();
|
|
147
|
-
}, [
|
|
148
|
-
threadIdPropIsAuthoritative,
|
|
149
|
-
threadId,
|
|
150
|
-
parentConfig?.threadId,
|
|
151
|
-
activeThreadOverride
|
|
152
|
-
]);
|
|
153
|
-
const copilotkit = useContext(CopilotKitContext)?.copilotkit;
|
|
154
|
-
const openThreadRef = useRef(null);
|
|
155
|
-
const latestThreadIdRef = useRef(resolvedThreadId);
|
|
156
|
-
latestThreadIdRef.current = resolvedThreadId;
|
|
157
|
-
useEffect(() => {
|
|
158
|
-
if (copilotkit === void 0) return;
|
|
159
|
-
const registration = copilotkit.registerOpenThread({
|
|
160
|
-
agentId: resolvedAgentId,
|
|
161
|
-
threadId: latestThreadIdRef.current
|
|
162
|
-
});
|
|
163
|
-
openThreadRef.current = registration;
|
|
164
|
-
return () => {
|
|
165
|
-
registration.unregister();
|
|
166
|
-
openThreadRef.current = null;
|
|
167
|
-
};
|
|
168
|
-
}, [copilotkit, resolvedAgentId]);
|
|
169
|
-
useEffect(() => {
|
|
170
|
-
openThreadRef.current?.update(resolvedThreadId);
|
|
171
|
-
}, [resolvedThreadId]);
|
|
172
|
-
const resolvedHasExplicitThreadId = (threadIdPropIsAuthoritative ? true : activeThreadOverride?.explicit ?? hasExplicitThreadId ?? false) || !!parentConfig?.hasExplicitThreadId;
|
|
173
|
-
const [internalModalOpen, setInternalModalOpen] = useState(isModalDefaultOpen ?? true);
|
|
174
|
-
const hasExplicitDefault = isModalDefaultOpen !== void 0;
|
|
175
|
-
const setAndSync = useCallback((open) => {
|
|
176
|
-
setInternalModalOpen(open);
|
|
177
|
-
parentConfig?.setModalOpen(open);
|
|
178
|
-
}, [parentConfig?.setModalOpen]);
|
|
179
|
-
const isMounted = useRef(false);
|
|
180
|
-
useEffect(() => {
|
|
181
|
-
if (!hasExplicitDefault) return;
|
|
182
|
-
if (!isMounted.current) {
|
|
183
|
-
isMounted.current = true;
|
|
184
|
-
return;
|
|
185
|
-
}
|
|
186
|
-
if (parentConfig?.isModalOpen === void 0) return;
|
|
187
|
-
setInternalModalOpen(parentConfig.isModalOpen);
|
|
188
|
-
}, [parentConfig?.isModalOpen, hasExplicitDefault]);
|
|
189
|
-
const resolvedIsModalOpen = hasExplicitDefault ? internalModalOpen : parentConfig?.isModalOpen ?? internalModalOpen;
|
|
190
|
-
const resolvedSetModalOpen = hasExplicitDefault ? setAndSync : parentConfig?.setModalOpen ?? setInternalModalOpen;
|
|
191
|
-
const [ownDrawerOpen, setOwnDrawerOpen] = useState(false);
|
|
192
|
-
const [ownDrawerCount, setOwnDrawerCount] = useState(0);
|
|
193
|
-
const modalCloseRef = useRef(() => {});
|
|
194
|
-
modalCloseRef.current = resolvedSetModalOpen;
|
|
195
|
-
const registeredModalClosersRef = useRef([]);
|
|
196
|
-
const ownRegisterModalCloser = useCallback((closeModal) => {
|
|
197
|
-
registeredModalClosersRef.current.push(closeModal);
|
|
198
|
-
return () => {
|
|
199
|
-
registeredModalClosersRef.current = registeredModalClosersRef.current.filter((entry) => entry !== closeModal);
|
|
200
|
-
};
|
|
201
|
-
}, []);
|
|
202
|
-
const ownSetDrawerOpen = useCallback((open) => {
|
|
203
|
-
setOwnDrawerOpen(open);
|
|
204
|
-
if (open && isMobileViewport()) {
|
|
205
|
-
const registered = registeredModalClosersRef.current;
|
|
206
|
-
(registered.length > 0 ? registered[registered.length - 1] : modalCloseRef.current)(false);
|
|
207
|
-
}
|
|
208
|
-
}, []);
|
|
209
|
-
const ownRegisterDrawer = useCallback(() => {
|
|
210
|
-
setOwnDrawerCount((count) => count + 1);
|
|
211
|
-
return () => {
|
|
212
|
-
setOwnDrawerCount((count) => Math.max(0, count - 1));
|
|
213
|
-
};
|
|
214
|
-
}, []);
|
|
215
|
-
const resolvedDrawerOpen = parentConfig ? parentConfig.drawerOpen : ownDrawerOpen;
|
|
216
|
-
const resolvedSetDrawerOpen = parentConfig ? parentConfig.setDrawerOpen : ownSetDrawerOpen;
|
|
217
|
-
const resolvedDrawerRegistered = parentConfig ? parentConfig.drawerRegistered : ownDrawerCount > 0;
|
|
218
|
-
const resolvedRegisterDrawer = parentConfig ? parentConfig.registerDrawer : ownRegisterDrawer;
|
|
219
|
-
const resolvedRegisterModalCloser = parentConfig ? parentConfig.ɵregisterModalCloser : ownRegisterModalCloser;
|
|
220
|
-
useEffect(() => {
|
|
221
|
-
if (!hasExplicitDefault) return;
|
|
222
|
-
return resolvedRegisterModalCloser(resolvedSetModalOpen);
|
|
223
|
-
}, [
|
|
224
|
-
hasExplicitDefault,
|
|
225
|
-
resolvedRegisterModalCloser,
|
|
226
|
-
resolvedSetModalOpen
|
|
227
|
-
]);
|
|
228
|
-
const isThreadIdControlledRef = useRef(isThreadIdControlled);
|
|
229
|
-
isThreadIdControlledRef.current = isThreadIdControlled;
|
|
230
|
-
const ownSetActiveThreadId = useCallback((id, options) => {
|
|
231
|
-
setActiveThreadOverride({
|
|
232
|
-
threadId: id,
|
|
233
|
-
explicit: options?.explicit ?? true
|
|
234
|
-
});
|
|
235
|
-
}, []);
|
|
236
|
-
const ownStartNewThread = useCallback(() => {
|
|
237
|
-
setActiveThreadOverride({
|
|
238
|
-
threadId: randomUUID$1(),
|
|
239
|
-
explicit: false
|
|
240
|
-
});
|
|
241
|
-
}, []);
|
|
242
|
-
const parentSetActiveThreadId = parentConfig?.setActiveThreadId;
|
|
243
|
-
const parentStartNewThread = parentConfig?.startNewThread;
|
|
244
|
-
const resolvedSetActiveThreadId = useCallback((id, options) => {
|
|
245
|
-
if (isThreadIdControlledRef.current) {
|
|
246
|
-
console.warn("[CopilotKit] Ignoring setActiveThreadId(): threadId is controlled via the `threadId` prop on CopilotChatConfigurationProvider.");
|
|
247
|
-
return;
|
|
248
|
-
}
|
|
249
|
-
if (parentSetActiveThreadId) {
|
|
250
|
-
parentSetActiveThreadId(id, options);
|
|
251
|
-
return;
|
|
252
|
-
}
|
|
253
|
-
ownSetActiveThreadId(id, options);
|
|
254
|
-
}, [parentSetActiveThreadId, ownSetActiveThreadId]);
|
|
255
|
-
const resolvedStartNewThread = useCallback(() => {
|
|
256
|
-
if (isThreadIdControlledRef.current) {
|
|
257
|
-
console.warn("[CopilotKit] Ignoring startNewThread(): threadId is controlled via the `threadId` prop on CopilotChatConfigurationProvider.");
|
|
258
|
-
return;
|
|
259
|
-
}
|
|
260
|
-
if (parentStartNewThread) {
|
|
261
|
-
parentStartNewThread();
|
|
262
|
-
return;
|
|
263
|
-
}
|
|
264
|
-
ownStartNewThread();
|
|
265
|
-
}, [parentStartNewThread, ownStartNewThread]);
|
|
266
|
-
const setModalOpenWithDrawerExclusion = useCallback((open) => {
|
|
267
|
-
if (open && isMobileViewport()) resolvedSetDrawerOpen(false);
|
|
268
|
-
resolvedSetModalOpen(open);
|
|
269
|
-
}, [resolvedSetModalOpen, resolvedSetDrawerOpen]);
|
|
270
|
-
const configurationValue = useMemo(() => ({
|
|
271
|
-
labels: mergedLabels,
|
|
272
|
-
agentId: resolvedAgentId,
|
|
273
|
-
threadId: resolvedThreadId,
|
|
274
|
-
hasExplicitThreadId: resolvedHasExplicitThreadId,
|
|
275
|
-
isModalOpen: resolvedIsModalOpen,
|
|
276
|
-
setModalOpen: setModalOpenWithDrawerExclusion,
|
|
277
|
-
drawerOpen: resolvedDrawerOpen,
|
|
278
|
-
setDrawerOpen: resolvedSetDrawerOpen,
|
|
279
|
-
drawerRegistered: resolvedDrawerRegistered,
|
|
280
|
-
registerDrawer: resolvedRegisterDrawer,
|
|
281
|
-
ɵregisterModalCloser: resolvedRegisterModalCloser,
|
|
282
|
-
setActiveThreadId: resolvedSetActiveThreadId,
|
|
283
|
-
startNewThread: resolvedStartNewThread
|
|
284
|
-
}), [
|
|
285
|
-
mergedLabels,
|
|
286
|
-
resolvedAgentId,
|
|
287
|
-
resolvedThreadId,
|
|
288
|
-
resolvedHasExplicitThreadId,
|
|
289
|
-
resolvedIsModalOpen,
|
|
290
|
-
setModalOpenWithDrawerExclusion,
|
|
291
|
-
resolvedDrawerOpen,
|
|
292
|
-
resolvedSetDrawerOpen,
|
|
293
|
-
resolvedDrawerRegistered,
|
|
294
|
-
resolvedRegisterDrawer,
|
|
295
|
-
resolvedRegisterModalCloser,
|
|
296
|
-
resolvedSetActiveThreadId,
|
|
297
|
-
resolvedStartNewThread
|
|
298
|
-
]);
|
|
299
|
-
return /* @__PURE__ */ jsx(CopilotChatConfiguration.Provider, {
|
|
300
|
-
value: configurationValue,
|
|
301
|
-
children
|
|
302
|
-
});
|
|
303
|
-
};
|
|
304
|
-
const useCopilotChatConfiguration = () => {
|
|
305
|
-
return useContext(CopilotChatConfiguration);
|
|
306
|
-
};
|
|
307
|
-
/**
|
|
308
|
-
* Reports modal open/close requests to the host, and — when `open` is
|
|
309
|
-
* supplied — makes the modal state of an already-established chat
|
|
310
|
-
* configuration **controlled** for the subtree it wraps.
|
|
311
|
-
*
|
|
312
|
-
* This is deliberately a scope component rather than another mode inside
|
|
313
|
-
* {@link CopilotChatConfigurationProvider}. The provider resolves modal state
|
|
314
|
-
* across a nested chain (own state, parent sync, drawer mutual-exclusion, the
|
|
315
|
-
* modal-closer registry); a controlled branch inside that resolution would add
|
|
316
|
-
* a fourth interacting mode. Overriding the context for the subtree instead
|
|
317
|
-
* leaves every one of those paths untouched:
|
|
318
|
-
*
|
|
319
|
-
* - `isModalOpen` is replaced with the host's `open`, so the rendered surface
|
|
320
|
-
* follows the prop from the very first frame (no open-then-close flash).
|
|
321
|
-
* - `setModalOpen` still calls the underlying setter, so the existing
|
|
322
|
-
* parent-sync and drawer mutual-exclusion side effects continue to run, and
|
|
323
|
-
* *then* reports the request through `onOpenChange`.
|
|
324
|
-
* - The wrapped setter is registered as the modal closer, so the drawer's
|
|
325
|
-
* mobile mutual-exclusion reaches the host instead of silently flipping
|
|
326
|
-
* state that nothing displays.
|
|
327
|
-
*
|
|
328
|
-
* A host that supplies `open` and ignores `onOpenChange` gets a modal pinned
|
|
329
|
-
* to `open`, which is the standard controlled-component contract. A host that
|
|
330
|
-
* supplies only `onOpenChange` is notified while the modal keeps managing
|
|
331
|
-
* itself.
|
|
332
|
-
*
|
|
333
|
-
* Renders `children` unchanged when no chat configuration is in scope.
|
|
334
|
-
*/
|
|
335
|
-
const ControlledModalOpenScope = ({ children, open, onOpenChange }) => {
|
|
336
|
-
const parentConfig = useContext(CopilotChatConfiguration);
|
|
337
|
-
const parentSetModalOpen = parentConfig?.setModalOpen;
|
|
338
|
-
const registerModalCloser = parentConfig?.ɵregisterModalCloser;
|
|
339
|
-
const setModalOpen = useCallback((next) => {
|
|
340
|
-
parentSetModalOpen?.(next);
|
|
341
|
-
onOpenChange?.(next);
|
|
342
|
-
}, [parentSetModalOpen, onOpenChange]);
|
|
343
|
-
useEffect(() => {
|
|
344
|
-
if (!registerModalCloser) return;
|
|
345
|
-
return registerModalCloser(setModalOpen);
|
|
346
|
-
}, [registerModalCloser, setModalOpen]);
|
|
347
|
-
const configurationValue = useMemo(() => parentConfig ? {
|
|
348
|
-
...parentConfig,
|
|
349
|
-
isModalOpen: open ?? parentConfig.isModalOpen,
|
|
350
|
-
setModalOpen
|
|
351
|
-
} : null, [
|
|
352
|
-
parentConfig,
|
|
353
|
-
open,
|
|
354
|
-
setModalOpen
|
|
355
|
-
]);
|
|
356
|
-
if (!configurationValue) return /* @__PURE__ */ jsx(Fragment$1, { children });
|
|
357
|
-
return /* @__PURE__ */ jsx(CopilotChatConfiguration.Provider, {
|
|
358
|
-
value: configurationValue,
|
|
359
|
-
children
|
|
360
|
-
});
|
|
361
|
-
};
|
|
362
|
-
ControlledModalOpenScope.displayName = "ControlledModalOpenScope";
|
|
363
|
-
|
|
364
|
-
//#endregion
|
|
365
31
|
//#region src/v2/lib/utils.ts
|
|
366
32
|
const twMerge$1 = extendTailwindMerge({ prefix: "cpk" });
|
|
367
33
|
function cn(...inputs) {
|
|
@@ -1064,37 +730,6 @@ function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning =
|
|
|
1064
730
|
});
|
|
1065
731
|
const BoundDisclaimer = renderSlot(disclaimer, CopilotChatInput.Disclaimer, {});
|
|
1066
732
|
const shouldShowDisclaimer = showDisclaimer ?? positioning === "absolute";
|
|
1067
|
-
if (children) {
|
|
1068
|
-
const childProps = {
|
|
1069
|
-
textArea: BoundTextArea,
|
|
1070
|
-
audioRecorder: BoundAudioRecorder,
|
|
1071
|
-
sendButton: BoundSendButton,
|
|
1072
|
-
startTranscribeButton: BoundStartTranscribeButton,
|
|
1073
|
-
cancelTranscribeButton: BoundCancelTranscribeButton,
|
|
1074
|
-
finishTranscribeButton: BoundFinishTranscribeButton,
|
|
1075
|
-
addMenuButton: BoundAddMenuButton,
|
|
1076
|
-
disclaimer: BoundDisclaimer,
|
|
1077
|
-
onSubmitMessage,
|
|
1078
|
-
onStop,
|
|
1079
|
-
isRunning,
|
|
1080
|
-
onStartTranscribe,
|
|
1081
|
-
onCancelTranscribe,
|
|
1082
|
-
onFinishTranscribe,
|
|
1083
|
-
onAddFile,
|
|
1084
|
-
mode,
|
|
1085
|
-
toolsMenu,
|
|
1086
|
-
autoFocus,
|
|
1087
|
-
positioning,
|
|
1088
|
-
keyboardHeight,
|
|
1089
|
-
showDisclaimer: shouldShowDisclaimer,
|
|
1090
|
-
containerRef
|
|
1091
|
-
};
|
|
1092
|
-
return /* @__PURE__ */ jsx("div", {
|
|
1093
|
-
"data-copilotkit": true,
|
|
1094
|
-
style: { display: "contents" },
|
|
1095
|
-
children: children(childProps)
|
|
1096
|
-
});
|
|
1097
|
-
}
|
|
1098
733
|
const handleContainerClick = (e) => {
|
|
1099
734
|
const target = e.target;
|
|
1100
735
|
if (target.tagName !== "BUTTON" && !target.closest("button") && inputRef.current && mode === "input") inputRef.current.focus();
|
|
@@ -1178,7 +813,11 @@ function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning =
|
|
|
1178
813
|
const grid = gridRef.current;
|
|
1179
814
|
const addContainer = addButtonContainerRef.current;
|
|
1180
815
|
const actionsContainer = actionsContainerRef.current;
|
|
1181
|
-
if (!textarea
|
|
816
|
+
if (!textarea) return;
|
|
817
|
+
if (!grid || !addContainer || !actionsContainer) {
|
|
818
|
+
adjustTextareaHeight();
|
|
819
|
+
return;
|
|
820
|
+
}
|
|
1182
821
|
if (measurementsRef.current.singleLineHeight === 0) ensureMeasurements();
|
|
1183
822
|
const scrollHeight = adjustTextareaHeight();
|
|
1184
823
|
const baseline = measurementsRef.current.singleLineHeight;
|
|
@@ -1282,13 +921,13 @@ function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning =
|
|
|
1282
921
|
const slashMenu = slashMenuVisible ? /* @__PURE__ */ jsx("div", {
|
|
1283
922
|
"data-testid": "copilot-slash-menu",
|
|
1284
923
|
role: "listbox",
|
|
1285
|
-
"aria-label":
|
|
924
|
+
"aria-label": labels.chatInputSlashMenuLabel,
|
|
1286
925
|
ref: slashMenuRef,
|
|
1287
926
|
className: "cpk:absolute cpk:bottom-full cpk:left-0 cpk:right-0 cpk:z-30 cpk:mb-2 cpk:max-h-64 cpk:overflow-y-auto cpk:rounded-lg cpk:border cpk:border-border cpk:bg-white cpk:shadow-lg cpk:dark:border-[#3a3a3a] cpk:dark:bg-[#1f1f1f]",
|
|
1288
927
|
style: { maxHeight: `${SLASH_MENU_MAX_VISIBLE_ITEMS * SLASH_MENU_ITEM_HEIGHT_PX}px` },
|
|
1289
928
|
children: filteredCommands.length === 0 ? /* @__PURE__ */ jsx("div", {
|
|
1290
929
|
className: "cpk:px-3 cpk:py-2 cpk:text-sm cpk:text-muted-foreground",
|
|
1291
|
-
children:
|
|
930
|
+
children: labels.chatInputSlashMenuEmptyText
|
|
1292
931
|
}) : filteredCommands.map((item, index) => {
|
|
1293
932
|
const isActive = index === slashHighlightIndex;
|
|
1294
933
|
return /* @__PURE__ */ jsx("button", {
|
|
@@ -1337,6 +976,37 @@ function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning =
|
|
|
1337
976
|
]
|
|
1338
977
|
})
|
|
1339
978
|
});
|
|
979
|
+
if (children) {
|
|
980
|
+
const childProps = {
|
|
981
|
+
textArea: BoundTextArea,
|
|
982
|
+
audioRecorder: BoundAudioRecorder,
|
|
983
|
+
sendButton: BoundSendButton,
|
|
984
|
+
startTranscribeButton: BoundStartTranscribeButton,
|
|
985
|
+
cancelTranscribeButton: BoundCancelTranscribeButton,
|
|
986
|
+
finishTranscribeButton: BoundFinishTranscribeButton,
|
|
987
|
+
addMenuButton: BoundAddMenuButton,
|
|
988
|
+
disclaimer: BoundDisclaimer,
|
|
989
|
+
onSubmitMessage,
|
|
990
|
+
onStop,
|
|
991
|
+
isRunning,
|
|
992
|
+
onStartTranscribe,
|
|
993
|
+
onCancelTranscribe,
|
|
994
|
+
onFinishTranscribe,
|
|
995
|
+
onAddFile,
|
|
996
|
+
mode,
|
|
997
|
+
toolsMenu,
|
|
998
|
+
autoFocus,
|
|
999
|
+
positioning,
|
|
1000
|
+
keyboardHeight,
|
|
1001
|
+
showDisclaimer: shouldShowDisclaimer,
|
|
1002
|
+
containerRef
|
|
1003
|
+
};
|
|
1004
|
+
return /* @__PURE__ */ jsx("div", {
|
|
1005
|
+
"data-copilotkit": true,
|
|
1006
|
+
style: { display: "contents" },
|
|
1007
|
+
children: children(childProps)
|
|
1008
|
+
});
|
|
1009
|
+
}
|
|
1340
1010
|
return /* @__PURE__ */ jsxs("div", {
|
|
1341
1011
|
"data-copilotkit": true,
|
|
1342
1012
|
ref: containerRef,
|
|
@@ -1517,25 +1187,6 @@ CopilotChatInput.AddMenuButton.displayName = "CopilotChatInput.AddMenuButton";
|
|
|
1517
1187
|
CopilotChatInput.Disclaimer.displayName = "CopilotChatInput.Disclaimer";
|
|
1518
1188
|
var CopilotChatInput_default = CopilotChatInput;
|
|
1519
1189
|
|
|
1520
|
-
//#endregion
|
|
1521
|
-
//#region src/v2/hooks/useKatexStyles.ts
|
|
1522
|
-
let injected = false;
|
|
1523
|
-
/**
|
|
1524
|
-
* Dynamically injects KaTeX CSS at runtime to avoid the Next.js
|
|
1525
|
-
* "Global CSS cannot be imported from within node_modules" build error.
|
|
1526
|
-
*
|
|
1527
|
-
* Uses a singleton flag so the stylesheet is only injected once.
|
|
1528
|
-
*/
|
|
1529
|
-
function useKatexStyles() {
|
|
1530
|
-
useEffect(() => {
|
|
1531
|
-
if (injected || typeof document === "undefined") return;
|
|
1532
|
-
injected = true;
|
|
1533
|
-
import("katex/dist/katex.min.css").catch(() => {
|
|
1534
|
-
console.warn("[CopilotKit] Failed to load katex styles — math content may render without formatting");
|
|
1535
|
-
});
|
|
1536
|
-
}, []);
|
|
1537
|
-
}
|
|
1538
|
-
|
|
1539
1190
|
//#endregion
|
|
1540
1191
|
//#region src/v2/hooks/use-render-tool-call.tsx
|
|
1541
1192
|
/**
|
|
@@ -1671,7 +1322,7 @@ function useRenderToolCall() {
|
|
|
1671
1322
|
|
|
1672
1323
|
//#endregion
|
|
1673
1324
|
//#region package.json
|
|
1674
|
-
var version = "1.
|
|
1325
|
+
var version = "1.82.0";
|
|
1675
1326
|
|
|
1676
1327
|
//#endregion
|
|
1677
1328
|
//#region src/v2/components/CopilotKitInspector.tsx
|
|
@@ -2976,7 +2627,7 @@ function createA2UIMessageRenderer(options) {
|
|
|
2976
2627
|
const groupedOperations = useMemo(() => {
|
|
2977
2628
|
const groups = /* @__PURE__ */ new Map();
|
|
2978
2629
|
for (const operation of operations) {
|
|
2979
|
-
const surfaceId = getOperationSurfaceId(operation) ?? DEFAULT_SURFACE_ID;
|
|
2630
|
+
const surfaceId = getOperationSurfaceId$1(operation) ?? DEFAULT_SURFACE_ID;
|
|
2980
2631
|
if (!groups.has(surfaceId)) groups.set(surfaceId, []);
|
|
2981
2632
|
groups.get(surfaceId).push(operation);
|
|
2982
2633
|
}
|
|
@@ -3198,7 +2849,7 @@ function surfaceHasRenderableContent(operations) {
|
|
|
3198
2849
|
* @param operation - One A2UI operation, of any shape.
|
|
3199
2850
|
* @returns The surface id, or null when the operation names none.
|
|
3200
2851
|
*/
|
|
3201
|
-
function getOperationSurfaceId(operation) {
|
|
2852
|
+
function getOperationSurfaceId$1(operation) {
|
|
3202
2853
|
if (!operation || typeof operation !== "object") return null;
|
|
3203
2854
|
const nested = operation?.createSurface?.surfaceId ?? operation?.updateComponents?.surfaceId ?? operation?.updateDataModel?.surfaceId ?? operation?.deleteSurface?.surfaceId;
|
|
3204
2855
|
if (typeof nested === "string") return nested;
|
|
@@ -3206,19 +2857,6 @@ function getOperationSurfaceId(operation) {
|
|
|
3206
2857
|
return null;
|
|
3207
2858
|
}
|
|
3208
2859
|
|
|
3209
|
-
//#endregion
|
|
3210
|
-
//#region src/v2/types/defineToolCallRenderer.ts
|
|
3211
|
-
function defineToolCallRenderer(def) {
|
|
3212
|
-
const argsSchema = def.name === "*" && !def.args ? z.any() : def.args;
|
|
3213
|
-
return {
|
|
3214
|
-
name: def.name,
|
|
3215
|
-
args: argsSchema,
|
|
3216
|
-
render: def.render,
|
|
3217
|
-
...def.agentId ? { agentId: def.agentId } : {},
|
|
3218
|
-
...def.group ? { group: true } : {}
|
|
3219
|
-
};
|
|
3220
|
-
}
|
|
3221
|
-
|
|
3222
2860
|
//#endregion
|
|
3223
2861
|
//#region src/v2/a2ui/A2UIToolCallRenderer.tsx
|
|
3224
2862
|
/**
|
|
@@ -3247,68 +2885,1881 @@ function A2UIBuiltInToolCallRenderer() {
|
|
|
3247
2885
|
args: z.any(),
|
|
3248
2886
|
render: () => /* @__PURE__ */ jsx(Fragment$1, {})
|
|
3249
2887
|
});
|
|
3250
|
-
const existing = copilotkit._renderToolCalls ?? [];
|
|
3251
|
-
copilotkit.setRenderToolCalls([...existing.filter((rc) => rc.name !== RENDER_A2UI_TOOL_NAME), renderer]);
|
|
3252
|
-
}, [copilotkit]);
|
|
3253
|
-
return null;
|
|
2888
|
+
const existing = copilotkit._renderToolCalls ?? [];
|
|
2889
|
+
copilotkit.setRenderToolCalls([...existing.filter((rc) => rc.name !== RENDER_A2UI_TOOL_NAME), renderer]);
|
|
2890
|
+
}, [copilotkit]);
|
|
2891
|
+
return null;
|
|
2892
|
+
}
|
|
2893
|
+
|
|
2894
|
+
//#endregion
|
|
2895
|
+
//#region src/v2/a2ui/A2UICatalogContext.tsx
|
|
2896
|
+
/**
|
|
2897
|
+
* Renders agent context describing the available A2UI catalog and custom components.
|
|
2898
|
+
* Only mount this component when A2UI is enabled.
|
|
2899
|
+
*
|
|
2900
|
+
* The entries are scoped to the agents the runtime applies A2UI to
|
|
2901
|
+
* (`copilotkit.a2uiAgents`, #5369), so agents outside that list don't receive
|
|
2902
|
+
* the catalog/schema/guidelines payload on their runs.
|
|
2903
|
+
*
|
|
2904
|
+
* When `includeSchema` is true, the full component schemas (JSON Schema) are also
|
|
2905
|
+
* sent as context using the same description key as the A2UI middleware, so the
|
|
2906
|
+
* middleware can optionally overwrite it with a server-side schema.
|
|
2907
|
+
*/
|
|
2908
|
+
function A2UICatalogContext({ catalog, includeSchema }) {
|
|
2909
|
+
const { copilotkit } = useCopilotKit$1();
|
|
2910
|
+
const capabilitiesValue = useMemo(() => buildCatalogContextValue(catalog, { includeSchema: includeSchema !== false }), [catalog, includeSchema]);
|
|
2911
|
+
const schemaValue = useMemo(() => includeSchema !== false ? JSON.stringify(extractCatalogComponentSchemas(catalog)) : null, [catalog, includeSchema]);
|
|
2912
|
+
const a2uiAgentsKey = copilotkit?.a2uiAgents?.join(",");
|
|
2913
|
+
useLayoutEffect(() => {
|
|
2914
|
+
if (!copilotkit) return;
|
|
2915
|
+
const agentIds = copilotkit.a2uiAgents;
|
|
2916
|
+
const scope = agentIds ? { agentIds } : {};
|
|
2917
|
+
const ids = [];
|
|
2918
|
+
ids.push(copilotkit.addContext({
|
|
2919
|
+
description: "A2UI catalog capabilities: available catalog IDs and custom component definitions the client can render.",
|
|
2920
|
+
value: capabilitiesValue,
|
|
2921
|
+
...scope
|
|
2922
|
+
}));
|
|
2923
|
+
if (schemaValue) {
|
|
2924
|
+
ids.push(copilotkit.addContext({
|
|
2925
|
+
description: A2UI_SCHEMA_CONTEXT_DESCRIPTION,
|
|
2926
|
+
value: schemaValue,
|
|
2927
|
+
...scope
|
|
2928
|
+
}));
|
|
2929
|
+
ids.push(copilotkit.addContext({
|
|
2930
|
+
description: "A2UI generation guidelines — protocol rules, tool arguments, path rules, data model format, and form/two-way-binding instructions.",
|
|
2931
|
+
value: A2UI_DEFAULT_GENERATION_GUIDELINES,
|
|
2932
|
+
...scope
|
|
2933
|
+
}));
|
|
2934
|
+
ids.push(copilotkit.addContext({
|
|
2935
|
+
description: "A2UI design guidelines — visual design rules, component hierarchy tips, and action handler patterns.",
|
|
2936
|
+
value: A2UI_DEFAULT_DESIGN_GUIDELINES,
|
|
2937
|
+
...scope
|
|
2938
|
+
}));
|
|
2939
|
+
}
|
|
2940
|
+
return () => {
|
|
2941
|
+
for (const id of ids) copilotkit.removeContext(id);
|
|
2942
|
+
};
|
|
2943
|
+
}, [
|
|
2944
|
+
copilotkit,
|
|
2945
|
+
capabilitiesValue,
|
|
2946
|
+
schemaValue,
|
|
2947
|
+
a2uiAgentsKey
|
|
2948
|
+
]);
|
|
2949
|
+
return null;
|
|
2950
|
+
}
|
|
2951
|
+
|
|
2952
|
+
//#endregion
|
|
2953
|
+
//#region src/v2/generative-ui/action-message.ts
|
|
2954
|
+
/** Context keys that supply the message's first line, in priority order. */
|
|
2955
|
+
const TEXT_KEYS = ["message", "label"];
|
|
2956
|
+
function isNonEmptyString(value) {
|
|
2957
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
2958
|
+
}
|
|
2959
|
+
/** `choose_plan`, `choose-plan` and `choosePlan` all become "Choose plan". */
|
|
2960
|
+
function humanize(name) {
|
|
2961
|
+
const spaced = name.replace(/[_-]+/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").trim();
|
|
2962
|
+
return spaced.charAt(0).toUpperCase() + spaced.slice(1).toLowerCase();
|
|
2963
|
+
}
|
|
2964
|
+
function formatContextValue(value) {
|
|
2965
|
+
return typeof value === "object" ? JSON.stringify(value) : String(value);
|
|
2966
|
+
}
|
|
2967
|
+
/**
|
|
2968
|
+
* Turns a user event that no function handles into the text of a visible
|
|
2969
|
+
* user message.
|
|
2970
|
+
*
|
|
2971
|
+
* The first line is, in order: `userMessage`, `context.message`,
|
|
2972
|
+
* `context.label`, the label of the source component (from `resolveLabel`),
|
|
2973
|
+
* or the event name made readable (`choose_plan` becomes "Choose plan").
|
|
2974
|
+
* Each other context field follows as one `key: value` line. Objects are
|
|
2975
|
+
* written as JSON. `null` and `undefined` fields are skipped.
|
|
2976
|
+
*
|
|
2977
|
+
* @param event - The user event, as sent by a surface.
|
|
2978
|
+
* @param resolveLabel - Finds the visible label of a component by id. Build
|
|
2979
|
+
* one with {@link createComponentLabelResolver}.
|
|
2980
|
+
*
|
|
2981
|
+
* @example
|
|
2982
|
+
* ```ts
|
|
2983
|
+
* buildActionMessageText({
|
|
2984
|
+
* name: "choose_plan",
|
|
2985
|
+
* surfaceId: "plans",
|
|
2986
|
+
* componentId: "team-button",
|
|
2987
|
+
* userMessage: "I pick the Team plan",
|
|
2988
|
+
* context: { seats: 12 },
|
|
2989
|
+
* });
|
|
2990
|
+
* // "I pick the Team plan\n\nseats: 12"
|
|
2991
|
+
* ```
|
|
2992
|
+
*/
|
|
2993
|
+
function buildActionMessageText(event, resolveLabel) {
|
|
2994
|
+
const { context, userMessage } = event;
|
|
2995
|
+
const explicit = [userMessage, ...TEXT_KEYS.map((key) => context[key])].find(isNonEmptyString);
|
|
2996
|
+
const resolved = explicit ? void 0 : resolveLabel?.(event.componentId);
|
|
2997
|
+
const head = explicit ?? (isNonEmptyString(resolved) ? resolved.trim() : humanize(event.name));
|
|
2998
|
+
const lines = Object.entries(context).filter(([key, value]) => !TEXT_KEYS.includes(key) && value !== void 0 && value !== null).map(([key, value]) => `${key}: ${formatContextValue(value)}`);
|
|
2999
|
+
return lines.length > 0 ? `${head}\n\n${lines.join("\n")}` : head;
|
|
3000
|
+
}
|
|
3001
|
+
function ownText(component) {
|
|
3002
|
+
if (!component) return void 0;
|
|
3003
|
+
if (isNonEmptyString(component.label)) return component.label;
|
|
3004
|
+
if (isNonEmptyString(component.text)) return component.text;
|
|
3005
|
+
}
|
|
3006
|
+
function childIds(component) {
|
|
3007
|
+
const { child, children } = component;
|
|
3008
|
+
const single = typeof child === "string" ? [child] : [];
|
|
3009
|
+
const multiple = Array.isArray(children) ? children.filter((id) => typeof id === "string") : [];
|
|
3010
|
+
return [...single, ...multiple];
|
|
3011
|
+
}
|
|
3012
|
+
/** The components that an operation adds, inline or in an update. */
|
|
3013
|
+
function componentsOf(operation) {
|
|
3014
|
+
if ("createSurface" in operation) return operation.createSurface.components ?? [];
|
|
3015
|
+
if ("updateComponents" in operation) return operation.updateComponents.components;
|
|
3016
|
+
return [];
|
|
3017
|
+
}
|
|
3018
|
+
/**
|
|
3019
|
+
* Builds a function that finds the visible label of a component on a surface.
|
|
3020
|
+
*
|
|
3021
|
+
* The label is the component's own string `label`, else its string `text`,
|
|
3022
|
+
* else the first `child` or `children` component that has a string `label`
|
|
3023
|
+
* or `text`. When a component id is defined more than once, the last
|
|
3024
|
+
* definition wins, as in the renderer.
|
|
3025
|
+
*
|
|
3026
|
+
* @param operations - The committed operations of the surface.
|
|
3027
|
+
*
|
|
3028
|
+
* @example
|
|
3029
|
+
* ```ts
|
|
3030
|
+
* const resolveLabel = createComponentLabelResolver(surface.operations);
|
|
3031
|
+
* buildActionMessageText(event, resolveLabel);
|
|
3032
|
+
* ```
|
|
3033
|
+
*/
|
|
3034
|
+
function createComponentLabelResolver(operations) {
|
|
3035
|
+
const byId = /* @__PURE__ */ new Map();
|
|
3036
|
+
for (const operation of operations) {
|
|
3037
|
+
const components = componentsOf(operation);
|
|
3038
|
+
for (const component of components) byId.set(component.id, component);
|
|
3039
|
+
}
|
|
3040
|
+
return (componentId) => {
|
|
3041
|
+
const component = byId.get(componentId);
|
|
3042
|
+
if (!component) return void 0;
|
|
3043
|
+
const own = ownText(component);
|
|
3044
|
+
if (own) return own;
|
|
3045
|
+
const ids = childIds(component);
|
|
3046
|
+
for (const id of ids) {
|
|
3047
|
+
const text = ownText(byId.get(id));
|
|
3048
|
+
if (text) return text;
|
|
3049
|
+
}
|
|
3050
|
+
};
|
|
3051
|
+
}
|
|
3052
|
+
|
|
3053
|
+
//#endregion
|
|
3054
|
+
//#region src/v2/generative-ui/manifest.ts
|
|
3055
|
+
/**
|
|
3056
|
+
* The built-in functions (the A2UI basic catalog plus calc and series) as
|
|
3057
|
+
* manifest entries. Their args are described by the short signature, not
|
|
3058
|
+
* by a full JSON Schema: the renderer checks them when they run. An app
|
|
3059
|
+
* function of the same name replaces the entry.
|
|
3060
|
+
*/
|
|
3061
|
+
function builtInFunctionManifests() {
|
|
3062
|
+
return Object.fromEntries(Object.entries(GENERATIVE_UI_FUNCTIONS).map(([name, fn]) => [name, {
|
|
3063
|
+
description: fn.description,
|
|
3064
|
+
parameters: {
|
|
3065
|
+
type: "object",
|
|
3066
|
+
description: fn.parameters
|
|
3067
|
+
},
|
|
3068
|
+
returnType: fn.returnType,
|
|
3069
|
+
allowedCallers: fn.allowedCallers,
|
|
3070
|
+
...fn.requiresUserActivation ? { requiresUserActivation: true } : {}
|
|
3071
|
+
}]));
|
|
3072
|
+
}
|
|
3073
|
+
/**
|
|
3074
|
+
* Builds the per-run manifest. Never contains handlers or renderers.
|
|
3075
|
+
*
|
|
3076
|
+
* - `functions`: the built-in functions, then the declared functions with
|
|
3077
|
+
* exactly one mounted handler.
|
|
3078
|
+
* - `targets`: the chat first, then each mounted `<GenerativeUISurface>`,
|
|
3079
|
+
* with its `description` and its `components` when it has them.
|
|
3080
|
+
*/
|
|
3081
|
+
function buildGenerativeUIManifest(runtime, threadId) {
|
|
3082
|
+
const { ui, manager, dispatcher } = runtime;
|
|
3083
|
+
const inlineTargets = manager.getMountedTargets().filter((target) => target.id !== GENERATIVE_UI_CHAT_TARGET).map(({ id, ...rest }) => ({
|
|
3084
|
+
id,
|
|
3085
|
+
kind: "inline",
|
|
3086
|
+
...rest
|
|
3087
|
+
}));
|
|
3088
|
+
return {
|
|
3089
|
+
catalogId: ui.id,
|
|
3090
|
+
catalogIds: catalogIdsOf(ui),
|
|
3091
|
+
components: ui.manifestComponents,
|
|
3092
|
+
functions: {
|
|
3093
|
+
...Object.fromEntries(Object.entries(builtInFunctionManifests()).filter(([name]) => !ui.functions.has(name))),
|
|
3094
|
+
...dispatcher.listExposed()
|
|
3095
|
+
},
|
|
3096
|
+
targets: [{
|
|
3097
|
+
id: GENERATIVE_UI_CHAT_TARGET,
|
|
3098
|
+
kind: "chat"
|
|
3099
|
+
}, ...inlineTargets],
|
|
3100
|
+
surfaces: threadId ? manager.describeSurfaces(threadId) : {}
|
|
3101
|
+
};
|
|
3102
|
+
}
|
|
3103
|
+
/**
|
|
3104
|
+
* Builds the envelope that a run sends as `forwardedProps.copilotkit.ui`,
|
|
3105
|
+
* from the per-run manifest. It has the A2UI v1.0 renderer capabilities
|
|
3106
|
+
* shape: one inline catalog with the id of the UI, and the CopilotKit data
|
|
3107
|
+
* in `metadata.extensions`.
|
|
3108
|
+
*
|
|
3109
|
+
* The inline catalog has no `components` only for the markdown transport
|
|
3110
|
+
* with `includeCatalog: false`. It has `instructions` for the markdown
|
|
3111
|
+
* transport, or when given.
|
|
3112
|
+
*
|
|
3113
|
+
* @param runtime - The generative UI runtime of the provider.
|
|
3114
|
+
* @param threadId - The thread of the run. Its surfaces go in `copilotkit_surfaces`.
|
|
3115
|
+
* @param options - The transport and what to send.
|
|
3116
|
+
*
|
|
3117
|
+
* @example
|
|
3118
|
+
* ```ts
|
|
3119
|
+
* const envelope = buildGenerativeUIEnvelope(runtime, agent.threadId, {
|
|
3120
|
+
* transport: "tool",
|
|
3121
|
+
* includeCatalog: true,
|
|
3122
|
+
* contextSent: false,
|
|
3123
|
+
* });
|
|
3124
|
+
* envelope["v1.0"].supportedCatalogIds; // [runtime.ui.id]
|
|
3125
|
+
* ```
|
|
3126
|
+
*/
|
|
3127
|
+
function buildGenerativeUIEnvelope(runtime, threadId, options) {
|
|
3128
|
+
const { transport, includeCatalog, contextSent, action } = options;
|
|
3129
|
+
const manifest = buildGenerativeUIManifest(runtime, threadId);
|
|
3130
|
+
const instructions = options.instructions ?? (transport === "markdown" ? buildGenerativeUIMarkdownGuidelines(generativeUIGuideFeatures(manifest)) : void 0);
|
|
3131
|
+
const omitComponents = transport === "markdown" && !includeCatalog;
|
|
3132
|
+
return {
|
|
3133
|
+
"v1.0": {
|
|
3134
|
+
supportedCatalogIds: manifest.catalogIds ?? [manifest.catalogId],
|
|
3135
|
+
inlineCatalogs: [{
|
|
3136
|
+
catalogId: manifest.catalogId,
|
|
3137
|
+
protocolVersion: "1.0",
|
|
3138
|
+
...omitComponents ? {} : { components: manifest.components },
|
|
3139
|
+
functions: manifest.functions,
|
|
3140
|
+
...instructions === void 0 ? {} : { instructions }
|
|
3141
|
+
}]
|
|
3142
|
+
},
|
|
3143
|
+
metadata: { extensions: {
|
|
3144
|
+
copilotkit_format: COPILOTKIT_UI_ENVELOPE_FORMAT,
|
|
3145
|
+
copilotkit_transport: transport,
|
|
3146
|
+
copilotkit_targets: manifest.targets,
|
|
3147
|
+
copilotkit_surfaces: manifest.surfaces,
|
|
3148
|
+
copilotkit_contextSent: contextSent,
|
|
3149
|
+
...action === void 0 ? {} : { copilotkit_action: action }
|
|
3150
|
+
} }
|
|
3151
|
+
};
|
|
3152
|
+
}
|
|
3153
|
+
|
|
3154
|
+
//#endregion
|
|
3155
|
+
//#region src/v2/generative-ui/markdown/context.ts
|
|
3156
|
+
/** Objects nested deeper than this show as `object`. */
|
|
3157
|
+
const MAX_OBJECT_DEPTH = 2;
|
|
3158
|
+
/** A prop must appear verbatim in at least this many components to be hoisted. */
|
|
3159
|
+
const COMMON_PROP_MIN_COMPONENTS = 8;
|
|
3160
|
+
/** A JSON Schema of a list of schemas (`anyOf`, `oneOf`), else an empty list. */
|
|
3161
|
+
function schemaList(value) {
|
|
3162
|
+
return Array.isArray(value) ? value.filter(isRecord) : [];
|
|
3163
|
+
}
|
|
3164
|
+
/**
|
|
3165
|
+
* Puts a top-level union in parentheses, so that `[]` applies to all of
|
|
3166
|
+
* it. A union inside braces needs none.
|
|
3167
|
+
*/
|
|
3168
|
+
function asArrayItem(type) {
|
|
3169
|
+
let outside = type;
|
|
3170
|
+
for (let inner = outside.replace(/\{[^{}]*\}/g, ""); inner !== outside;) {
|
|
3171
|
+
outside = inner;
|
|
3172
|
+
inner = outside.replace(/\{[^{}]*\}/g, "");
|
|
3173
|
+
}
|
|
3174
|
+
return outside.includes(" | ") ? `(${type})[]` : `${type}[]`;
|
|
3175
|
+
}
|
|
3176
|
+
/**
|
|
3177
|
+
* A JSON Schema as a short TypeScript-like type, for example
|
|
3178
|
+
* `{ label: string; size?: "sm" | "md" }`.
|
|
3179
|
+
*/
|
|
3180
|
+
function compactType(schema, depth) {
|
|
3181
|
+
const ref = childRefKind(schema);
|
|
3182
|
+
if (ref === "single") return "componentId";
|
|
3183
|
+
if (ref === "multiple") return "componentId[] | { componentId: string; path: string }";
|
|
3184
|
+
if ("const" in schema) return JSON.stringify(schema.const);
|
|
3185
|
+
if (Array.isArray(schema.enum)) return schema.enum.map((value) => JSON.stringify(value)).join(" | ");
|
|
3186
|
+
const variants = [...schemaList(schema.anyOf), ...schemaList(schema.oneOf)];
|
|
3187
|
+
if (variants.length > 0) return variants.map((variant) => compactType(variant, depth)).join(" | ");
|
|
3188
|
+
return (Array.isArray(schema.type) ? schema.type : [schema.type]).map((type) => {
|
|
3189
|
+
switch (type) {
|
|
3190
|
+
case "string":
|
|
3191
|
+
case "boolean":
|
|
3192
|
+
case "null": return type;
|
|
3193
|
+
case "number":
|
|
3194
|
+
case "integer": return "number";
|
|
3195
|
+
case "array": return isRecord(schema.items) ? asArrayItem(compactType(schema.items, depth)) : "unknown[]";
|
|
3196
|
+
case "object": return compactObject(schema, depth);
|
|
3197
|
+
default: return "unknown";
|
|
3198
|
+
}
|
|
3199
|
+
}).join(" | ");
|
|
3200
|
+
}
|
|
3201
|
+
/** An object schema as `{ key: type; other?: type }`. */
|
|
3202
|
+
function compactObject(schema, depth) {
|
|
3203
|
+
const properties = isRecord(schema.properties) ? schema.properties : {};
|
|
3204
|
+
const entries = Object.entries(properties);
|
|
3205
|
+
if (entries.length === 0) return isRecord(schema.additionalProperties) ? `Record<string, ${compactType(schema.additionalProperties, depth + 1)}>` : "object";
|
|
3206
|
+
if (depth >= MAX_OBJECT_DEPTH) return "object";
|
|
3207
|
+
const required = Array.isArray(schema.required) ? schema.required : [];
|
|
3208
|
+
return `{ ${entries.map(([key, value]) => {
|
|
3209
|
+
const type = isRecord(value) ? compactType(value, depth + 1) : "unknown";
|
|
3210
|
+
return `${key}${required.includes(key) ? "" : "?"}: ${type}`;
|
|
3211
|
+
}).join("; ")} }`;
|
|
3212
|
+
}
|
|
3213
|
+
/** A schema as its type, with its description after `//`. */
|
|
3214
|
+
function describedType(schema, depth) {
|
|
3215
|
+
const type = compactType(schema, depth);
|
|
3216
|
+
return typeof schema.description === "string" ? `${type} // ${schema.description}` : type;
|
|
3217
|
+
}
|
|
3218
|
+
/** The props of a component: `{ "label": "string", "size?": "..." }`. */
|
|
3219
|
+
function compactProps(schema) {
|
|
3220
|
+
const properties = isRecord(schema.properties) ? schema.properties : {};
|
|
3221
|
+
const required = Array.isArray(schema.required) ? schema.required : [];
|
|
3222
|
+
const props = {};
|
|
3223
|
+
for (const [key, value] of Object.entries(properties)) {
|
|
3224
|
+
if (!isRecord(value)) continue;
|
|
3225
|
+
const name = required.includes(key) ? key : `${key}?`;
|
|
3226
|
+
props[name] = describedType(value, 1);
|
|
3227
|
+
}
|
|
3228
|
+
return props;
|
|
3229
|
+
}
|
|
3230
|
+
/**
|
|
3231
|
+
* The prop set worth listing once. Candidates are (key, type) pairs that at
|
|
3232
|
+
* least {@link COMMON_PROP_MIN_COMPONENTS} components carry verbatim. The
|
|
3233
|
+
* candidate subset of each component is a possible common set, scored by
|
|
3234
|
+
* the characters it saves (set size times the components that contain all
|
|
3235
|
+
* of it). `undefined` when no set is shared by enough components.
|
|
3236
|
+
*/
|
|
3237
|
+
function findCommonProps(propsList) {
|
|
3238
|
+
const pairKey = (key, type) => `${key}\u0000${type}`;
|
|
3239
|
+
const counts = /* @__PURE__ */ new Map();
|
|
3240
|
+
for (const props of propsList) for (const [key, type] of Object.entries(props)) {
|
|
3241
|
+
const id = pairKey(key, type);
|
|
3242
|
+
counts.set(id, (counts.get(id) ?? 0) + 1);
|
|
3243
|
+
}
|
|
3244
|
+
let best;
|
|
3245
|
+
let bestScore = 0;
|
|
3246
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3247
|
+
for (const props of propsList) {
|
|
3248
|
+
const subset = Object.entries(props).filter(([key, type]) => (counts.get(pairKey(key, type)) ?? 0) >= COMMON_PROP_MIN_COMPONENTS);
|
|
3249
|
+
if (subset.length < 2) continue;
|
|
3250
|
+
const signature = subset.map(([key, type]) => pairKey(key, type)).join("\n");
|
|
3251
|
+
if (seen.has(signature)) continue;
|
|
3252
|
+
seen.add(signature);
|
|
3253
|
+
const members = propsList.filter((other) => subset.every(([key, type]) => other[key] === type)).length;
|
|
3254
|
+
if (members < COMMON_PROP_MIN_COMPONENTS) continue;
|
|
3255
|
+
const score = subset.reduce((total, [key, type]) => total + key.length + type.length, 0) * (members - 1);
|
|
3256
|
+
if (score > bestScore) {
|
|
3257
|
+
bestScore = score;
|
|
3258
|
+
best = Object.fromEntries(subset);
|
|
3259
|
+
}
|
|
3260
|
+
}
|
|
3261
|
+
return best;
|
|
3262
|
+
}
|
|
3263
|
+
/**
|
|
3264
|
+
* The component schema of the markdown transport, from the per-run
|
|
3265
|
+
* manifest. It is smaller than the manifest: each prop is one short type,
|
|
3266
|
+
* and the props that many components share verbatim (the layout props of
|
|
3267
|
+
* the containers) are listed once in `commonProps`; a component that takes
|
|
3268
|
+
* them is flagged `includesCommonProps`.
|
|
3269
|
+
* It has the catalog id, the targets with their descriptions and their
|
|
3270
|
+
* component lists, the functions with their parameters, the components
|
|
3271
|
+
* with their props, events and slots, and the surfaces of the thread. A surface lists the
|
|
3272
|
+
* values that the user set and the operations that the client dropped.
|
|
3273
|
+
*
|
|
3274
|
+
* @param manifest - The manifest from `buildGenerativeUIManifest`.
|
|
3275
|
+
* @returns A JSON-ready object.
|
|
3276
|
+
*
|
|
3277
|
+
* @example
|
|
3278
|
+
* ```ts
|
|
3279
|
+
* const value = JSON.stringify(
|
|
3280
|
+
* buildCompactGenerativeUISchema(buildGenerativeUIManifest(runtime, threadId)),
|
|
3281
|
+
* );
|
|
3282
|
+
* ```
|
|
3283
|
+
*/
|
|
3284
|
+
function buildCompactGenerativeUISchema(manifest) {
|
|
3285
|
+
const components = {};
|
|
3286
|
+
for (const [name, component] of Object.entries(manifest.components)) {
|
|
3287
|
+
const events = Object.entries(component.events ?? {}).map(([event, definition]) => [event, definition.description ?? compactType(definition.parameters, 0)]);
|
|
3288
|
+
components[name] = {
|
|
3289
|
+
...component.description ? { description: component.description } : {},
|
|
3290
|
+
props: compactProps(component.props),
|
|
3291
|
+
...events.length > 0 ? { events: Object.fromEntries(events) } : {},
|
|
3292
|
+
...component.slots ? { slots: component.slots } : {}
|
|
3293
|
+
};
|
|
3294
|
+
}
|
|
3295
|
+
const common = findCommonProps(Object.values(components).map((component) => component.props));
|
|
3296
|
+
if (common) {
|
|
3297
|
+
const commonKeys = Object.keys(common);
|
|
3298
|
+
for (const component of Object.values(components)) {
|
|
3299
|
+
if (!commonKeys.every((key) => component.props[key] === common[key])) continue;
|
|
3300
|
+
component.includesCommonProps = true;
|
|
3301
|
+
component.props = Object.fromEntries(Object.entries(component.props).filter(([key]) => !(key in common)));
|
|
3302
|
+
}
|
|
3303
|
+
}
|
|
3304
|
+
const functions = Object.fromEntries(Object.entries(manifest.functions).map(([name, fn]) => {
|
|
3305
|
+
const signature = fn.parameters.description;
|
|
3306
|
+
const hasSignature = typeof signature === "string" && signature.startsWith("{") && Object.keys(fn.parameters).length === 2;
|
|
3307
|
+
const callers = functionCallers(fn);
|
|
3308
|
+
return [name, {
|
|
3309
|
+
...fn.description ? { description: fn.description } : {},
|
|
3310
|
+
parameters: hasSignature ? signature : compactType(fn.parameters, 0),
|
|
3311
|
+
...callers.agent && GENERATIVE_UI_AGENT_FUNCTION_CALLS ? { callers: callers.renderer ? "UI or agent" : "agent only" } : {}
|
|
3312
|
+
}];
|
|
3313
|
+
}));
|
|
3314
|
+
return {
|
|
3315
|
+
catalogId: manifest.catalogId,
|
|
3316
|
+
targets: manifest.targets,
|
|
3317
|
+
functions,
|
|
3318
|
+
...common ? { commonProps: common } : {},
|
|
3319
|
+
components,
|
|
3320
|
+
surfaces: manifest.surfaces
|
|
3321
|
+
};
|
|
3322
|
+
}
|
|
3323
|
+
/**
|
|
3324
|
+
* Registers the two context entries of the markdown transport: the compact
|
|
3325
|
+
* component schema and the fence guideline. Both go only to `agentIds`.
|
|
3326
|
+
*
|
|
3327
|
+
* The schema is built again at each run start and when a
|
|
3328
|
+
* `<GenerativeUISurface>` mounts, unmounts, or changes its description or
|
|
3329
|
+
* its components, so its targets, functions, and surfaces stay current. The surfaces are those of the running thread.
|
|
3330
|
+
*
|
|
3331
|
+
* @param copilotkit - The CopilotKit core of the provider.
|
|
3332
|
+
* @param runtime - The generative UI runtime parts, or null without one.
|
|
3333
|
+
* @param options - `enabled` and `agentIds`.
|
|
3334
|
+
*
|
|
3335
|
+
* @example
|
|
3336
|
+
* ```ts
|
|
3337
|
+
* useGenerativeUIMarkdownContext(copilotkit, core, {
|
|
3338
|
+
* enabled: config?.transport === "markdown" && config.sendContext !== false,
|
|
3339
|
+
* agentIds: config?.agentIds,
|
|
3340
|
+
* });
|
|
3341
|
+
* ```
|
|
3342
|
+
*/
|
|
3343
|
+
function useGenerativeUIMarkdownContext(copilotkit, runtime, options) {
|
|
3344
|
+
const { enabled, agentIds } = options;
|
|
3345
|
+
const agentIdsKey = agentIds === void 0 ? "" : JSON.stringify(agentIds);
|
|
3346
|
+
useEffect(() => {
|
|
3347
|
+
if (!runtime || !enabled) return;
|
|
3348
|
+
const scopedAgentIds = agentIdsKey ? JSON.parse(agentIdsKey) : void 0;
|
|
3349
|
+
const scope = scopedAgentIds ? { agentIds: scopedAgentIds } : {};
|
|
3350
|
+
let guidelineId;
|
|
3351
|
+
let guidelineValue;
|
|
3352
|
+
let schemaId;
|
|
3353
|
+
let schemaValue;
|
|
3354
|
+
const refreshSchema = (threadId) => {
|
|
3355
|
+
const manifest = buildGenerativeUIManifest(runtime, threadId);
|
|
3356
|
+
const guideline = buildGenerativeUIMarkdownGuidelines(generativeUIGuideFeatures(manifest));
|
|
3357
|
+
if (guideline !== guidelineValue) {
|
|
3358
|
+
if (guidelineId !== void 0) copilotkit.removeContext(guidelineId);
|
|
3359
|
+
guidelineValue = guideline;
|
|
3360
|
+
guidelineId = copilotkit.addContext({
|
|
3361
|
+
description: GENERATIVE_UI_MARKDOWN_GUIDELINES_DESCRIPTION,
|
|
3362
|
+
value: guideline,
|
|
3363
|
+
...scope
|
|
3364
|
+
});
|
|
3365
|
+
}
|
|
3366
|
+
const value = JSON.stringify(buildCompactGenerativeUISchema(manifest));
|
|
3367
|
+
if (value === schemaValue) return;
|
|
3368
|
+
if (schemaId !== void 0) copilotkit.removeContext(schemaId);
|
|
3369
|
+
schemaValue = value;
|
|
3370
|
+
schemaId = copilotkit.addContext({
|
|
3371
|
+
description: GENERATIVE_UI_MARKDOWN_SCHEMA_CONTEXT_DESCRIPTION,
|
|
3372
|
+
value,
|
|
3373
|
+
...scope
|
|
3374
|
+
});
|
|
3375
|
+
};
|
|
3376
|
+
refreshSchema(runtime.manager.getActiveThread());
|
|
3377
|
+
let targetsKey = JSON.stringify(runtime.manager.getMountedTargets());
|
|
3378
|
+
const unsubscribeManager = runtime.manager.subscribe(() => {
|
|
3379
|
+
const nextKey = JSON.stringify(runtime.manager.getMountedTargets());
|
|
3380
|
+
if (nextKey === targetsKey) return;
|
|
3381
|
+
targetsKey = nextKey;
|
|
3382
|
+
refreshSchema(runtime.manager.getActiveThread());
|
|
3383
|
+
});
|
|
3384
|
+
const subscription = copilotkit.subscribe({ onAgentRunStarted: ({ agent }) => refreshSchema(agent.threadId) });
|
|
3385
|
+
return () => {
|
|
3386
|
+
subscription.unsubscribe();
|
|
3387
|
+
unsubscribeManager();
|
|
3388
|
+
if (guidelineId !== void 0) copilotkit.removeContext(guidelineId);
|
|
3389
|
+
if (schemaId !== void 0) copilotkit.removeContext(schemaId);
|
|
3390
|
+
};
|
|
3391
|
+
}, [
|
|
3392
|
+
copilotkit,
|
|
3393
|
+
runtime,
|
|
3394
|
+
enabled,
|
|
3395
|
+
agentIdsKey
|
|
3396
|
+
]);
|
|
3397
|
+
}
|
|
3398
|
+
|
|
3399
|
+
//#endregion
|
|
3400
|
+
//#region src/v2/generative-ui/debug-source.ts
|
|
3401
|
+
/**
|
|
3402
|
+
* What a run of `threadId` sends: its envelope, and the text that goes into
|
|
3403
|
+
* the prompt of the model because of it.
|
|
3404
|
+
*
|
|
3405
|
+
* - Tool transport: the runtime adds the `render_ui` guide. It builds it
|
|
3406
|
+
* from the envelope with `buildGenerativeUIPrompt`, as done here.
|
|
3407
|
+
* - Markdown transport: the provider sends the guideline and the compact
|
|
3408
|
+
* schema as context entries. With `sendContext: false`, the backend builds
|
|
3409
|
+
* its own prompt, usually from the `instructions` of the envelope.
|
|
3410
|
+
*/
|
|
3411
|
+
function describeGenerativeUIRun(runtime, threadId, options) {
|
|
3412
|
+
const envelope = buildGenerativeUIEnvelope(runtime, threadId, options);
|
|
3413
|
+
if (options.transport === "tool") return {
|
|
3414
|
+
envelope,
|
|
3415
|
+
prompt: [{
|
|
3416
|
+
title: "render_ui guide",
|
|
3417
|
+
source: "runtime",
|
|
3418
|
+
text: buildGenerativeUIPrompt(envelopeToManifest(envelope))
|
|
3419
|
+
}]
|
|
3420
|
+
};
|
|
3421
|
+
const manifest = buildGenerativeUIManifest(runtime, threadId);
|
|
3422
|
+
if (!options.contextSent) return {
|
|
3423
|
+
envelope,
|
|
3424
|
+
prompt: [{
|
|
3425
|
+
title: "Envelope instructions",
|
|
3426
|
+
source: "backend",
|
|
3427
|
+
text: envelopeToManifest(envelope).instructions ?? ""
|
|
3428
|
+
}]
|
|
3429
|
+
};
|
|
3430
|
+
const guideline = buildGenerativeUIMarkdownGuidelines(generativeUIGuideFeatures(manifest));
|
|
3431
|
+
const schema = JSON.stringify(buildCompactGenerativeUISchema(manifest));
|
|
3432
|
+
return {
|
|
3433
|
+
envelope,
|
|
3434
|
+
prompt: [{
|
|
3435
|
+
title: "Markdown guideline",
|
|
3436
|
+
source: "context",
|
|
3437
|
+
text: guideline
|
|
3438
|
+
}, {
|
|
3439
|
+
title: "Component schema",
|
|
3440
|
+
source: "context",
|
|
3441
|
+
text: schema
|
|
3442
|
+
}]
|
|
3443
|
+
};
|
|
3444
|
+
}
|
|
3445
|
+
/** The declared functions, with the JSON Schema of their parameters. */
|
|
3446
|
+
function debugFunctions(runtime) {
|
|
3447
|
+
const functions = {};
|
|
3448
|
+
for (const [name, declared] of runtime.ui.functions) {
|
|
3449
|
+
let parameters = {};
|
|
3450
|
+
try {
|
|
3451
|
+
parameters = toJsonSchema(declared.parameters);
|
|
3452
|
+
} catch {}
|
|
3453
|
+
functions[name] = {
|
|
3454
|
+
...declared.description ? { description: declared.description } : {},
|
|
3455
|
+
parameters,
|
|
3456
|
+
handlers: runtime.dispatcher.handlerCount(name)
|
|
3457
|
+
};
|
|
3458
|
+
}
|
|
3459
|
+
return functions;
|
|
3460
|
+
}
|
|
3461
|
+
/**
|
|
3462
|
+
* The debug source that the provider gives core for the inspector. It builds
|
|
3463
|
+
* a snapshot only when the inspector reads one.
|
|
3464
|
+
*
|
|
3465
|
+
* @param runtime - The generative UI parts of the provider.
|
|
3466
|
+
* @param getOptions - The envelope options and agent ids of the current config.
|
|
3467
|
+
* @returns The source, and `recordRun` for each run start.
|
|
3468
|
+
*/
|
|
3469
|
+
function createGenerativeUIDebugSource(runtime, getOptions) {
|
|
3470
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
3471
|
+
let lastRun;
|
|
3472
|
+
const notify = () => {
|
|
3473
|
+
for (const listener of [...listeners]) listener();
|
|
3474
|
+
};
|
|
3475
|
+
return {
|
|
3476
|
+
source: {
|
|
3477
|
+
getSnapshot() {
|
|
3478
|
+
const { options, agentIds } = getOptions();
|
|
3479
|
+
const threadId = runtime.manager.getActiveThread();
|
|
3480
|
+
const manifest = buildGenerativeUIManifest(runtime, threadId);
|
|
3481
|
+
return {
|
|
3482
|
+
catalogId: runtime.ui.id,
|
|
3483
|
+
transport: options.transport,
|
|
3484
|
+
...agentIds ? { agentIds } : {},
|
|
3485
|
+
components: runtime.ui.manifestComponents,
|
|
3486
|
+
componentCatalogs: Object.fromEntries(componentCatalogIds(runtime.ui)),
|
|
3487
|
+
functions: debugFunctions(runtime),
|
|
3488
|
+
state: { ...runtime.manager.getState() },
|
|
3489
|
+
targets: manifest.targets,
|
|
3490
|
+
activeThreadId: threadId,
|
|
3491
|
+
surfaces: runtime.manager.debugSurfaces(),
|
|
3492
|
+
lastRun,
|
|
3493
|
+
nextRun: {
|
|
3494
|
+
agentId: void 0,
|
|
3495
|
+
threadId,
|
|
3496
|
+
...describeGenerativeUIRun(runtime, threadId, options)
|
|
3497
|
+
}
|
|
3498
|
+
};
|
|
3499
|
+
},
|
|
3500
|
+
subscribe(listener) {
|
|
3501
|
+
listeners.add(listener);
|
|
3502
|
+
const unsubscribe = runtime.manager.subscribe(listener);
|
|
3503
|
+
return () => {
|
|
3504
|
+
listeners.delete(listener);
|
|
3505
|
+
unsubscribe();
|
|
3506
|
+
};
|
|
3507
|
+
}
|
|
3508
|
+
},
|
|
3509
|
+
recordRun(run) {
|
|
3510
|
+
lastRun = run;
|
|
3511
|
+
notify();
|
|
3512
|
+
}
|
|
3513
|
+
};
|
|
3514
|
+
}
|
|
3515
|
+
|
|
3516
|
+
//#endregion
|
|
3517
|
+
//#region src/v2/generative-ui/dispatcher.ts
|
|
3518
|
+
const messageOf = (error) => error instanceof Error ? error.message : String(error);
|
|
3519
|
+
/**
|
|
3520
|
+
* Creates the registry of functions that generated UI may call.
|
|
3521
|
+
*
|
|
3522
|
+
* A function is callable when it is declared in `getDeclared()` and exactly
|
|
3523
|
+
* one handler is mounted for it with `register`. Names are resolved at call
|
|
3524
|
+
* time and fail closed. Nothing is sent to the agent.
|
|
3525
|
+
* Neither `invoke` nor `listExposed` throws.
|
|
3526
|
+
*
|
|
3527
|
+
* @param options.getDeclared - Returns the declared functions.
|
|
3528
|
+
* @param options.onError - Gets each failed call.
|
|
3529
|
+
*
|
|
3530
|
+
* @example
|
|
3531
|
+
* ```ts
|
|
3532
|
+
* const dispatcher = createGenerativeUIDispatcher({
|
|
3533
|
+
* getDeclared: () => new Map(Object.entries(ui.functions)),
|
|
3534
|
+
* });
|
|
3535
|
+
* const unregister = dispatcher.register("addToCart", handlerRef);
|
|
3536
|
+
* await dispatcher.invoke("addToCart", { productId: "p1" }, origin);
|
|
3537
|
+
* unregister();
|
|
3538
|
+
* ```
|
|
3539
|
+
*/
|
|
3540
|
+
/**
|
|
3541
|
+
* True while the browser counts the current task as user-activated (a
|
|
3542
|
+
* click, a key press). Where the API is missing (older browsers, test
|
|
3543
|
+
* environments), the gesture is assumed.
|
|
3544
|
+
*/
|
|
3545
|
+
function hasUserActivation() {
|
|
3546
|
+
if (typeof navigator === "undefined") return true;
|
|
3547
|
+
const activation = navigator.userActivation;
|
|
3548
|
+
return activation === void 0 || activation.isActive;
|
|
3549
|
+
}
|
|
3550
|
+
/**
|
|
3551
|
+
* The permissions of a declared function as the manifest states them: the
|
|
3552
|
+
* callers always written out, so a reader needs no default.
|
|
3553
|
+
*/
|
|
3554
|
+
function permissionsOf(fn) {
|
|
3555
|
+
const callers = functionCallers(fn);
|
|
3556
|
+
return {
|
|
3557
|
+
allowedCallers: callers.renderer && callers.agent ? "rendererOrAgent" : callers.agent ? "agentOnly" : "rendererOnly",
|
|
3558
|
+
...fn.requiresUserActivation ? { requiresUserActivation: true } : {}
|
|
3559
|
+
};
|
|
3560
|
+
}
|
|
3561
|
+
function createGenerativeUIDispatcher(options) {
|
|
3562
|
+
const handlers = /* @__PURE__ */ new Map();
|
|
3563
|
+
const resolveUnchecked = (name) => {
|
|
3564
|
+
const declared = options.getDeclared().get(name);
|
|
3565
|
+
if (!declared) return {
|
|
3566
|
+
ok: false,
|
|
3567
|
+
error: new GenerativeUIError("function_not_found", `No generative UI function named "${name}" is declared in createGenerativeUI({ functions })`)
|
|
3568
|
+
};
|
|
3569
|
+
const mounted = [...handlers.get(name) ?? []];
|
|
3570
|
+
const [ref] = mounted;
|
|
3571
|
+
if (!ref) return {
|
|
3572
|
+
ok: false,
|
|
3573
|
+
error: new GenerativeUIError("function_not_found", `"${name}" is declared, but no useGenerativeUIFunction handler is mounted for it`)
|
|
3574
|
+
};
|
|
3575
|
+
if (mounted.length > 1) return {
|
|
3576
|
+
ok: false,
|
|
3577
|
+
error: new GenerativeUIError("function_conflict", `"${name}" has ${mounted.length} useGenerativeUIFunction handlers mounted. Mount exactly one.`)
|
|
3578
|
+
};
|
|
3579
|
+
return {
|
|
3580
|
+
ok: true,
|
|
3581
|
+
declared,
|
|
3582
|
+
ref
|
|
3583
|
+
};
|
|
3584
|
+
};
|
|
3585
|
+
const isDeclared = (name) => {
|
|
3586
|
+
try {
|
|
3587
|
+
return options.getDeclared().has(name);
|
|
3588
|
+
} catch {
|
|
3589
|
+
return false;
|
|
3590
|
+
}
|
|
3591
|
+
};
|
|
3592
|
+
const resolve = (name) => {
|
|
3593
|
+
try {
|
|
3594
|
+
return resolveUnchecked(name);
|
|
3595
|
+
} catch (error) {
|
|
3596
|
+
return {
|
|
3597
|
+
ok: false,
|
|
3598
|
+
error: new GenerativeUIError("handler_failed", `"${name}" could not be resolved: ${messageOf(error)}`)
|
|
3599
|
+
};
|
|
3600
|
+
}
|
|
3601
|
+
};
|
|
3602
|
+
const validateArgs = async (name, schema, args) => {
|
|
3603
|
+
try {
|
|
3604
|
+
const validation = await schema["~standard"].validate(args);
|
|
3605
|
+
if (!validation.issues) return {
|
|
3606
|
+
ok: true,
|
|
3607
|
+
value: validation.value
|
|
3608
|
+
};
|
|
3609
|
+
return {
|
|
3610
|
+
ok: false,
|
|
3611
|
+
error: new GenerativeUIError("invalid_arguments", `Invalid arguments for "${name}": ${validation.issues.map((i) => `${(i.path ?? []).map((p) => typeof p === "object" ? p.key : p).join(".") || "args"}: ${i.message}`).join("; ")}`)
|
|
3612
|
+
};
|
|
3613
|
+
} catch (error) {
|
|
3614
|
+
return {
|
|
3615
|
+
ok: false,
|
|
3616
|
+
error: new GenerativeUIError("invalid_arguments", `Invalid arguments for "${name}": ${messageOf(error)}`)
|
|
3617
|
+
};
|
|
3618
|
+
}
|
|
3619
|
+
};
|
|
3620
|
+
const failWith = (name, origin, error) => {
|
|
3621
|
+
try {
|
|
3622
|
+
options.onError?.({
|
|
3623
|
+
name,
|
|
3624
|
+
origin,
|
|
3625
|
+
error
|
|
3626
|
+
});
|
|
3627
|
+
} catch {}
|
|
3628
|
+
return {
|
|
3629
|
+
ok: false,
|
|
3630
|
+
error
|
|
3631
|
+
};
|
|
3632
|
+
};
|
|
3633
|
+
/**
|
|
3634
|
+
* Why `origin` may not call a function with these permissions now, as an
|
|
3635
|
+
* error, or `undefined` when it may. The agent is refused what is for the
|
|
3636
|
+
* renderer; a component is refused what is for the agent, and a gesture
|
|
3637
|
+
* function when the browser counts no user activation.
|
|
3638
|
+
*/
|
|
3639
|
+
const callerError = (name, fn, origin) => {
|
|
3640
|
+
const isComponent = "componentId" in origin;
|
|
3641
|
+
if (!isComponent && !GENERATIVE_UI_AGENT_FUNCTION_CALLS) return new GenerativeUIError("invalid_function_call", GENERATIVE_UI_AGENT_FUNCTION_CALLS_OFF_REASON);
|
|
3642
|
+
const problem = callerProblem(name, fn, isComponent ? "renderer" : "agent");
|
|
3643
|
+
if (problem !== void 0) return new GenerativeUIError("invalid_function_call", problem);
|
|
3644
|
+
if (isComponent && fn.requiresUserActivation && !hasUserActivation()) return new GenerativeUIError("invalid_function_call", `function "${name}" runs only from a user gesture; this event was not one`);
|
|
3645
|
+
};
|
|
3646
|
+
/**
|
|
3647
|
+
* Runs a basic function of the A2UI catalog. They are value functions of
|
|
3648
|
+
* the renderer: the agent cannot call them, and one that needs a user
|
|
3649
|
+
* gesture runs only from an event binding.
|
|
3650
|
+
*/
|
|
3651
|
+
const invokeBasic = (name, args, origin) => {
|
|
3652
|
+
const refused = callerError(name, GENERATIVE_UI_FUNCTIONS[name], origin);
|
|
3653
|
+
if (refused) return failWith(name, origin, refused);
|
|
3654
|
+
if (args !== void 0 && !(typeof args === "object" && args !== null && !Array.isArray(args))) return failWith(name, origin, new GenerativeUIError("invalid_arguments", `Invalid arguments for "${name}": args must be an object`));
|
|
3655
|
+
try {
|
|
3656
|
+
return {
|
|
3657
|
+
ok: true,
|
|
3658
|
+
result: BASIC_FUNCTIONS[name](args ?? {})
|
|
3659
|
+
};
|
|
3660
|
+
} catch (error) {
|
|
3661
|
+
return failWith(name, origin, new GenerativeUIError(error instanceof ExpressionError ? "invalid_arguments" : "handler_failed", `"${name}" failed: ${messageOf(error)}`));
|
|
3662
|
+
}
|
|
3663
|
+
};
|
|
3664
|
+
return {
|
|
3665
|
+
async invoke(name, args, origin) {
|
|
3666
|
+
const resolved = resolve(name);
|
|
3667
|
+
if (!resolved.ok && resolved.error.code === "function_not_found" && !isDeclared(name) && Object.prototype.hasOwnProperty.call(BASIC_FUNCTIONS, name)) return invokeBasic(name, args, origin);
|
|
3668
|
+
if (!resolved.ok) return failWith(name, origin, resolved.error);
|
|
3669
|
+
const refused = callerError(name, resolved.declared, origin);
|
|
3670
|
+
if (refused) return failWith(name, origin, refused);
|
|
3671
|
+
const validated = await validateArgs(name, resolved.declared.parameters, args ?? {});
|
|
3672
|
+
if (!validated.ok) return failWith(name, origin, validated.error);
|
|
3673
|
+
try {
|
|
3674
|
+
return {
|
|
3675
|
+
ok: true,
|
|
3676
|
+
result: await resolved.ref.current(validated.value)
|
|
3677
|
+
};
|
|
3678
|
+
} catch (error) {
|
|
3679
|
+
return failWith(name, origin, new GenerativeUIError("handler_failed", `"${name}" failed: ${messageOf(error)}`));
|
|
3680
|
+
}
|
|
3681
|
+
},
|
|
3682
|
+
listExposed() {
|
|
3683
|
+
let names;
|
|
3684
|
+
try {
|
|
3685
|
+
names = [...options.getDeclared().keys()];
|
|
3686
|
+
} catch {
|
|
3687
|
+
return {};
|
|
3688
|
+
}
|
|
3689
|
+
const listed = {};
|
|
3690
|
+
for (const name of names) {
|
|
3691
|
+
const resolved = resolve(name);
|
|
3692
|
+
if (!resolved.ok) continue;
|
|
3693
|
+
if (!functionCallers(resolved.declared).renderer && !GENERATIVE_UI_AGENT_FUNCTION_CALLS) continue;
|
|
3694
|
+
const { description, parameters, returnType } = resolved.declared;
|
|
3695
|
+
try {
|
|
3696
|
+
listed[name] = {
|
|
3697
|
+
...description ? { description } : {},
|
|
3698
|
+
parameters: toJsonSchema(parameters),
|
|
3699
|
+
...returnType ? { returnType } : {},
|
|
3700
|
+
...permissionsOf(resolved.declared)
|
|
3701
|
+
};
|
|
3702
|
+
} catch {}
|
|
3703
|
+
}
|
|
3704
|
+
return listed;
|
|
3705
|
+
},
|
|
3706
|
+
register(name, ref) {
|
|
3707
|
+
const mounted = handlers.get(name) ?? /* @__PURE__ */ new Set();
|
|
3708
|
+
mounted.add(ref);
|
|
3709
|
+
handlers.set(name, mounted);
|
|
3710
|
+
return () => {
|
|
3711
|
+
mounted.delete(ref);
|
|
3712
|
+
};
|
|
3713
|
+
},
|
|
3714
|
+
handlerCount: (name) => handlers.get(name)?.size ?? 0
|
|
3715
|
+
};
|
|
3716
|
+
}
|
|
3717
|
+
|
|
3718
|
+
//#endregion
|
|
3719
|
+
//#region src/v2/generative-ui/surface-manager.ts
|
|
3720
|
+
function surfaceKey(threadId, surfaceId) {
|
|
3721
|
+
return `${threadId}::${surfaceId}`;
|
|
3722
|
+
}
|
|
3723
|
+
let creationCounter = 0;
|
|
3724
|
+
const FORBIDDEN_SEGMENTS = new Set([
|
|
3725
|
+
"__proto__",
|
|
3726
|
+
"constructor",
|
|
3727
|
+
"prototype"
|
|
3728
|
+
]);
|
|
3729
|
+
/** "/a/b/" to "/a/b". The root stays "/". */
|
|
3730
|
+
function normalizePath(path) {
|
|
3731
|
+
return (path.length > 1 && path.endsWith("/") ? path.slice(0, -1) : path) || "/";
|
|
3732
|
+
}
|
|
3733
|
+
/** True when `path` is `ancestor` or below it. */
|
|
3734
|
+
function isAtOrBelow(path, ancestor) {
|
|
3735
|
+
if (ancestor === "/") return true;
|
|
3736
|
+
return path === ancestor || path.startsWith(`${ancestor}/`);
|
|
3737
|
+
}
|
|
3738
|
+
/**
|
|
3739
|
+
* Rejections as `"operation <index>: <reason>"` lines, cut to the size that
|
|
3740
|
+
* the envelope reader accepts.
|
|
3741
|
+
*/
|
|
3742
|
+
function summarizeRejections(rejections) {
|
|
3743
|
+
return rejections.slice(0, GENERATIVE_UI_MAX_SUMMARY_REJECTIONS).map(({ index, reason }) => `operation ${index}: ${reason}`.slice(0, GENERATIVE_UI_MAX_REJECTION_LENGTH));
|
|
3744
|
+
}
|
|
3745
|
+
/**
|
|
3746
|
+
* Framework-agnostic store of generated surfaces. One web_core SurfaceModel per
|
|
3747
|
+
* (threadId, surfaceId), shared by every mount. Applies only newly committed
|
|
3748
|
+
* operations, validates each before applying it, and owns app state and the
|
|
3749
|
+
* data model paths that the user wrote, so agent updates cannot overwrite
|
|
3750
|
+
* them. App state never goes into a surface's data model. Selectors read it
|
|
3751
|
+
* with `getState()`.
|
|
3752
|
+
*/
|
|
3753
|
+
var GenerativeUISurfaceManager = class {
|
|
3754
|
+
constructor(ui, options = {}) {
|
|
3755
|
+
this.ui = ui;
|
|
3756
|
+
this.options = options;
|
|
3757
|
+
this.surfaces = /* @__PURE__ */ new Map();
|
|
3758
|
+
this.bookkeeping = /* @__PURE__ */ new Map();
|
|
3759
|
+
this.listeners = /* @__PURE__ */ new Set();
|
|
3760
|
+
this.targets = /* @__PURE__ */ new Map();
|
|
3761
|
+
this.state = {};
|
|
3762
|
+
this.owned = /* @__PURE__ */ new Map();
|
|
3763
|
+
this.deletedKeys = /* @__PURE__ */ new Set();
|
|
3764
|
+
this.linked = /* @__PURE__ */ new Map();
|
|
3765
|
+
this.version = 0;
|
|
3766
|
+
this.subscribe = (listener) => {
|
|
3767
|
+
this.listeners.add(listener);
|
|
3768
|
+
return () => {
|
|
3769
|
+
this.listeners.delete(listener);
|
|
3770
|
+
};
|
|
3771
|
+
};
|
|
3772
|
+
this.getVersion = () => this.version;
|
|
3773
|
+
this.getState = () => this.state;
|
|
3774
|
+
this.webCoreCatalog = new Catalog$1(ui.id, [...ui.components.keys()].map((name) => ({
|
|
3775
|
+
name,
|
|
3776
|
+
schema: z.any()
|
|
3777
|
+
})), []);
|
|
3778
|
+
}
|
|
3779
|
+
notify() {
|
|
3780
|
+
this.version++;
|
|
3781
|
+
for (const listener of [...this.listeners]) listener();
|
|
3782
|
+
}
|
|
3783
|
+
setActiveThread(threadId) {
|
|
3784
|
+
if (threadId === this.activeThreadId) return;
|
|
3785
|
+
this.activeThreadId = threadId;
|
|
3786
|
+
this.notify();
|
|
3787
|
+
}
|
|
3788
|
+
getActiveThread() {
|
|
3789
|
+
return this.activeThreadId;
|
|
3790
|
+
}
|
|
3791
|
+
ingest(threadId, agentId, content) {
|
|
3792
|
+
const key = surfaceKey(threadId, content.surfaceId);
|
|
3793
|
+
const operations = content.operations ?? [];
|
|
3794
|
+
let surface = this.surfaces.get(key);
|
|
3795
|
+
let book = this.bookkeeping.get(key);
|
|
3796
|
+
let changed = false;
|
|
3797
|
+
if (surface && book && !this.extendsApplied(book, operations)) {
|
|
3798
|
+
this.disposeSurface(key);
|
|
3799
|
+
surface = void 0;
|
|
3800
|
+
book = void 0;
|
|
3801
|
+
}
|
|
3802
|
+
if (!surface || !book) {
|
|
3803
|
+
surface = this.createSurface(key, threadId, agentId, content);
|
|
3804
|
+
this.restoreOwnedValues(surface);
|
|
3805
|
+
book = {
|
|
3806
|
+
appliedCount: 0,
|
|
3807
|
+
lastFingerprint: void 0
|
|
3808
|
+
};
|
|
3809
|
+
this.surfaces.set(key, surface);
|
|
3810
|
+
this.bookkeeping.set(key, book);
|
|
3811
|
+
changed = true;
|
|
3812
|
+
}
|
|
3813
|
+
const serverRejected = content.rejected ?? [];
|
|
3814
|
+
if (surface.clientRejected.length > 0 && (surface.status !== "streaming" && content.status === "streaming" || serverRejected.length < surface.serverRejected.length)) {
|
|
3815
|
+
surface.clientRejected = [];
|
|
3816
|
+
changed = true;
|
|
3817
|
+
}
|
|
3818
|
+
if (operations.length > 0) {
|
|
3819
|
+
const lastFingerprint = JSON.stringify(operations[operations.length - 1]);
|
|
3820
|
+
const isReplay = operations.some((op) => getOperationKind(op) === "deleteSurface");
|
|
3821
|
+
for (let index = book.appliedCount; index < operations.length; index++) {
|
|
3822
|
+
this.applyOperation(surface, operations[index], {
|
|
3823
|
+
index,
|
|
3824
|
+
isReplay
|
|
3825
|
+
});
|
|
3826
|
+
changed = true;
|
|
3827
|
+
}
|
|
3828
|
+
book.appliedCount = operations.length;
|
|
3829
|
+
surface.operations = operations;
|
|
3830
|
+
book.lastFingerprint = lastFingerprint;
|
|
3831
|
+
}
|
|
3832
|
+
if (surface.status !== content.status || surface.target !== content.target || surface.serverRejected.length !== serverRejected.length) {
|
|
3833
|
+
surface.status = content.status;
|
|
3834
|
+
surface.target = content.target;
|
|
3835
|
+
surface.serverRejected = serverRejected;
|
|
3836
|
+
changed = true;
|
|
3837
|
+
}
|
|
3838
|
+
if (changed) this.notify();
|
|
3839
|
+
}
|
|
3840
|
+
/** The surface of a `key` (see `surfaceKey`), unless it is deleted. */
|
|
3841
|
+
getSurfaceByKey(key) {
|
|
3842
|
+
const surface = this.surfaces.get(key);
|
|
3843
|
+
return surface && !surface.deleted ? surface : void 0;
|
|
3844
|
+
}
|
|
3845
|
+
getSurface(threadId, surfaceId) {
|
|
3846
|
+
const surface = this.surfaces.get(surfaceKey(threadId, surfaceId));
|
|
3847
|
+
return surface && !surface.deleted ? surface : void 0;
|
|
3848
|
+
}
|
|
3849
|
+
getSurfaceForTarget(target, threadId = this.activeThreadId) {
|
|
3850
|
+
if (!threadId) return void 0;
|
|
3851
|
+
let latest;
|
|
3852
|
+
for (const surface of this.surfaces.values()) {
|
|
3853
|
+
if (surface.threadId !== threadId || surface.target !== target || surface.deleted) continue;
|
|
3854
|
+
if (!latest || surface.createdAt > latest.createdAt) latest = surface;
|
|
3855
|
+
}
|
|
3856
|
+
return latest;
|
|
3857
|
+
}
|
|
3858
|
+
/**
|
|
3859
|
+
* A surface whose first createSurface was rejected, so the chat can show
|
|
3860
|
+
* the error where the surface would be. `undefined` for any other surface.
|
|
3861
|
+
*/
|
|
3862
|
+
getFailedSurface(threadId, surfaceId) {
|
|
3863
|
+
const surface = this.surfaces.get(surfaceKey(threadId, surfaceId));
|
|
3864
|
+
return surface?.failed ? surface : void 0;
|
|
3865
|
+
}
|
|
3866
|
+
/**
|
|
3867
|
+
* The surfaces of a thread, for the model. A surface with user-owned
|
|
3868
|
+
* values lists them in `dataModel`, so the model can read what the user
|
|
3869
|
+
* entered. A surface with dropped operations lists them in `rejected`, so
|
|
3870
|
+
* the model can fix them on the next run. A deleted surface, or one that
|
|
3871
|
+
* was never created, has a `status`, so the model knows that the id is
|
|
3872
|
+
* not a live surface.
|
|
3873
|
+
*/
|
|
3874
|
+
describeSurfaces(threadId) {
|
|
3875
|
+
const described = {};
|
|
3876
|
+
for (const surface of this.surfaces.values()) {
|
|
3877
|
+
if (surface.threadId !== threadId) continue;
|
|
3878
|
+
const owned = this.owned.get(surface.key);
|
|
3879
|
+
const rejections = [...surface.serverRejected, ...surface.clientRejected];
|
|
3880
|
+
const status = this.deletedKeys.has(surface.key) ? "deleted" : surface.failed ? "failed" : void 0;
|
|
3881
|
+
described[surface.surfaceId] = {
|
|
3882
|
+
target: surface.target,
|
|
3883
|
+
...owned && owned.size > 0 ? { dataModel: Object.fromEntries(owned) } : {},
|
|
3884
|
+
...rejections.length > 0 && status !== "deleted" ? { rejected: summarizeRejections(rejections) } : {},
|
|
3885
|
+
...status ? { status } : {}
|
|
3886
|
+
};
|
|
3887
|
+
}
|
|
3888
|
+
return described;
|
|
3889
|
+
}
|
|
3890
|
+
/** Every surface that is not deleted, oldest first, for the inspector. */
|
|
3891
|
+
debugSurfaces() {
|
|
3892
|
+
return [...this.surfaces.values()].filter((surface) => !surface.deleted).sort((a, b) => a.createdAt - b.createdAt).map((surface) => ({
|
|
3893
|
+
surfaceId: surface.surfaceId,
|
|
3894
|
+
threadId: surface.threadId,
|
|
3895
|
+
agentId: surface.agentId,
|
|
3896
|
+
target: surface.target,
|
|
3897
|
+
status: surface.status,
|
|
3898
|
+
operations: surface.operations,
|
|
3899
|
+
dataModel: surface.model.dataModel.get("/"),
|
|
3900
|
+
userValues: Object.fromEntries(this.owned.get(surface.key) ?? []),
|
|
3901
|
+
rejected: [...surface.serverRejected.map((r) => ({
|
|
3902
|
+
...r,
|
|
3903
|
+
source: "runtime"
|
|
3904
|
+
})), ...surface.clientRejected.map((r) => ({
|
|
3905
|
+
...r,
|
|
3906
|
+
source: "browser"
|
|
3907
|
+
}))]
|
|
3908
|
+
}));
|
|
3909
|
+
}
|
|
3910
|
+
/**
|
|
3911
|
+
* Marks a target as mounted. Returns the function that unmounts it. Calling
|
|
3912
|
+
* that function more than once has no effect.
|
|
3913
|
+
*
|
|
3914
|
+
* @param id - The target id.
|
|
3915
|
+
* @param options - The description and the allowed components of this mount.
|
|
3916
|
+
*/
|
|
3917
|
+
registerTarget(id, options = {}) {
|
|
3918
|
+
const registration = { ...options };
|
|
3919
|
+
const registrations = this.targets.get(id) ?? /* @__PURE__ */ new Set();
|
|
3920
|
+
registrations.add(registration);
|
|
3921
|
+
this.targets.set(id, registrations);
|
|
3922
|
+
this.notify();
|
|
3923
|
+
let released = false;
|
|
3924
|
+
return () => {
|
|
3925
|
+
if (released) return;
|
|
3926
|
+
released = true;
|
|
3927
|
+
registrations.delete(registration);
|
|
3928
|
+
if (registrations.size === 0) this.targets.delete(id);
|
|
3929
|
+
this.notify();
|
|
3930
|
+
};
|
|
3931
|
+
}
|
|
3932
|
+
/**
|
|
3933
|
+
* The mounted targets. Each has the description and the component list of
|
|
3934
|
+
* its earliest mount that has one.
|
|
3935
|
+
*/
|
|
3936
|
+
getMountedTargets() {
|
|
3937
|
+
const mounted = [];
|
|
3938
|
+
for (const [id, registrations] of this.targets) {
|
|
3939
|
+
const description = [...registrations].find((registration) => registration.description !== void 0)?.description;
|
|
3940
|
+
const components = this.targetComponents(id);
|
|
3941
|
+
mounted.push({
|
|
3942
|
+
id,
|
|
3943
|
+
...description === void 0 ? {} : { description },
|
|
3944
|
+
...components === void 0 ? {} : { components: [...components] }
|
|
3945
|
+
});
|
|
3946
|
+
}
|
|
3947
|
+
return mounted;
|
|
3948
|
+
}
|
|
3949
|
+
/**
|
|
3950
|
+
* The component list of the earliest mount of `id` that has one.
|
|
3951
|
+
* `undefined` when no mount of `id` limits its components.
|
|
3952
|
+
*/
|
|
3953
|
+
targetComponents(id) {
|
|
3954
|
+
return [...this.targets.get(id) ?? /* @__PURE__ */ new Set()].find((registration) => registration.components !== void 0)?.components;
|
|
3955
|
+
}
|
|
3956
|
+
/** The components that `validateOperation` allows on a surface. */
|
|
3957
|
+
allowedComponentsFor(surface) {
|
|
3958
|
+
const components = this.targetComponents(surface.target);
|
|
3959
|
+
return components === void 0 ? void 0 : {
|
|
3960
|
+
target: surface.target,
|
|
3961
|
+
names: new Set(components)
|
|
3962
|
+
};
|
|
3963
|
+
}
|
|
3964
|
+
/** Sets one state key. Notifies only when the value changed. */
|
|
3965
|
+
setState(key, value) {
|
|
3966
|
+
if (Object.hasOwn(this.state, key) && Object.is(this.state[key], value)) return;
|
|
3967
|
+
this.state = {
|
|
3968
|
+
...this.state,
|
|
3969
|
+
[key]: value
|
|
3970
|
+
};
|
|
3971
|
+
this.notify();
|
|
3972
|
+
}
|
|
3973
|
+
/** Removes one state key. Notifies only when the key was set. */
|
|
3974
|
+
removeState(key) {
|
|
3975
|
+
if (!Object.hasOwn(this.state, key)) return;
|
|
3976
|
+
const { [key]: _removed, ...rest } = this.state;
|
|
3977
|
+
this.state = rest;
|
|
3978
|
+
this.notify();
|
|
3979
|
+
}
|
|
3980
|
+
/**
|
|
3981
|
+
* Makes the surfaces of `surfaceIds` share their data model: a user write
|
|
3982
|
+
* to one of them goes to all of them (see `setOwnedValue`). The markdown
|
|
3983
|
+
* transport links the parts of a chat surface that the prose lift split.
|
|
3984
|
+
* A later call for one of the surfaces replaces its group.
|
|
3985
|
+
*
|
|
3986
|
+
* @param threadId - The thread of the surfaces.
|
|
3987
|
+
* @param surfaceIds - The surface ids of the group. One id clears a link.
|
|
3988
|
+
*/
|
|
3989
|
+
linkSurfaces(threadId, surfaceIds) {
|
|
3990
|
+
const keys = new Set(surfaceIds.map((id) => surfaceKey(threadId, id)));
|
|
3991
|
+
for (const key of keys) if (keys.size > 1) this.linked.set(key, keys);
|
|
3992
|
+
else this.linked.delete(key);
|
|
3993
|
+
}
|
|
3994
|
+
/**
|
|
3995
|
+
* Writes a user value into the data model of a surface, and marks `path`
|
|
3996
|
+
* as user-owned. Then agent writes to that path, or below it, are ignored.
|
|
3997
|
+
* An agent write above it keeps the user value. Ownership ends when the
|
|
3998
|
+
* surface is deleted. Does nothing for an unknown or deleted surface. The
|
|
3999
|
+
* surfaces linked to it (see `linkSurfaces`) get the same write.
|
|
4000
|
+
*
|
|
4001
|
+
* @param key - The `key` of the surface.
|
|
4002
|
+
* @param path - An absolute JSON pointer, for example "/form/email".
|
|
4003
|
+
* @param value - The new value. It is copied.
|
|
4004
|
+
* @throws Error when a path segment is "__proto__", "constructor" or
|
|
4005
|
+
* "prototype", or when the path does not fit the data (for example, a
|
|
4006
|
+
* segment above it holds a string).
|
|
4007
|
+
*/
|
|
4008
|
+
setOwnedValue(key, path, value) {
|
|
4009
|
+
const normalized = normalizePath(path);
|
|
4010
|
+
const forbidden = normalized.split("/").find((segment) => FORBIDDEN_SEGMENTS.has(segment));
|
|
4011
|
+
if (forbidden !== void 0) throw new Error(`[generativeUI] path segment "${forbidden}" is not allowed in "${path}".`);
|
|
4012
|
+
for (const target of this.linked.get(key) ?? [key]) this.writeOwnedValue(target, normalized, value);
|
|
4013
|
+
}
|
|
4014
|
+
writeOwnedValue(key, path, value) {
|
|
4015
|
+
const surface = this.surfaces.get(key);
|
|
4016
|
+
if (!surface || surface.deleted) return;
|
|
4017
|
+
surface.model.dataModel.set(path, structuredClone(value));
|
|
4018
|
+
const owned = this.owned.get(key) ?? /* @__PURE__ */ new Map();
|
|
4019
|
+
owned.set(path, structuredClone(value));
|
|
4020
|
+
this.owned.set(key, owned);
|
|
4021
|
+
}
|
|
4022
|
+
/**
|
|
4023
|
+
* Writes the user-owned values into the new, empty data model of a rebuilt
|
|
4024
|
+
* surface. The agent operations are applied after it.
|
|
4025
|
+
*/
|
|
4026
|
+
restoreOwnedValues(surface) {
|
|
4027
|
+
const owned = this.owned.get(surface.key) ?? /* @__PURE__ */ new Map();
|
|
4028
|
+
for (const [path, value] of owned) surface.model.dataModel.set(path, structuredClone(value));
|
|
4029
|
+
}
|
|
4030
|
+
/**
|
|
4031
|
+
* The value that an agent write puts at `path`, with the user-owned values
|
|
4032
|
+
* below `path` written back into it. `undefined` when `path` is user-owned
|
|
4033
|
+
* or below a user-owned path, so the agent cannot write it. Throws when a
|
|
4034
|
+
* user value does not fit the new value.
|
|
4035
|
+
*/
|
|
4036
|
+
mergeOwnedValues(key, path, value) {
|
|
4037
|
+
const merged = { value: structuredClone(value) };
|
|
4038
|
+
const owned = this.owned.get(key);
|
|
4039
|
+
if (!owned) return merged;
|
|
4040
|
+
const ownedPaths = [...owned.keys()];
|
|
4041
|
+
if (ownedPaths.some((ownedPath) => isAtOrBelow(path, ownedPath))) return void 0;
|
|
4042
|
+
const below = ownedPaths.filter((ownedPath) => isAtOrBelow(ownedPath, path));
|
|
4043
|
+
if (below.length === 0) return merged;
|
|
4044
|
+
const scratch = new DataModel({ value: merged.value });
|
|
4045
|
+
const prefix = path === "/" ? "" : path;
|
|
4046
|
+
for (const ownedPath of below) {
|
|
4047
|
+
const relative = ownedPath.slice(prefix.length);
|
|
4048
|
+
scratch.set(`/value${relative}`, structuredClone(owned.get(ownedPath)));
|
|
4049
|
+
}
|
|
4050
|
+
return { value: scratch.get("/value") };
|
|
4051
|
+
}
|
|
4052
|
+
extendsApplied(book, operations) {
|
|
4053
|
+
if (operations.length < book.appliedCount) return false;
|
|
4054
|
+
if (book.appliedCount === 0) return true;
|
|
4055
|
+
return JSON.stringify(operations[book.appliedCount - 1]) === book.lastFingerprint;
|
|
4056
|
+
}
|
|
4057
|
+
createSurface(key, threadId, agentId, content) {
|
|
4058
|
+
return {
|
|
4059
|
+
key,
|
|
4060
|
+
threadId,
|
|
4061
|
+
surfaceId: content.surfaceId,
|
|
4062
|
+
agentId,
|
|
4063
|
+
model: new SurfaceModel(content.surfaceId, this.webCoreCatalog),
|
|
4064
|
+
createdAt: ++creationCounter,
|
|
4065
|
+
target: content.target,
|
|
4066
|
+
status: content.status,
|
|
4067
|
+
deleted: false,
|
|
4068
|
+
failed: false,
|
|
4069
|
+
serverRejected: content.rejected ?? [],
|
|
4070
|
+
clientRejected: [],
|
|
4071
|
+
operations: []
|
|
4072
|
+
};
|
|
4073
|
+
}
|
|
4074
|
+
disposeSurface(key) {
|
|
4075
|
+
this.surfaces.get(key)?.model.dispose();
|
|
4076
|
+
this.surfaces.delete(key);
|
|
4077
|
+
this.bookkeeping.delete(key);
|
|
4078
|
+
}
|
|
4079
|
+
/**
|
|
4080
|
+
* Marks a surface deleted and frees its components and data. The record
|
|
4081
|
+
* stays, so the model is still told about the id and the bookkeeping does
|
|
4082
|
+
* not rebuild the surface for content that was already applied.
|
|
4083
|
+
*/
|
|
4084
|
+
closeSurface(surface) {
|
|
4085
|
+
surface.deleted = true;
|
|
4086
|
+
surface.model.dispose();
|
|
4087
|
+
surface.model = new SurfaceModel(surface.surfaceId, this.webCoreCatalog);
|
|
4088
|
+
this.owned.delete(surface.key);
|
|
4089
|
+
this.linked.delete(surface.key);
|
|
4090
|
+
}
|
|
4091
|
+
/** The surfaces of a thread that a part of `surfaceId` reads, for tests. */
|
|
4092
|
+
getLinkedSurfaceIds(threadId, surfaceId) {
|
|
4093
|
+
const keys = this.linked.get(surfaceKey(threadId, surfaceId));
|
|
4094
|
+
if (!keys) return [surfaceId];
|
|
4095
|
+
const prefix = `${threadId}::`;
|
|
4096
|
+
return [...keys].map((key) => key.slice(prefix.length));
|
|
4097
|
+
}
|
|
4098
|
+
/**
|
|
4099
|
+
* Drops the node keys that the app sets: bound props and matched events.
|
|
4100
|
+
* The model does not see them, so a model value for one is ignored, not
|
|
4101
|
+
* rejected. This runs before validation, because validation rejects keys
|
|
4102
|
+
* that are not in the manifest. It never changes the given operation.
|
|
4103
|
+
*/
|
|
4104
|
+
dropAppSetKeys(op) {
|
|
4105
|
+
const kind = getOperationKind(op);
|
|
4106
|
+
if (kind !== "updateComponents" && kind !== "createSurface") return op;
|
|
4107
|
+
const record = op;
|
|
4108
|
+
const payload = record[kind];
|
|
4109
|
+
const nodes = payload?.components;
|
|
4110
|
+
if (!Array.isArray(nodes)) return op;
|
|
4111
|
+
return {
|
|
4112
|
+
...record,
|
|
4113
|
+
[kind]: {
|
|
4114
|
+
...payload,
|
|
4115
|
+
components: nodes.map((node) => this.dropAppSetNodeKeys(node))
|
|
4116
|
+
}
|
|
4117
|
+
};
|
|
4118
|
+
}
|
|
4119
|
+
dropAppSetNodeKeys(node) {
|
|
4120
|
+
if (typeof node !== "object" || node === null || !("component" in node)) return node;
|
|
4121
|
+
const { component } = node;
|
|
4122
|
+
if (typeof component !== "string") return node;
|
|
4123
|
+
const definition = this.ui.components.get(component);
|
|
4124
|
+
if (!definition) return node;
|
|
4125
|
+
return Object.fromEntries(Object.entries(node).filter(([key]) => !Object.hasOwn(definition.selectors, key) && !Object.hasOwn(definition.eventFunctions, key)));
|
|
4126
|
+
}
|
|
4127
|
+
/**
|
|
4128
|
+
* The surfaces that `validateOperation` gets for one operation of the
|
|
4129
|
+
* content of `surface`.
|
|
4130
|
+
*
|
|
4131
|
+
* - `knownSurfaces`: the surface, when it exists before the operation. It
|
|
4132
|
+
* does not exist before its first createSurface, or after a delete.
|
|
4133
|
+
* - `createdSurfaces`: the surface, when a createSurface at this position
|
|
4134
|
+
* uses its id again. That is the case after the first operation, and for
|
|
4135
|
+
* a surface that was deleted before, unless the content replays that
|
|
4136
|
+
* delete.
|
|
4137
|
+
*/
|
|
4138
|
+
surfacesFor(surface, kind, position) {
|
|
4139
|
+
const isFirstCreate = kind === "createSurface" && position.index === 0;
|
|
4140
|
+
const exists = !surface.deleted && !isFirstCreate;
|
|
4141
|
+
const isRecreate = this.deletedKeys.has(surface.key) && !position.isReplay;
|
|
4142
|
+
const isUsedAgain = position.index > 0 || isRecreate;
|
|
4143
|
+
return {
|
|
4144
|
+
knownSurfaces: new Set(exists ? [surface.surfaceId] : []),
|
|
4145
|
+
createdSurfaces: new Set(isUsedAgain ? [surface.surfaceId] : [])
|
|
4146
|
+
};
|
|
4147
|
+
}
|
|
4148
|
+
applyOperation(surface, received, position) {
|
|
4149
|
+
const { index } = position;
|
|
4150
|
+
const kind = getOperationKind(received);
|
|
4151
|
+
if (kind === "callRendererFunction") return;
|
|
4152
|
+
const reject = (reason) => {
|
|
4153
|
+
if (kind === "createSurface" && index === 0) {
|
|
4154
|
+
this.closeSurface(surface);
|
|
4155
|
+
surface.failed = true;
|
|
4156
|
+
}
|
|
4157
|
+
surface.clientRejected.push({
|
|
4158
|
+
index,
|
|
4159
|
+
reason
|
|
4160
|
+
});
|
|
4161
|
+
this.options.onOperationRejected?.({
|
|
4162
|
+
surfaceId: surface.surfaceId,
|
|
4163
|
+
index,
|
|
4164
|
+
reason
|
|
4165
|
+
});
|
|
4166
|
+
};
|
|
4167
|
+
const targetId = getOperationSurfaceId(received);
|
|
4168
|
+
if (targetId !== void 0 && targetId !== surface.surfaceId) return reject(`operation is for surface "${targetId}", not "${surface.surfaceId}"`);
|
|
4169
|
+
const op = this.dropAppSetKeys(received);
|
|
4170
|
+
const validation = validateOperation(op, {
|
|
4171
|
+
manifest: {
|
|
4172
|
+
catalogId: this.ui.id,
|
|
4173
|
+
catalogIds: catalogIdsOf(this.ui),
|
|
4174
|
+
components: this.ui.manifestComponents
|
|
4175
|
+
},
|
|
4176
|
+
...this.surfacesFor(surface, kind, position),
|
|
4177
|
+
allowedComponents: this.allowedComponentsFor(surface)
|
|
4178
|
+
});
|
|
4179
|
+
if (!validation.ok) return reject(validation.reason);
|
|
4180
|
+
const typed = op;
|
|
4181
|
+
if ("createSurface" in typed) {
|
|
4182
|
+
const { dataModel, components = [] } = typed.createSurface;
|
|
4183
|
+
const problem = this.nodesProblem(components);
|
|
4184
|
+
if (problem) return reject(problem);
|
|
4185
|
+
if (dataModel) {
|
|
4186
|
+
const failure = this.writeAgentData(surface, "/", dataModel);
|
|
4187
|
+
if (failure) return reject(failure);
|
|
4188
|
+
}
|
|
4189
|
+
for (const node of components) this.upsertNode(surface.model, node);
|
|
4190
|
+
return;
|
|
4191
|
+
}
|
|
4192
|
+
if ("updateComponents" in typed) {
|
|
4193
|
+
const nodes = typed.updateComponents.components;
|
|
4194
|
+
const problem = this.nodesProblem(nodes);
|
|
4195
|
+
if (problem) return reject(problem);
|
|
4196
|
+
for (const node of nodes) this.upsertNode(surface.model, node);
|
|
4197
|
+
return;
|
|
4198
|
+
}
|
|
4199
|
+
if ("updateDataModel" in typed) {
|
|
4200
|
+
const { path = "/", value } = typed.updateDataModel;
|
|
4201
|
+
const written = value === null ? void 0 : value;
|
|
4202
|
+
const failure = this.writeAgentData(surface, normalizePath(path), written);
|
|
4203
|
+
if (failure) return reject(failure);
|
|
4204
|
+
return;
|
|
4205
|
+
}
|
|
4206
|
+
if ("deleteSurface" in typed) {
|
|
4207
|
+
this.closeSurface(surface);
|
|
4208
|
+
this.deletedKeys.add(surface.key);
|
|
4209
|
+
}
|
|
4210
|
+
}
|
|
4211
|
+
/** The first node with props of the wrong type, as a reason. */
|
|
4212
|
+
nodesProblem(nodes) {
|
|
4213
|
+
for (const node of nodes) {
|
|
4214
|
+
const problem = this.checkNodeProps(node);
|
|
4215
|
+
if (problem) return `component "${node.id}": ${problem}`;
|
|
4216
|
+
}
|
|
4217
|
+
}
|
|
4218
|
+
/**
|
|
4219
|
+
* Writes an agent value at `path` and keeps the user-owned values. A write
|
|
4220
|
+
* to a user-owned path is ignored, not rejected. Gives the reason when the
|
|
4221
|
+
* value does not fit the data, else `undefined`.
|
|
4222
|
+
*/
|
|
4223
|
+
writeAgentData(surface, path, value) {
|
|
4224
|
+
try {
|
|
4225
|
+
const merged = this.mergeOwnedValues(surface.key, path, value);
|
|
4226
|
+
if (merged) surface.model.dataModel.set(path, merged.value);
|
|
4227
|
+
return;
|
|
4228
|
+
} catch (error) {
|
|
4229
|
+
return error instanceof Error ? error.message : String(error);
|
|
4230
|
+
}
|
|
4231
|
+
}
|
|
4232
|
+
checkNodeProps(node) {
|
|
4233
|
+
const definition = this.ui.components.get(node.component);
|
|
4234
|
+
if (!definition) return `unknown component "${node.component}"`;
|
|
4235
|
+
const { id: _id, component: _component, ...rest } = node;
|
|
4236
|
+
const dataProps = Object.fromEntries(Object.entries(rest).filter(([key]) => !definition.events?.[key] && !definition.slots?.[key] && !A2UI_COMPONENT_ENVELOPE_KEYS.has(key)));
|
|
4237
|
+
if (!definition.props) return void 0;
|
|
4238
|
+
const unknownNow = new Set(Object.keys(definition.selectors));
|
|
4239
|
+
const literals = {};
|
|
4240
|
+
for (const [key, value] of Object.entries(dataProps)) if (containsDynamicValue(value)) unknownNow.add(key);
|
|
4241
|
+
else literals[key] = value;
|
|
4242
|
+
let result = validateSchemaSync(definition.props, literals);
|
|
4243
|
+
if (!result.success) {
|
|
4244
|
+
const unset = withoutRejectedNulls(literals, result.issues);
|
|
4245
|
+
if (unset) result = validateSchemaSync(definition.props, unset);
|
|
4246
|
+
}
|
|
4247
|
+
if (result.success) return void 0;
|
|
4248
|
+
const issues = result.issues.filter((issue) => {
|
|
4249
|
+
const key = issueKey(issue);
|
|
4250
|
+
return key === void 0 ? isAsyncIssue(issue) : !unknownNow.has(key);
|
|
4251
|
+
});
|
|
4252
|
+
return issues.length > 0 ? formatIssues(issues) : void 0;
|
|
4253
|
+
}
|
|
4254
|
+
upsertNode(model, node) {
|
|
4255
|
+
const { id, component, ...rest } = node;
|
|
4256
|
+
const properties = structuredClone(rest);
|
|
4257
|
+
const existing = model.componentsModel.get(id);
|
|
4258
|
+
if (existing && existing.type === component) {
|
|
4259
|
+
existing.properties = properties;
|
|
4260
|
+
return;
|
|
4261
|
+
}
|
|
4262
|
+
if (existing) model.componentsModel.removeComponent(id);
|
|
4263
|
+
model.componentsModel.addComponent(new ComponentModel(id, component, properties));
|
|
4264
|
+
}
|
|
4265
|
+
};
|
|
4266
|
+
|
|
4267
|
+
//#endregion
|
|
4268
|
+
//#region src/v2/generative-ui/use-generative-ui-root.ts
|
|
4269
|
+
const isDevelopment = () => process.env.NODE_ENV !== "production";
|
|
4270
|
+
/** At most this many function follow-up runs for each user turn. */
|
|
4271
|
+
const MAX_FUNCTION_FOLLOW_UPS = 5;
|
|
4272
|
+
function ingestMessages(manager, agent, messages) {
|
|
4273
|
+
if (!agent.threadId) return;
|
|
4274
|
+
for (const message of messages) if (message.role === "activity" && message.activityType === GENERATIVE_UI_ACTIVITY_TYPE) manager.ingest(agent.threadId, agent.agentId, message.content);
|
|
4275
|
+
}
|
|
4276
|
+
/** What the envelope of a run says, from the provider config. */
|
|
4277
|
+
function envelopeOptionsFor(config) {
|
|
4278
|
+
if (config.transport === "markdown") return {
|
|
4279
|
+
transport: "markdown",
|
|
4280
|
+
includeCatalog: config.includeCatalog !== false,
|
|
4281
|
+
contextSent: config.sendContext !== false
|
|
4282
|
+
};
|
|
4283
|
+
return {
|
|
4284
|
+
transport: "tool",
|
|
4285
|
+
includeCatalog: true,
|
|
4286
|
+
contextSent: false
|
|
4287
|
+
};
|
|
4288
|
+
}
|
|
4289
|
+
/**
|
|
4290
|
+
* The components of a surface as one `updateComponents` operation, so that
|
|
4291
|
+
* the label of the component that sent an event can be found.
|
|
4292
|
+
*/
|
|
4293
|
+
function surfaceComponents(surface) {
|
|
4294
|
+
const components = [...surface.model.componentsModel.entries].map(([id, model]) => ({
|
|
4295
|
+
...model.properties,
|
|
4296
|
+
id,
|
|
4297
|
+
component: model.type
|
|
4298
|
+
}));
|
|
4299
|
+
return [{
|
|
4300
|
+
version: A2UI_VERSION,
|
|
4301
|
+
updateComponents: {
|
|
4302
|
+
surfaceId: surface.surfaceId,
|
|
4303
|
+
components
|
|
4304
|
+
}
|
|
4305
|
+
}];
|
|
4306
|
+
}
|
|
4307
|
+
/** True when `value` names a `functionCallId`. */
|
|
4308
|
+
function hasFunctionCallId(value) {
|
|
4309
|
+
return typeof value === "object" && value !== null && "functionCallId" in value && typeof value.functionCallId === "string" && value.functionCallId !== "";
|
|
4310
|
+
}
|
|
4311
|
+
/** The `functionCallId` that a developer message answers, if any. */
|
|
4312
|
+
function answeredCallId(content) {
|
|
4313
|
+
if (!content.includes("rendererFunctionResponse")) return void 0;
|
|
4314
|
+
try {
|
|
4315
|
+
const parsed = JSON.parse(content);
|
|
4316
|
+
const response = typeof parsed === "object" && parsed !== null && "rendererFunctionResponse" in parsed ? parsed.rendererFunctionResponse : void 0;
|
|
4317
|
+
return hasFunctionCallId(response) ? response.functionCallId : void 0;
|
|
4318
|
+
} catch {
|
|
4319
|
+
return;
|
|
4320
|
+
}
|
|
4321
|
+
}
|
|
4322
|
+
/** The function calls that a developer message in `messages` answers. */
|
|
4323
|
+
function answeredCallIds(messages) {
|
|
4324
|
+
const ids = /* @__PURE__ */ new Set();
|
|
4325
|
+
for (const message of messages) {
|
|
4326
|
+
if (message.role !== "developer") continue;
|
|
4327
|
+
const id = answeredCallId(message.content);
|
|
4328
|
+
if (id !== void 0) ids.add(id);
|
|
4329
|
+
}
|
|
4330
|
+
return ids;
|
|
4331
|
+
}
|
|
4332
|
+
/** The id of the last user message. A user turn starts with it. */
|
|
4333
|
+
function lastUserMessageId(messages) {
|
|
4334
|
+
for (let index = messages.length - 1; index >= 0; index--) {
|
|
4335
|
+
const message = messages[index];
|
|
4336
|
+
if (message?.role === "user") return message.id;
|
|
4337
|
+
}
|
|
4338
|
+
}
|
|
4339
|
+
/** The function calls of the tool transport: its function-call activities. */
|
|
4340
|
+
function activityFunctionCalls(messages) {
|
|
4341
|
+
const requests = [];
|
|
4342
|
+
for (const message of messages) {
|
|
4343
|
+
if (!(message.role === "activity" && message.activityType === GENERATIVE_UI_FUNCTION_CALL_ACTIVITY_TYPE) || !hasFunctionCallId(message.content)) continue;
|
|
4344
|
+
requests.push({
|
|
4345
|
+
functionCallId: message.content.functionCallId,
|
|
4346
|
+
operation: {
|
|
4347
|
+
version: A2UI_VERSION,
|
|
4348
|
+
callRendererFunction: message.content
|
|
4349
|
+
}
|
|
4350
|
+
});
|
|
4351
|
+
}
|
|
4352
|
+
return requests;
|
|
4353
|
+
}
|
|
4354
|
+
/** The function calls of the markdown transport: its fence lines. */
|
|
4355
|
+
function markdownFunctionCalls(calls) {
|
|
4356
|
+
const requests = [];
|
|
4357
|
+
for (const { operation } of calls) {
|
|
4358
|
+
const payload = operation.callRendererFunction;
|
|
4359
|
+
if (!hasFunctionCallId(payload)) continue;
|
|
4360
|
+
requests.push({
|
|
4361
|
+
functionCallId: payload.functionCallId,
|
|
4362
|
+
operation
|
|
4363
|
+
});
|
|
4364
|
+
}
|
|
4365
|
+
return requests;
|
|
3254
4366
|
}
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
4367
|
+
/** The text of a `rendererFunctionResponse` developer message. */
|
|
4368
|
+
function responseContent(response) {
|
|
4369
|
+
return JSON.stringify({
|
|
4370
|
+
version: A2UI_VERSION,
|
|
4371
|
+
rendererFunctionResponse: response
|
|
4372
|
+
});
|
|
4373
|
+
}
|
|
4374
|
+
function errorAnswer(functionCallId, code, message) {
|
|
4375
|
+
return {
|
|
4376
|
+
content: responseContent({
|
|
4377
|
+
functionCallId,
|
|
4378
|
+
error: {
|
|
4379
|
+
code,
|
|
4380
|
+
message
|
|
4381
|
+
}
|
|
4382
|
+
}),
|
|
4383
|
+
followUp: true
|
|
4384
|
+
};
|
|
4385
|
+
}
|
|
4386
|
+
const overCapAnswer = (functionCallId) => ({
|
|
4387
|
+
content: responseContent({
|
|
4388
|
+
functionCallId,
|
|
4389
|
+
error: {
|
|
4390
|
+
code: "follow_up_limit",
|
|
4391
|
+
message: `The function did not run. A user turn can have at most ${MAX_FUNCTION_FOLLOW_UPS} function follow-up runs. Wait for the next user message.`
|
|
4392
|
+
}
|
|
4393
|
+
}),
|
|
4394
|
+
followUp: false
|
|
4395
|
+
});
|
|
3258
4396
|
/**
|
|
3259
|
-
*
|
|
3260
|
-
*
|
|
3261
|
-
*
|
|
3262
|
-
*
|
|
3263
|
-
*
|
|
3264
|
-
*
|
|
3265
|
-
*
|
|
3266
|
-
*
|
|
3267
|
-
*
|
|
3268
|
-
*
|
|
4397
|
+
* Runs the functions that the agent calls with `callRendererFunction`, for
|
|
4398
|
+
* both transports, and answers each call.
|
|
4399
|
+
*
|
|
4400
|
+
* - Each `functionCallId` runs once for each thread. A replay, a sync of
|
|
4401
|
+
* the same messages again, or a call that already has an answer message
|
|
4402
|
+
* does not run it again.
|
|
4403
|
+
* - The answer is a hidden developer message with a `rendererFunctionResponse`.
|
|
4404
|
+
* The answers go to the agent only when it is not running. Then one
|
|
4405
|
+
* follow-up run starts for all of them.
|
|
4406
|
+
* - A user turn has at most {@link MAX_FUNCTION_FOLLOW_UPS} follow-up runs.
|
|
4407
|
+
* A call after that does not run. It gets a `follow_up_limit` error and
|
|
4408
|
+
* starts no follow-up run.
|
|
3269
4409
|
*/
|
|
3270
|
-
function
|
|
3271
|
-
const { copilotkit } =
|
|
3272
|
-
const
|
|
3273
|
-
const
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
}));
|
|
3285
|
-
if (schemaValue) {
|
|
3286
|
-
ids.push(copilotkit.addContext({
|
|
3287
|
-
description: A2UI_SCHEMA_CONTEXT_DESCRIPTION,
|
|
3288
|
-
value: schemaValue,
|
|
3289
|
-
...scope
|
|
3290
|
-
}));
|
|
3291
|
-
ids.push(copilotkit.addContext({
|
|
3292
|
-
description: "A2UI generation guidelines — protocol rules, tool arguments, path rules, data model format, and form/two-way-binding instructions.",
|
|
3293
|
-
value: A2UI_DEFAULT_GENERATION_GUIDELINES,
|
|
3294
|
-
...scope
|
|
3295
|
-
}));
|
|
3296
|
-
ids.push(copilotkit.addContext({
|
|
3297
|
-
description: "A2UI design guidelines — visual design rules, component hierarchy tips, and action handler patterns.",
|
|
3298
|
-
value: A2UI_DEFAULT_DESIGN_GUIDELINES,
|
|
3299
|
-
...scope
|
|
3300
|
-
}));
|
|
4410
|
+
function createFunctionCallRunner(options) {
|
|
4411
|
+
const { copilotkit, dispatcher, manifest } = options;
|
|
4412
|
+
const threads = /* @__PURE__ */ new Map();
|
|
4413
|
+
const threadState = (threadId) => {
|
|
4414
|
+
let state = threads.get(threadId);
|
|
4415
|
+
if (!state) {
|
|
4416
|
+
state = {
|
|
4417
|
+
done: /* @__PURE__ */ new Set(),
|
|
4418
|
+
pending: [],
|
|
4419
|
+
turn: void 0,
|
|
4420
|
+
followUps: 0,
|
|
4421
|
+
flushing: false
|
|
4422
|
+
};
|
|
4423
|
+
threads.set(threadId, state);
|
|
3301
4424
|
}
|
|
3302
|
-
return
|
|
3303
|
-
|
|
4425
|
+
return state;
|
|
4426
|
+
};
|
|
4427
|
+
const answer = async (request) => {
|
|
4428
|
+
const { functionCallId } = request;
|
|
4429
|
+
const validation = validateOperation(request.operation, {
|
|
4430
|
+
manifest,
|
|
4431
|
+
knownSurfaces: /* @__PURE__ */ new Set()
|
|
4432
|
+
});
|
|
4433
|
+
if (!validation.ok) return errorAnswer(functionCallId, "invalid_arguments", validation.reason);
|
|
4434
|
+
const operation = request.operation;
|
|
4435
|
+
if (!("callRendererFunction" in operation)) return errorAnswer(functionCallId, "invalid_arguments", "the operation is not a callRendererFunction");
|
|
4436
|
+
const { callFunction } = operation.callRendererFunction;
|
|
4437
|
+
const name = callFunction["@call"];
|
|
4438
|
+
const result = await dispatcher.invoke(name, callFunction.args ?? {}, { functionCallId });
|
|
4439
|
+
if (!result.ok) return errorAnswer(functionCallId, result.error.code, result.error.message);
|
|
4440
|
+
try {
|
|
4441
|
+
return {
|
|
4442
|
+
content: responseContent({
|
|
4443
|
+
functionCallId,
|
|
4444
|
+
value: result.result ?? null
|
|
4445
|
+
}),
|
|
4446
|
+
followUp: true
|
|
4447
|
+
};
|
|
4448
|
+
} catch (cause) {
|
|
4449
|
+
return errorAnswer(functionCallId, "handler_failed", `The result of "${name}" is not JSON: ${cause instanceof Error ? cause.message : String(cause)}`);
|
|
4450
|
+
}
|
|
4451
|
+
};
|
|
4452
|
+
/**
|
|
4453
|
+
* Adds the pending answers of a thread to the agent, then starts one
|
|
4454
|
+
* follow-up run. It waits while the agent runs: the next read of the
|
|
4455
|
+
* thread, at the end of the run, flushes again.
|
|
4456
|
+
*/
|
|
4457
|
+
const flush = async (agent, threadId, state) => {
|
|
4458
|
+
if (state.flushing) return;
|
|
4459
|
+
state.flushing = true;
|
|
4460
|
+
try {
|
|
4461
|
+
while (state.pending.length > 0) {
|
|
4462
|
+
const batch = [...state.pending];
|
|
4463
|
+
const answers = await Promise.all(batch);
|
|
4464
|
+
await copilotkit.waitForPendingFrameworkUpdates();
|
|
4465
|
+
if (agent.isRunning || agent.threadId !== threadId) return;
|
|
4466
|
+
if (state.pending.length > batch.length) continue;
|
|
4467
|
+
state.pending = [];
|
|
4468
|
+
for (const { content } of answers) agent.addMessage({
|
|
4469
|
+
id: randomUUID$1(),
|
|
4470
|
+
role: "developer",
|
|
4471
|
+
content
|
|
4472
|
+
});
|
|
4473
|
+
if (!answers.some((item) => item.followUp)) continue;
|
|
4474
|
+
state.followUps++;
|
|
4475
|
+
await copilotkit.runAgent({ agent });
|
|
4476
|
+
}
|
|
4477
|
+
} catch (error) {
|
|
4478
|
+
if (isDevelopment()) console.warn("[generativeUI] function follow-up run failed:", error);
|
|
4479
|
+
} finally {
|
|
4480
|
+
state.flushing = false;
|
|
4481
|
+
}
|
|
4482
|
+
};
|
|
4483
|
+
return { run(agent, requests, messages, running) {
|
|
4484
|
+
const { threadId } = agent;
|
|
4485
|
+
if (!threadId) return;
|
|
4486
|
+
const state = threadState(threadId);
|
|
4487
|
+
const turn = lastUserMessageId(messages);
|
|
4488
|
+
if (turn !== state.turn) {
|
|
4489
|
+
state.turn = turn;
|
|
4490
|
+
state.followUps = 0;
|
|
4491
|
+
}
|
|
4492
|
+
const isNew = (request) => !state.done.has(request.functionCallId);
|
|
4493
|
+
const fresh = requests.filter(isNew);
|
|
4494
|
+
const answered = fresh.length > 0 ? answeredCallIds(messages) : /* @__PURE__ */ new Set();
|
|
4495
|
+
for (const request of fresh) {
|
|
4496
|
+
const { functionCallId } = request;
|
|
4497
|
+
if (state.done.has(functionCallId)) continue;
|
|
4498
|
+
state.done.add(functionCallId);
|
|
4499
|
+
if (answered.has(functionCallId)) continue;
|
|
4500
|
+
const isOverCap = state.followUps >= MAX_FUNCTION_FOLLOW_UPS;
|
|
4501
|
+
state.pending.push(isOverCap ? Promise.resolve(overCapAnswer(functionCallId)) : answer(request));
|
|
4502
|
+
}
|
|
4503
|
+
if (!running) flush(agent, threadId, state);
|
|
4504
|
+
} };
|
|
4505
|
+
}
|
|
4506
|
+
/** Provider-side wiring: manager, dispatcher, agent subscriptions, envelope. */
|
|
4507
|
+
function useGenerativeUIRoot(copilotkit, config) {
|
|
4508
|
+
const configRef = useRef(config);
|
|
4509
|
+
configRef.current = config;
|
|
4510
|
+
const ui = config?.ui;
|
|
4511
|
+
const transport = config?.transport ?? "tool";
|
|
4512
|
+
const theme = useShallowStableRef(config?.theme);
|
|
4513
|
+
const core = useMemo(() => {
|
|
4514
|
+
if (!ui) return null;
|
|
4515
|
+
const reportError = (info) => {
|
|
4516
|
+
try {
|
|
4517
|
+
configRef.current?.errorBoundary?.onError?.(info);
|
|
4518
|
+
} catch (hostError) {
|
|
4519
|
+
if (isDevelopment()) console.error("[generativeUI] errorBoundary.onError threw:", hostError);
|
|
4520
|
+
}
|
|
4521
|
+
if (isDevelopment()) console.warn(`[generativeUI] ${info.kind} error in ${info.surfaceId}${info.componentId ? `/${info.componentId}` : ""}: ${info.error?.message}`);
|
|
4522
|
+
};
|
|
4523
|
+
const manager = new GenerativeUISurfaceManager(ui, { onOperationRejected: ({ surfaceId, index, reason }) => reportError({
|
|
4524
|
+
kind: "operation",
|
|
4525
|
+
surfaceId,
|
|
4526
|
+
error: /* @__PURE__ */ new Error(`operation ${index} rejected: ${reason}`)
|
|
4527
|
+
}) });
|
|
4528
|
+
const dispatcher = createGenerativeUIDispatcher({
|
|
4529
|
+
getDeclared: () => ui.functions,
|
|
4530
|
+
onError: ({ name, origin, error }) => {
|
|
4531
|
+
if ("functionCallId" in origin) {
|
|
4532
|
+
if (isDevelopment()) console.warn(`[generativeUI] function call ${origin.functionCallId} to "${name}" failed: ${error.message}`);
|
|
4533
|
+
return;
|
|
4534
|
+
}
|
|
4535
|
+
reportError({
|
|
4536
|
+
kind: "function",
|
|
4537
|
+
...origin,
|
|
4538
|
+
error
|
|
4539
|
+
});
|
|
4540
|
+
}
|
|
4541
|
+
});
|
|
4542
|
+
const functionCalls = createFunctionCallRunner({
|
|
4543
|
+
copilotkit,
|
|
4544
|
+
dispatcher,
|
|
4545
|
+
manifest: {
|
|
4546
|
+
catalogId: ui.id,
|
|
4547
|
+
catalogIds: catalogIdsOf(ui),
|
|
4548
|
+
components: ui.manifestComponents
|
|
4549
|
+
}
|
|
4550
|
+
});
|
|
4551
|
+
const forwardingAgents = /* @__PURE__ */ new Set();
|
|
4552
|
+
/**
|
|
4553
|
+
* The action of a user event, as an envelope entry scoped to the agent
|
|
4554
|
+
* the user acted on, for the run that the event starts: the structured
|
|
4555
|
+
* form of the user message. It is set before the run starts and dropped
|
|
4556
|
+
* when the run is over, so a suggestion request or a follow-up run
|
|
4557
|
+
* (both read the properties with no run start) does not carry the same
|
|
4558
|
+
* action again, and another agent never gets a click meant for this one.
|
|
4559
|
+
* The entry comes after the shared envelope, so it wins for its agent;
|
|
4560
|
+
* `refreshActions` keeps it last when the shared envelope is set again.
|
|
4561
|
+
*/
|
|
4562
|
+
const actions = /* @__PURE__ */ new Map();
|
|
4563
|
+
const dropAction = (agent) => {
|
|
4564
|
+
const entry = actions.get(agent);
|
|
4565
|
+
if (!entry) return;
|
|
4566
|
+
entry.subscription.unsubscribe();
|
|
4567
|
+
copilotkit.removeScopedProperties(entry.id);
|
|
4568
|
+
actions.delete(agent);
|
|
4569
|
+
};
|
|
4570
|
+
const setAction = (agent, action) => {
|
|
4571
|
+
const previous = actions.get(agent);
|
|
4572
|
+
previous?.subscription.unsubscribe();
|
|
4573
|
+
if (previous) copilotkit.removeScopedProperties(previous.id);
|
|
4574
|
+
actions.delete(agent);
|
|
4575
|
+
const latest = configRef.current;
|
|
4576
|
+
if (!latest) return;
|
|
4577
|
+
const envelope = buildGenerativeUIEnvelope({
|
|
4578
|
+
ui,
|
|
4579
|
+
manager,
|
|
4580
|
+
dispatcher
|
|
4581
|
+
}, agent.threadId, {
|
|
4582
|
+
...envelopeOptionsFor(latest),
|
|
4583
|
+
action
|
|
4584
|
+
});
|
|
4585
|
+
const id = copilotkit.addScopedProperties({
|
|
4586
|
+
properties: { [COPILOTKIT_FORWARDED_PROPS_KEY]: { ui: envelope } },
|
|
4587
|
+
agentIds: agent.agentId === void 0 ? latest.agentIds : [agent.agentId]
|
|
4588
|
+
});
|
|
4589
|
+
const subscription = agent.subscribe({
|
|
4590
|
+
onRunFinalized: () => dropAction(agent),
|
|
4591
|
+
onRunFailed: () => dropAction(agent)
|
|
4592
|
+
});
|
|
4593
|
+
actions.set(agent, {
|
|
4594
|
+
id,
|
|
4595
|
+
action,
|
|
4596
|
+
subscription
|
|
4597
|
+
});
|
|
4598
|
+
};
|
|
4599
|
+
const refreshActions = () => {
|
|
4600
|
+
for (const [agent, { action }] of [...actions]) setAction(agent, action);
|
|
4601
|
+
};
|
|
4602
|
+
const dropAllActions = () => {
|
|
4603
|
+
for (const agent of [...actions.keys()]) dropAction(agent);
|
|
4604
|
+
};
|
|
4605
|
+
const forwardEvent = async (event, agentId) => {
|
|
4606
|
+
const fail = (message) => {
|
|
4607
|
+
const error = new GenerativeUIError("event_forward_failed", message);
|
|
4608
|
+
reportError({
|
|
4609
|
+
kind: "event",
|
|
4610
|
+
surfaceId: event.surfaceId,
|
|
4611
|
+
componentId: event.componentId,
|
|
4612
|
+
error
|
|
4613
|
+
});
|
|
4614
|
+
return {
|
|
4615
|
+
ok: false,
|
|
4616
|
+
error
|
|
4617
|
+
};
|
|
4618
|
+
};
|
|
4619
|
+
const agent = copilotkit.getAgent(agentId ?? DEFAULT_AGENT_ID);
|
|
4620
|
+
if (!agent) return fail(`No agent "${agentId}" to receive "${event.name}"`);
|
|
4621
|
+
if (agent.isRunning || forwardingAgents.has(agent)) return {
|
|
4622
|
+
ok: false,
|
|
4623
|
+
error: new GenerativeUIError("agent_busy", `"${event.name}" was not sent: the agent is running`)
|
|
4624
|
+
};
|
|
4625
|
+
forwardingAgents.add(agent);
|
|
4626
|
+
try {
|
|
4627
|
+
const surface = agent.threadId ? manager.getSurface(agent.threadId, event.surfaceId) : void 0;
|
|
4628
|
+
const resolveLabel = surface ? createComponentLabelResolver(surfaceComponents(surface)) : void 0;
|
|
4629
|
+
agent.addMessage({
|
|
4630
|
+
id: randomUUID$1(),
|
|
4631
|
+
role: "user",
|
|
4632
|
+
content: buildActionMessageText(event, resolveLabel)
|
|
4633
|
+
});
|
|
4634
|
+
setAction(agent, toA2UIActionMessage(event));
|
|
4635
|
+
await copilotkit.runAgent({ agent });
|
|
4636
|
+
return {
|
|
4637
|
+
ok: true,
|
|
4638
|
+
result: void 0
|
|
4639
|
+
};
|
|
4640
|
+
} catch (cause) {
|
|
4641
|
+
return fail(`Forwarding "${event.name}" failed: ${cause instanceof Error ? cause.message : String(cause)}`);
|
|
4642
|
+
} finally {
|
|
4643
|
+
forwardingAgents.delete(agent);
|
|
4644
|
+
dropAction(agent);
|
|
4645
|
+
}
|
|
4646
|
+
};
|
|
4647
|
+
return {
|
|
4648
|
+
manager,
|
|
4649
|
+
dispatcher,
|
|
4650
|
+
ui,
|
|
4651
|
+
forwardEvent,
|
|
4652
|
+
reportError,
|
|
4653
|
+
functionCalls,
|
|
4654
|
+
refreshActions,
|
|
4655
|
+
dropAllActions
|
|
4656
|
+
};
|
|
4657
|
+
}, [ui, copilotkit]);
|
|
4658
|
+
const runtime = useMemo(() => {
|
|
4659
|
+
if (!core) return null;
|
|
4660
|
+
const { manager, dispatcher, forwardEvent, reportError } = core;
|
|
4661
|
+
return {
|
|
4662
|
+
manager,
|
|
4663
|
+
dispatcher,
|
|
4664
|
+
ui: core.ui,
|
|
4665
|
+
forwardEvent,
|
|
4666
|
+
reportError,
|
|
4667
|
+
transport,
|
|
4668
|
+
theme,
|
|
4669
|
+
get config() {
|
|
4670
|
+
return configRef.current ?? { ui: core.ui };
|
|
4671
|
+
},
|
|
4672
|
+
get errorFallback() {
|
|
4673
|
+
return configRef.current?.errorBoundary?.fallback;
|
|
4674
|
+
}
|
|
3304
4675
|
};
|
|
3305
4676
|
}, [
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
a2uiAgentsKey
|
|
4677
|
+
core,
|
|
4678
|
+
transport,
|
|
4679
|
+
theme
|
|
3310
4680
|
]);
|
|
3311
|
-
|
|
4681
|
+
useEffect(() => {
|
|
4682
|
+
if (!core) return;
|
|
4683
|
+
const watched = /* @__PURE__ */ new WeakSet();
|
|
4684
|
+
const agentSubscriptions = [];
|
|
4685
|
+
let envelopeId;
|
|
4686
|
+
const debug = createGenerativeUIDebugSource(core, () => {
|
|
4687
|
+
const latest = configRef.current ?? { ui: core.ui };
|
|
4688
|
+
return {
|
|
4689
|
+
options: envelopeOptionsFor(latest),
|
|
4690
|
+
agentIds: latest.agentIds
|
|
4691
|
+
};
|
|
4692
|
+
});
|
|
4693
|
+
copilotkit.ɵsetGenerativeUIDebugSource(debug.source);
|
|
4694
|
+
const removeEnvelope = () => {
|
|
4695
|
+
if (envelopeId === void 0) return;
|
|
4696
|
+
copilotkit.removeScopedProperties(envelopeId);
|
|
4697
|
+
envelopeId = void 0;
|
|
4698
|
+
};
|
|
4699
|
+
/**
|
|
4700
|
+
* Sets the shared envelope of the run. The action entries of the agents
|
|
4701
|
+
* with a user event under way (see `forwardEvent`) are set again after
|
|
4702
|
+
* it, so they stay the last entries and win for their agents.
|
|
4703
|
+
*/
|
|
4704
|
+
const setEnvelope = (agent, latest) => {
|
|
4705
|
+
removeEnvelope();
|
|
4706
|
+
const run = describeGenerativeUIRun(core, agent.threadId, envelopeOptionsFor(latest));
|
|
4707
|
+
envelopeId = copilotkit.addScopedProperties({
|
|
4708
|
+
properties: { [COPILOTKIT_FORWARDED_PROPS_KEY]: { ui: run.envelope } },
|
|
4709
|
+
agentIds: latest.agentIds
|
|
4710
|
+
});
|
|
4711
|
+
core.refreshActions();
|
|
4712
|
+
if (!latest.agentIds || latest.agentIds.includes(agent.agentId ?? "")) debug.recordRun({
|
|
4713
|
+
...run,
|
|
4714
|
+
agentId: agent.agentId,
|
|
4715
|
+
threadId: agent.threadId,
|
|
4716
|
+
startedAt: Date.now()
|
|
4717
|
+
});
|
|
4718
|
+
};
|
|
4719
|
+
/**
|
|
4720
|
+
* The tool transport reads the surface activity messages. The markdown
|
|
4721
|
+
* transport reads the ```a2ui fences of the assistant messages, and
|
|
4722
|
+
* builds the surfaces of the thread from them again on each change.
|
|
4723
|
+
* Both give their function calls to the one runner.
|
|
4724
|
+
*/
|
|
4725
|
+
const readMessages = (agent, messages, running) => {
|
|
4726
|
+
const requests = activityFunctionCalls(messages);
|
|
4727
|
+
const { threadId } = agent;
|
|
4728
|
+
if (configRef.current?.transport !== "markdown") ingestMessages(core.manager, agent, messages);
|
|
4729
|
+
else if (threadId) {
|
|
4730
|
+
core.manager.setActiveThread(threadId);
|
|
4731
|
+
const calls = getMarkdownSurfaceSource(core).sync(threadId, agent.agentId, messages, { running });
|
|
4732
|
+
requests.push(...markdownFunctionCalls(calls));
|
|
4733
|
+
}
|
|
4734
|
+
core.functionCalls.run(agent, requests, messages, running);
|
|
4735
|
+
};
|
|
4736
|
+
const subscription = copilotkit.subscribe({ onAgentRunStarted: ({ agent }) => {
|
|
4737
|
+
core.manager.setActiveThread(agent.threadId);
|
|
4738
|
+
const latest = configRef.current;
|
|
4739
|
+
if (latest) setEnvelope(agent, latest);
|
|
4740
|
+
if (!watched.has(agent)) {
|
|
4741
|
+
watched.add(agent);
|
|
4742
|
+
agentSubscriptions.push(agent.subscribe({
|
|
4743
|
+
onMessagesChanged: ({ messages }) => readMessages(agent, messages, agent.isRunning),
|
|
4744
|
+
onRunFinalized: () => readMessages(agent, agent.messages, false),
|
|
4745
|
+
onRunFailed: () => readMessages(agent, agent.messages, false)
|
|
4746
|
+
}));
|
|
4747
|
+
}
|
|
4748
|
+
readMessages(agent, agent.messages, true);
|
|
4749
|
+
} });
|
|
4750
|
+
return () => {
|
|
4751
|
+
subscription.unsubscribe();
|
|
4752
|
+
for (const s of agentSubscriptions) s.unsubscribe();
|
|
4753
|
+
core.dropAllActions();
|
|
4754
|
+
removeEnvelope();
|
|
4755
|
+
if (copilotkit.ɵgenerativeUIDebugSource === debug.source) copilotkit.ɵsetGenerativeUIDebugSource(void 0);
|
|
4756
|
+
};
|
|
4757
|
+
}, [core, copilotkit]);
|
|
4758
|
+
useGenerativeUIMarkdownContext(copilotkit, core, {
|
|
4759
|
+
enabled: config?.transport === "markdown" && config.sendContext !== false,
|
|
4760
|
+
agentIds: config?.agentIds
|
|
4761
|
+
});
|
|
4762
|
+
return runtime;
|
|
3312
4763
|
}
|
|
3313
4764
|
|
|
3314
4765
|
//#endregion
|
|
@@ -3453,7 +4904,7 @@ function useStableArrayProp(prop, warningMessage, isMeaningfulChange) {
|
|
|
3453
4904
|
return value;
|
|
3454
4905
|
}
|
|
3455
4906
|
/** 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 }) => {
|
|
4907
|
+
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, generativeUI, mcpApps, defaultThrottleMs, debug, learning }) => {
|
|
3457
4908
|
const learningConfig = useMemo(() => toLearningConfig(learning), [learning]);
|
|
3458
4909
|
const [shouldRenderInspector, setShouldRenderInspector] = useState(false);
|
|
3459
4910
|
const [inspectorVisible, setInspectorVisible] = useState(false);
|
|
@@ -3475,6 +4926,7 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY
|
|
|
3475
4926
|
const openGenUIActive = runtimeOpenGenUIEnabled || !!openGenerativeUI;
|
|
3476
4927
|
const a2uiCatalogProvided = !!a2ui?.catalog;
|
|
3477
4928
|
const a2uiActive = runtimeA2UIEnabled || a2uiCatalogProvided;
|
|
4929
|
+
const generativeUIActive = !!generativeUI?.ui;
|
|
3478
4930
|
const [runtimeLicenseStatus, setRuntimeLicenseStatus] = useState(void 0);
|
|
3479
4931
|
const [runtimeEntitlements, setRuntimeEntitlements] = useState(void 0);
|
|
3480
4932
|
const [runtimeEntitlementRetryPending, setRuntimeEntitlementRetryPending] = useState(false);
|
|
@@ -3528,10 +4980,12 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY
|
|
|
3528
4980
|
loadingComponent: a2ui?.loadingComponent,
|
|
3529
4981
|
recovery: a2ui?.recovery
|
|
3530
4982
|
}));
|
|
4983
|
+
if (generativeUIActive) renderers.push(createGenerativeUIActivityRenderer(), createGenerativeUIFunctionCallActivityRenderer());
|
|
3531
4984
|
return renderers;
|
|
3532
4985
|
}, [
|
|
3533
4986
|
a2uiActive,
|
|
3534
4987
|
openGenUIActive,
|
|
4988
|
+
generativeUIActive,
|
|
3535
4989
|
a2ui,
|
|
3536
4990
|
filteredCatalog,
|
|
3537
4991
|
mcpAppsAllowSameOrigin
|
|
@@ -3698,6 +5152,7 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY
|
|
|
3698
5152
|
if (defaultThrottleMs !== void 0) copilotkitRef.current.setDefaultThrottleMs(defaultThrottleMs);
|
|
3699
5153
|
}
|
|
3700
5154
|
const copilotkit = copilotkitRef.current;
|
|
5155
|
+
const generativeUIRuntime = useGenerativeUIRoot(copilotkit, generativeUI);
|
|
3701
5156
|
useEffect(() => {
|
|
3702
5157
|
if (!rawCatalog) return;
|
|
3703
5158
|
if (!(rawCatalog instanceof Catalog)) return;
|
|
@@ -3936,6 +5391,7 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY
|
|
|
3936
5391
|
value: licenseContextValue,
|
|
3937
5392
|
children: [
|
|
3938
5393
|
a2uiActive && /* @__PURE__ */ jsx(A2UIBuiltInToolCallRenderer, {}),
|
|
5394
|
+
generativeUIActive && /* @__PURE__ */ jsx(GenerativeUIToolCallRenderer, {}),
|
|
3939
5395
|
a2uiActive && /* @__PURE__ */ jsx(A2UICatalogContext, {
|
|
3940
5396
|
catalog: filteredCatalog,
|
|
3941
5397
|
includeSchema: a2ui?.includeSchema
|
|
@@ -3944,7 +5400,10 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY
|
|
|
3944
5400
|
value: inspectorContextValue,
|
|
3945
5401
|
children: [/* @__PURE__ */ jsx(CopilotKitAgentIdContext.Provider, {
|
|
3946
5402
|
value: agentId,
|
|
3947
|
-
children
|
|
5403
|
+
children: /* @__PURE__ */ jsx(GenerativeUIRuntimeContext.Provider, {
|
|
5404
|
+
value: generativeUIRuntime,
|
|
5405
|
+
children
|
|
5406
|
+
})
|
|
3948
5407
|
}), shouldRenderInspector ? /* @__PURE__ */ jsx(CopilotKitInspector, {
|
|
3949
5408
|
core: copilotkit,
|
|
3950
5409
|
openRequest: inspectorOpenRequest,
|
|
@@ -4542,14 +6001,14 @@ function ToolCallRow({ name, parameters, result, status, appearance, className,
|
|
|
4542
6001
|
const line = appearance === "line";
|
|
4543
6002
|
return /* @__PURE__ */ jsxs("div", {
|
|
4544
6003
|
"data-copilotkit": true,
|
|
4545
|
-
className: twMerge(
|
|
6004
|
+
className: twMerge(appearance === "card" && "cpk:border-t cpk:border-border", className),
|
|
4546
6005
|
...props,
|
|
4547
6006
|
children: [/* @__PURE__ */ jsxs("button", {
|
|
4548
6007
|
type: "button",
|
|
4549
6008
|
"aria-expanded": open,
|
|
4550
6009
|
"aria-controls": detailsId,
|
|
4551
6010
|
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"),
|
|
6011
|
+
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" : appearance === "stack" ? "cpk:w-full cpk:px-3.5 cpk:py-2.5" : "cpk:w-full cpk:px-3.5 cpk:py-2"),
|
|
4553
6012
|
children: [
|
|
4554
6013
|
/* @__PURE__ */ jsx(StatusIcon, { status }),
|
|
4555
6014
|
/* @__PURE__ */ jsx("span", {
|
|
@@ -4589,7 +6048,8 @@ function ToolCallRow({ name, parameters, result, status, appearance, className,
|
|
|
4589
6048
|
*
|
|
4590
6049
|
* Each call is drawn by its registered renderer. CopilotKit's built-in card
|
|
4591
6050
|
* (`useDefaultRenderTool`) draws a compact row inside the card and line
|
|
4592
|
-
* appearances; a custom wildcard renderer draws whatever it
|
|
6051
|
+
* appearances and an open stack; a custom wildcard renderer draws whatever it
|
|
6052
|
+
* draws.
|
|
4593
6053
|
*/
|
|
4594
6054
|
function CopilotChatToolCallGroup({ calls, renderCall, appearance = "card", isActive = false, className, ...props }) {
|
|
4595
6055
|
const [open, setOpen] = useState(false);
|
|
@@ -4668,11 +6128,6 @@ function CopilotChatToolCallGroup({ calls, renderCall, appearance = "card", isAc
|
|
|
4668
6128
|
});
|
|
4669
6129
|
}
|
|
4670
6130
|
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
6131
|
const behind = open ? 0 : Math.min(calls.length - 1, 2);
|
|
4677
6132
|
const layer = "cpk:rounded-xl cpk:border cpk:border-border cpk:bg-card cpk:text-card-foreground";
|
|
4678
6133
|
const latestStatus = entryStatus(latest, isActive);
|
|
@@ -4686,68 +6141,88 @@ function CopilotChatToolCallGroup({ calls, renderCall, appearance = "card", isAc
|
|
|
4686
6141
|
},
|
|
4687
6142
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
4688
6143
|
className: "cpk:relative cpk:isolate",
|
|
4689
|
-
children: [
|
|
4690
|
-
|
|
4691
|
-
|
|
4692
|
-
|
|
4693
|
-
|
|
4694
|
-
|
|
4695
|
-
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
|
|
4699
|
-
"
|
|
4700
|
-
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
|
|
4704
|
-
|
|
4705
|
-
/* @__PURE__ */
|
|
4706
|
-
|
|
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: [
|
|
6144
|
+
children: [
|
|
6145
|
+
Array.from({ length: behind }, (_, index) => /* @__PURE__ */ jsx("div", {
|
|
6146
|
+
"aria-hidden": "true",
|
|
6147
|
+
className: twMerge(layer, "cpk:absolute cpk:inset-0"),
|
|
6148
|
+
style: {
|
|
6149
|
+
transform: `translateY(${(index + 1) * 6}px) scaleX(${1 - (index + 1) * .045})`,
|
|
6150
|
+
zIndex: -1 - index,
|
|
6151
|
+
opacity: 1 - (index + 1) * .28
|
|
6152
|
+
}
|
|
6153
|
+
}, index)),
|
|
6154
|
+
/* @__PURE__ */ jsx("button", {
|
|
6155
|
+
type: "button",
|
|
6156
|
+
"aria-expanded": open,
|
|
6157
|
+
"aria-controls": open ? bodyId : void 0,
|
|
6158
|
+
onClick: () => setOpen((value) => !value),
|
|
6159
|
+
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.5 cpk:w-full 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")),
|
|
6160
|
+
children: open ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
6161
|
+
pluralize(calls.length, "tool call"),
|
|
4727
6162
|
/* @__PURE__ */ jsx(FailedCount, { calls }),
|
|
4728
|
-
/* @__PURE__ */
|
|
4729
|
-
className: "cpk:
|
|
4730
|
-
children:
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
|
|
4734
|
-
className: "cpk:rotate-90"
|
|
6163
|
+
/* @__PURE__ */ jsxs("span", {
|
|
6164
|
+
className: "cpk:ml-auto cpk:inline-flex cpk:items-center cpk:gap-1",
|
|
6165
|
+
children: ["Collapse", /* @__PURE__ */ jsx(Chevron, {
|
|
6166
|
+
open: true,
|
|
6167
|
+
className: "cpk:-rotate-90"
|
|
6168
|
+
})]
|
|
4735
6169
|
})
|
|
4736
|
-
]
|
|
4737
|
-
|
|
4738
|
-
|
|
6170
|
+
] }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("span", {
|
|
6171
|
+
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",
|
|
6172
|
+
children: [
|
|
6173
|
+
/* @__PURE__ */ jsx(StatusIcon, { status: latestStatus }),
|
|
6174
|
+
/* @__PURE__ */ jsx("span", {
|
|
6175
|
+
className: twMerge("cpk:shrink-0 cpk:font-mono cpk:font-medium cpk:text-foreground", latestStatus === "running" && "cpk-shimmer"),
|
|
6176
|
+
children: latest.toolCall.function.name
|
|
6177
|
+
}),
|
|
6178
|
+
latestPreview && /* @__PURE__ */ jsx("span", {
|
|
6179
|
+
className: "cpk:min-w-0 cpk:truncate cpk:font-mono cpk:text-muted-foreground",
|
|
6180
|
+
children: latestPreview
|
|
6181
|
+
}),
|
|
6182
|
+
/* @__PURE__ */ jsx("span", {
|
|
6183
|
+
className: "cpk:sr-only",
|
|
6184
|
+
children: statusLabels[latestStatus]
|
|
6185
|
+
})
|
|
6186
|
+
]
|
|
6187
|
+
}, latest.toolCall.id), /* @__PURE__ */ jsxs("span", {
|
|
6188
|
+
className: "cpk:ml-2 cpk:inline-flex cpk:shrink-0 cpk:items-center cpk:gap-2 cpk:text-xs cpk:text-muted-foreground",
|
|
6189
|
+
children: [
|
|
6190
|
+
/* @__PURE__ */ jsx(FailedCount, { calls }),
|
|
6191
|
+
/* @__PURE__ */ jsx("span", {
|
|
6192
|
+
className: "cpk:tabular-nums",
|
|
6193
|
+
children: pluralize(calls.length, "call")
|
|
6194
|
+
}),
|
|
6195
|
+
/* @__PURE__ */ jsx(Chevron, {
|
|
6196
|
+
open: false,
|
|
6197
|
+
className: "cpk:rotate-90"
|
|
6198
|
+
})
|
|
6199
|
+
]
|
|
6200
|
+
})] })
|
|
6201
|
+
}),
|
|
6202
|
+
/* @__PURE__ */ jsx("span", {
|
|
6203
|
+
"aria-live": "polite",
|
|
6204
|
+
className: "cpk:sr-only",
|
|
6205
|
+
children: open ? "" : `${latest.toolCall.function.name}: ${statusLabels[latestStatus]}`
|
|
6206
|
+
})
|
|
6207
|
+
]
|
|
4739
6208
|
}), open && /* @__PURE__ */ jsx("div", {
|
|
4740
6209
|
id: bodyId,
|
|
4741
|
-
className: "cpk:
|
|
4742
|
-
children:
|
|
6210
|
+
className: "cpk:grid cpk:gap-1.5",
|
|
6211
|
+
children: /* @__PURE__ */ jsx(ToolCallGroupContext.Provider, {
|
|
6212
|
+
value: {
|
|
6213
|
+
appearance: "stack",
|
|
6214
|
+
failedIds,
|
|
6215
|
+
active: isActive
|
|
6216
|
+
},
|
|
6217
|
+
children: calls.map((call, index) => /* @__PURE__ */ jsx("div", {
|
|
6218
|
+
className: twMerge(layer, "cpk:overflow-hidden cpk:shadow-[0_1px_2px_rgb(0_0_0/0.04)] cpk:animate-[cpk-stack-fan_240ms_cubic-bezier(0.16,1,0.3,1)_both] cpk:motion-reduce:animate-none"),
|
|
6219
|
+
style: { animationDelay: `${index * 30}ms` },
|
|
6220
|
+
children: renderCall(call)
|
|
6221
|
+
}, call.toolCall.id))
|
|
6222
|
+
})
|
|
4743
6223
|
})]
|
|
4744
6224
|
});
|
|
4745
6225
|
}
|
|
4746
|
-
if (calls.length === 1) return /* @__PURE__ */ jsx("div", {
|
|
4747
|
-
...groupProps,
|
|
4748
|
-
className: twMerge("cpk:py-1", className),
|
|
4749
|
-
children: renderCall(latest)
|
|
4750
|
-
});
|
|
4751
6226
|
return /* @__PURE__ */ jsxs("div", {
|
|
4752
6227
|
...groupProps,
|
|
4753
6228
|
className: twMerge("cpk:my-3 cpk:overflow-hidden cpk:rounded-xl cpk:border cpk:border-border cpk:bg-card cpk:text-card-foreground", className),
|
|
@@ -4770,7 +6245,7 @@ function CopilotChatToolCallGroup({ calls, renderCall, appearance = "card", isAc
|
|
|
4770
6245
|
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
6246
|
children: [status === "failed" ? /* @__PURE__ */ jsx(FailedCount, { calls }) : /* @__PURE__ */ jsx("span", {
|
|
4772
6247
|
className: "cpk:tabular-nums",
|
|
4773
|
-
children: status
|
|
6248
|
+
children: status !== "running" ? statusLabels[status] : done > 0 && `${done} done`
|
|
4774
6249
|
}), /* @__PURE__ */ jsx(Chevron, { open })]
|
|
4775
6250
|
})
|
|
4776
6251
|
]
|
|
@@ -7605,7 +9080,10 @@ function CopilotChatAssistantMessage({ message, messages, isRunning, isLatest, o
|
|
|
7605
9080
|
}
|
|
7606
9081
|
};
|
|
7607
9082
|
};
|
|
7608
|
-
const boundMarkdownRenderer = renderSlot(markdownRenderer, CopilotChatAssistantMessage.MarkdownRenderer, {
|
|
9083
|
+
const boundMarkdownRenderer = renderSlot(markdownRenderer, CopilotChatAssistantMessage.MarkdownRenderer, {
|
|
9084
|
+
content: message.content || "",
|
|
9085
|
+
messageId: message.id
|
|
9086
|
+
});
|
|
7609
9087
|
const boundCopyButton = renderSlot(copyButton, CopilotChatAssistantMessage.CopyButton, { onClick: async () => {
|
|
7610
9088
|
if (message.content) return await copyToClipboard(message.content);
|
|
7611
9089
|
return false;
|
|
@@ -7715,11 +9193,19 @@ function CopilotChatAssistantMessage({ message, messages, isRunning, isLatest, o
|
|
|
7715
9193
|
});
|
|
7716
9194
|
}
|
|
7717
9195
|
(function(_CopilotChatAssistantMessage) {
|
|
7718
|
-
_CopilotChatAssistantMessage.MarkdownRenderer = ({ content, className, ...props }) =>
|
|
7719
|
-
|
|
7720
|
-
|
|
7721
|
-
|
|
7722
|
-
|
|
9196
|
+
_CopilotChatAssistantMessage.MarkdownRenderer = ({ content, className, messageId, ...props }) => {
|
|
9197
|
+
if (useGenerativeUIRuntime()?.transport === "markdown" && messageId !== void 0) return /* @__PURE__ */ jsx(MarkdownSurfaces, {
|
|
9198
|
+
content: content ?? "",
|
|
9199
|
+
messageId,
|
|
9200
|
+
className,
|
|
9201
|
+
...props
|
|
9202
|
+
});
|
|
9203
|
+
return /* @__PURE__ */ jsx(Streamdown, {
|
|
9204
|
+
className,
|
|
9205
|
+
...props,
|
|
9206
|
+
children: content ?? ""
|
|
9207
|
+
});
|
|
9208
|
+
};
|
|
7723
9209
|
_CopilotChatAssistantMessage.Toolbar = ({ className, ...props }) => /* @__PURE__ */ jsx("div", {
|
|
7724
9210
|
"data-testid": "copilot-assistant-toolbar",
|
|
7725
9211
|
className: twMerge("cpk:w-full cpk:bg-transparent cpk:flex cpk:items-center cpk:-ml-[5px] cpk:-mt-[0px]", className),
|
|
@@ -7870,7 +9356,13 @@ var CopilotChatAssistantMessage_default = CopilotChatAssistantMessage;
|
|
|
7870
9356
|
|
|
7871
9357
|
//#endregion
|
|
7872
9358
|
//#region src/v2/components/chat/Lightbox.tsx
|
|
9359
|
+
/**
|
|
9360
|
+
* A full-screen preview portalled to `document.body`. It closes on Escape, a
|
|
9361
|
+
* click on the backdrop, or its close button, which is named by
|
|
9362
|
+
* `labels.attachmentPreviewCloseButtonLabel`.
|
|
9363
|
+
*/
|
|
7873
9364
|
function Lightbox({ onClose, children }) {
|
|
9365
|
+
const labels = useCopilotChatConfiguration()?.labels ?? CopilotChatDefaultLabels;
|
|
7874
9366
|
useEffect(() => {
|
|
7875
9367
|
const handleKey = (e) => {
|
|
7876
9368
|
if (e.key === "Escape") onClose();
|
|
@@ -7885,7 +9377,7 @@ function Lightbox({ onClose, children }) {
|
|
|
7885
9377
|
children: [/* @__PURE__ */ jsx("button", {
|
|
7886
9378
|
onClick: onClose,
|
|
7887
9379
|
className: "cpk:absolute cpk:top-4 cpk:right-4 cpk:text-white cpk:bg-white/10 cpk:hover:bg-white/20 cpk:rounded-full cpk:w-10 cpk:h-10 cpk:flex cpk:items-center cpk:justify-center cpk:cursor-pointer cpk:border-none cpk:z-10",
|
|
7888
|
-
"aria-label":
|
|
9380
|
+
"aria-label": labels.attachmentPreviewCloseButtonLabel,
|
|
7889
9381
|
children: /* @__PURE__ */ jsx(X, { className: "cpk:w-5 cpk:h-5" })
|
|
7890
9382
|
}), /* @__PURE__ */ jsx("div", {
|
|
7891
9383
|
onClick: (e) => e.stopPropagation(),
|
|
@@ -8238,7 +9730,14 @@ function formatDuration$1(seconds) {
|
|
|
8238
9730
|
if (secs === 0) return `${mins} minute${mins > 1 ? "s" : ""}`;
|
|
8239
9731
|
return `${mins}m ${secs}s`;
|
|
8240
9732
|
}
|
|
9733
|
+
/**
|
|
9734
|
+
* A reasoning message as a collapsible block. While the model reasons it is
|
|
9735
|
+
* open and the header shows `labels.reasoningMessageThinkingLabel`; when
|
|
9736
|
+
* streaming ends it collapses and the header reads "Thought for …". The
|
|
9737
|
+
* `header` slot also receives `elapsedSeconds`.
|
|
9738
|
+
*/
|
|
8241
9739
|
function CopilotChatReasoningMessage({ message, messages, isRunning, isLatest: isLatestProp, header, contentView, toggle, children, className, ...props }) {
|
|
9740
|
+
const labels = useCopilotChatConfiguration()?.labels ?? CopilotChatDefaultLabels;
|
|
8242
9741
|
const isLatest = isLatestProp ?? messages?.[messages.length - 1]?.id === message.id;
|
|
8243
9742
|
const isStreaming = !!(isRunning && isLatest);
|
|
8244
9743
|
const hasContent = !!(message.content && message.content.length > 0);
|
|
@@ -8268,12 +9767,13 @@ function CopilotChatReasoningMessage({ message, messages, isRunning, isLatest: i
|
|
|
8268
9767
|
userToggledRef.current = true;
|
|
8269
9768
|
setIsOpen((prev) => !prev);
|
|
8270
9769
|
} : void 0;
|
|
8271
|
-
const label = isStreaming ?
|
|
9770
|
+
const label = isStreaming ? labels.reasoningMessageThinkingLabel : `Thought for ${formatDuration$1(elapsed)}`;
|
|
8272
9771
|
const boundHeader = renderSlot(header, CopilotChatReasoningMessage.Header, {
|
|
8273
9772
|
isOpen,
|
|
8274
9773
|
label,
|
|
8275
9774
|
hasContent,
|
|
8276
9775
|
isStreaming,
|
|
9776
|
+
elapsedSeconds: elapsed,
|
|
8277
9777
|
onClick: handleToggle
|
|
8278
9778
|
});
|
|
8279
9779
|
const boundContent = renderSlot(contentView, CopilotChatReasoningMessage.Content, {
|
|
@@ -8305,7 +9805,7 @@ function CopilotChatReasoningMessage({ message, messages, isRunning, isLatest: i
|
|
|
8305
9805
|
});
|
|
8306
9806
|
}
|
|
8307
9807
|
(function(_CopilotChatReasoningMessage) {
|
|
8308
|
-
_CopilotChatReasoningMessage.Header = ({ isOpen, label = "Thoughts", hasContent, isStreaming, className, children: headerChildren, ...headerProps }) => {
|
|
9808
|
+
_CopilotChatReasoningMessage.Header = ({ isOpen, label = "Thoughts", hasContent, isStreaming, elapsedSeconds: _elapsedSeconds, className, children: headerChildren, ...headerProps }) => {
|
|
8309
9809
|
const isExpandable = !!hasContent;
|
|
8310
9810
|
return /* @__PURE__ */ jsxs("button", {
|
|
8311
9811
|
type: "button",
|
|
@@ -9581,7 +11081,12 @@ CopilotChatMessageView.Cursor = function Cursor({ className, ...props }) {
|
|
|
9581
11081
|
|
|
9582
11082
|
//#endregion
|
|
9583
11083
|
//#region src/v2/components/chat/CopilotChatAttachmentQueue.tsx
|
|
11084
|
+
/**
|
|
11085
|
+
* The attachments queued in the composer, each with a preview and a remove
|
|
11086
|
+
* button named by `labels.attachmentRemoveButtonLabel`.
|
|
11087
|
+
*/
|
|
9584
11088
|
const CopilotChatAttachmentQueue = ({ attachments, onRemoveAttachment, className }) => {
|
|
11089
|
+
const labels = useCopilotChatConfiguration()?.labels ?? CopilotChatDefaultLabels;
|
|
9585
11090
|
if (attachments.length === 0) return null;
|
|
9586
11091
|
return /* @__PURE__ */ jsx("div", {
|
|
9587
11092
|
"data-testid": "copilot-attachment-queue",
|
|
@@ -9596,7 +11101,7 @@ const CopilotChatAttachmentQueue = ({ attachments, onRemoveAttachment, className
|
|
|
9596
11101
|
/* @__PURE__ */ jsx("button", {
|
|
9597
11102
|
onClick: () => onRemoveAttachment(attachment.id),
|
|
9598
11103
|
className: cn("cpk:absolute cpk:bg-black/60 cpk:text-white cpk:border-none cpk:rounded-full cpk:w-5 cpk:h-5 cpk:flex cpk:items-center cpk:justify-center cpk:cursor-pointer cpk:text-[10px] cpk:z-20", isMedia ? "cpk:top-1 cpk:right-1" : "cpk:top-1.5 cpk:right-1.5"),
|
|
9599
|
-
"aria-label":
|
|
11104
|
+
"aria-label": labels.attachmentRemoveButtonLabel,
|
|
9600
11105
|
children: "✕"
|
|
9601
11106
|
})
|
|
9602
11107
|
]
|
|
@@ -9652,7 +11157,13 @@ function AudioPreview({ attachment }) {
|
|
|
9652
11157
|
})]
|
|
9653
11158
|
});
|
|
9654
11159
|
}
|
|
11160
|
+
/**
|
|
11161
|
+
* A video thumbnail with a play button, named by
|
|
11162
|
+
* `labels.attachmentPlayVideoButtonLabel`, that opens the full player in a
|
|
11163
|
+
* lightbox.
|
|
11164
|
+
*/
|
|
9655
11165
|
function VideoPreview({ attachment }) {
|
|
11166
|
+
const labels = useCopilotChatConfiguration()?.labels ?? CopilotChatDefaultLabels;
|
|
9656
11167
|
const src = getSourceUrl(attachment.source);
|
|
9657
11168
|
const { thumbnailRef, vtName, open, openLightbox, closeLightbox } = useLightbox();
|
|
9658
11169
|
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
@@ -9673,7 +11184,7 @@ function VideoPreview({ attachment }) {
|
|
|
9673
11184
|
/* @__PURE__ */ jsx("button", {
|
|
9674
11185
|
onClick: openLightbox,
|
|
9675
11186
|
className: "cpk:absolute cpk:inset-0 cpk:flex cpk:items-center cpk:justify-center cpk:z-10 cpk:cursor-pointer cpk:bg-black/20 cpk:border-none cpk:p-0",
|
|
9676
|
-
"aria-label":
|
|
11187
|
+
"aria-label": labels.attachmentPlayVideoButtonLabel,
|
|
9677
11188
|
children: /* @__PURE__ */ jsx("div", {
|
|
9678
11189
|
className: "cpk:w-8 cpk:h-8 cpk:rounded-full cpk:bg-black/60 cpk:flex cpk:items-center cpk:justify-center",
|
|
9679
11190
|
children: /* @__PURE__ */ jsx(Play, { className: "cpk:w-4 cpk:h-4 cpk:text-white cpk:ml-0.5" })
|
|
@@ -10655,7 +12166,7 @@ function useInspectorThreadOverride(args) {
|
|
|
10655
12166
|
|
|
10656
12167
|
//#endregion
|
|
10657
12168
|
//#region src/v2/components/chat/CopilotChat.tsx
|
|
10658
|
-
function CopilotChat({ agentId, threadId, labels, inspectorTools, chatView, isModalDefaultOpen, attachments: attachmentsConfig, onError, throttleMs, ...props }) {
|
|
12169
|
+
function CopilotChat({ agentId, threadId, labels, inspectorTools, chatView, isModalDefaultOpen, attachments: attachmentsConfig, onError, throttleMs, generativeUISurface, ...props }) {
|
|
10659
12170
|
const existingConfig = useCopilotChatConfiguration();
|
|
10660
12171
|
const inspector = useCopilotKitInspector();
|
|
10661
12172
|
const inspectorContextValue = useMemo(() => ({
|
|
@@ -10760,6 +12271,7 @@ function CopilotChat({ agentId, threadId, labels, inspectorTools, chatView, isMo
|
|
|
10760
12271
|
const pendingRunActivityReconnectRef = useRef(false);
|
|
10761
12272
|
const runActivityReconnectGenerationRef = useRef(0);
|
|
10762
12273
|
const activeLocalRunIdsRef = useRef(/* @__PURE__ */ new Set());
|
|
12274
|
+
const observedLocalRunIdsRef = useRef(/* @__PURE__ */ new Set());
|
|
10763
12275
|
const recentlyLocalRunIdsRef = useRef(/* @__PURE__ */ new Map());
|
|
10764
12276
|
const activeWakeRunIdsRef = useRef(/* @__PURE__ */ new Set());
|
|
10765
12277
|
const recentlyWakeRunIdsRef = useRef(/* @__PURE__ */ new Map());
|
|
@@ -10791,7 +12303,7 @@ function CopilotChat({ agentId, threadId, labels, inspectorTools, chatView, isMo
|
|
|
10791
12303
|
}, []);
|
|
10792
12304
|
const isLocalActiveRunActivity = useCallback((notification) => {
|
|
10793
12305
|
if (notification.agentId && notification.agentId !== resolvedAgentId) return false;
|
|
10794
|
-
if (!notification.runId || !activeLocalRunIdsRef.current.has(notification.runId) && !recentlyLocalRunIdsRef.current.has(notification.runId)) return false;
|
|
12306
|
+
if (!notification.runId || !activeLocalRunIdsRef.current.has(notification.runId) && !observedLocalRunIdsRef.current.has(notification.runId) && !recentlyLocalRunIdsRef.current.has(notification.runId)) return false;
|
|
10795
12307
|
const eventType = notification.eventType.toUpperCase();
|
|
10796
12308
|
return eventType === "RUN_STARTED" || eventType === "RUN_FINISHED" || eventType === "RUN_ERROR";
|
|
10797
12309
|
}, [resolvedAgentId]);
|
|
@@ -10990,6 +12502,16 @@ function CopilotChat({ agentId, threadId, labels, inspectorTools, chatView, isMo
|
|
|
10990
12502
|
pendingWakeRunIdRef.current = notification.runId;
|
|
10991
12503
|
startRunActivityReconnectRef.current?.(generation);
|
|
10992
12504
|
});
|
|
12505
|
+
const observedLocalRunIds = observedLocalRunIdsRef.current;
|
|
12506
|
+
const localRunSubscription = agent.subscribe({
|
|
12507
|
+
onRunInitialized: ({ input }) => {
|
|
12508
|
+
observedLocalRunIds.add(input.runId);
|
|
12509
|
+
},
|
|
12510
|
+
onRunFinalized: ({ input }) => {
|
|
12511
|
+
observedLocalRunIds.delete(input.runId);
|
|
12512
|
+
rememberRecentlyLocalRunId(input.runId);
|
|
12513
|
+
}
|
|
12514
|
+
});
|
|
10993
12515
|
return () => {
|
|
10994
12516
|
detached = true;
|
|
10995
12517
|
pendingRunActivityReconnectRef.current = false;
|
|
@@ -11002,6 +12524,7 @@ function CopilotChat({ agentId, threadId, labels, inspectorTools, chatView, isMo
|
|
|
11002
12524
|
if (wakeReconnectActive) agent.detachActiveRun().catch(() => {});
|
|
11003
12525
|
activeWakeRunIdsRef.current.clear();
|
|
11004
12526
|
subscription.unsubscribe();
|
|
12527
|
+
localRunSubscription.unsubscribe();
|
|
11005
12528
|
if (ownsStandaloneStore) {
|
|
11006
12529
|
threadStore.setContext(null);
|
|
11007
12530
|
threadStore.stop();
|
|
@@ -11020,6 +12543,7 @@ function CopilotChat({ agentId, threadId, labels, inspectorTools, chatView, isMo
|
|
|
11020
12543
|
copilotkit.threadEndpoints?.realtimeMetadata,
|
|
11021
12544
|
standaloneRunActivityStore,
|
|
11022
12545
|
isLocalActiveRunActivity,
|
|
12546
|
+
rememberRecentlyLocalRunId,
|
|
11023
12547
|
rememberRecentlyWakeRunId
|
|
11024
12548
|
]);
|
|
11025
12549
|
const waitForActiveRunToSettle = useCallback(async () => {
|
|
@@ -11334,7 +12858,10 @@ function CopilotChat({ agentId, threadId, labels, inspectorTools, chatView, isMo
|
|
|
11334
12858
|
value: lastUserMessageState,
|
|
11335
12859
|
children: /* @__PURE__ */ jsx(CopilotKitInspectorContextProvider, {
|
|
11336
12860
|
value: inspectorContextValue,
|
|
11337
|
-
children:
|
|
12861
|
+
children: /* @__PURE__ */ jsx(GenerativeUIChatSlotContext.Provider, {
|
|
12862
|
+
value: generativeUISurface,
|
|
12863
|
+
children: RenderedChatView
|
|
12864
|
+
})
|
|
11338
12865
|
})
|
|
11339
12866
|
})
|
|
11340
12867
|
]
|
|
@@ -11538,28 +13065,34 @@ CopilotModalHeader.displayName = "CopilotModalHeader";
|
|
|
11538
13065
|
...props,
|
|
11539
13066
|
children
|
|
11540
13067
|
});
|
|
11541
|
-
_CopilotModalHeader.CloseButton = ({ className, ...props }) =>
|
|
11542
|
-
|
|
11543
|
-
|
|
11544
|
-
|
|
11545
|
-
|
|
11546
|
-
|
|
11547
|
-
|
|
11548
|
-
|
|
11549
|
-
|
|
11550
|
-
|
|
11551
|
-
|
|
11552
|
-
|
|
11553
|
-
|
|
11554
|
-
|
|
11555
|
-
|
|
11556
|
-
|
|
11557
|
-
|
|
11558
|
-
|
|
11559
|
-
|
|
11560
|
-
"
|
|
11561
|
-
|
|
11562
|
-
|
|
13068
|
+
_CopilotModalHeader.CloseButton = ({ className, ...props }) => {
|
|
13069
|
+
const labels = useCopilotChatConfiguration()?.labels ?? CopilotChatDefaultLabels;
|
|
13070
|
+
return /* @__PURE__ */ jsx("button", {
|
|
13071
|
+
type: "button",
|
|
13072
|
+
"data-testid": "copilot-close-button",
|
|
13073
|
+
className: cn("cpk:inline-flex cpk:size-8 cpk:items-center cpk:justify-center cpk:rounded-full cpk:text-muted-foreground cpk:transition cpk:cursor-pointer", "cpk:hover:bg-muted cpk:hover:text-foreground cpk:focus-visible:outline-none cpk:focus-visible:ring-2 cpk:focus-visible:ring-ring", className),
|
|
13074
|
+
"aria-label": labels.modalHeaderCloseButtonLabel,
|
|
13075
|
+
...props,
|
|
13076
|
+
children: /* @__PURE__ */ jsx(X, {
|
|
13077
|
+
className: "cpk:h-4 cpk:w-4",
|
|
13078
|
+
"aria-hidden": "true"
|
|
13079
|
+
})
|
|
13080
|
+
});
|
|
13081
|
+
};
|
|
13082
|
+
_CopilotModalHeader.DrawerLauncher = ({ className, ...props }) => {
|
|
13083
|
+
const labels = useCopilotChatConfiguration()?.labels ?? CopilotChatDefaultLabels;
|
|
13084
|
+
return /* @__PURE__ */ jsx("button", {
|
|
13085
|
+
type: "button",
|
|
13086
|
+
"data-testid": "copilot-threads-drawer-launcher",
|
|
13087
|
+
className: cn("cpk:inline-flex cpk:size-8 cpk:items-center cpk:justify-center cpk:rounded-full cpk:text-muted-foreground cpk:transition cpk:cursor-pointer", "cpk:hover:bg-muted cpk:hover:text-foreground cpk:focus-visible:outline-none cpk:focus-visible:ring-2 cpk:focus-visible:ring-ring", className),
|
|
13088
|
+
"aria-label": labels.modalHeaderThreadsButtonLabel,
|
|
13089
|
+
...props,
|
|
13090
|
+
children: /* @__PURE__ */ jsx(PanelLeftOpen, {
|
|
13091
|
+
className: "cpk:h-4 cpk:w-4",
|
|
13092
|
+
"aria-hidden": "true"
|
|
13093
|
+
})
|
|
13094
|
+
});
|
|
13095
|
+
};
|
|
11563
13096
|
})(CopilotModalHeader || (CopilotModalHeader = {}));
|
|
11564
13097
|
CopilotModalHeader.Title.displayName = "CopilotModalHeader.Title";
|
|
11565
13098
|
CopilotModalHeader.CloseButton.displayName = "CopilotModalHeader.CloseButton";
|
|
@@ -11569,6 +13102,10 @@ CopilotModalHeader.DrawerLauncher.displayName = "CopilotModalHeader.DrawerLaunch
|
|
|
11569
13102
|
//#region src/v2/components/chat/CopilotSidebarView.tsx
|
|
11570
13103
|
const DEFAULT_SIDEBAR_WIDTH = 480;
|
|
11571
13104
|
const SIDEBAR_TRANSITION_MS = 260;
|
|
13105
|
+
/**
|
|
13106
|
+
* The chat in a side panel: a `complementary` region named by
|
|
13107
|
+
* `labels.sidebarLabel`, with a header, the chat view and a toggle button.
|
|
13108
|
+
*/
|
|
11572
13109
|
function CopilotSidebarView({ header, toggleButton, width, defaultOpen = true, position = "right", ...props }) {
|
|
11573
13110
|
const { open, onOpenChange } = useModalOpenControl();
|
|
11574
13111
|
const hasOpenControl = open !== void 0 || onOpenChange !== void 0;
|
|
@@ -11589,7 +13126,8 @@ function CopilotSidebarView({ header, toggleButton, width, defaultOpen = true, p
|
|
|
11589
13126
|
});
|
|
11590
13127
|
}
|
|
11591
13128
|
function CopilotSidebarViewInternal({ header, toggleButton, width, position = "right", ...props }) {
|
|
11592
|
-
const
|
|
13129
|
+
const configuration = useCopilotChatConfiguration();
|
|
13130
|
+
const isSidebarOpen = configuration?.isModalOpen ?? false;
|
|
11593
13131
|
const sidebarRef = useRef(null);
|
|
11594
13132
|
const [sidebarWidth, setSidebarWidth] = useState(width ?? DEFAULT_SIDEBAR_WIDTH);
|
|
11595
13133
|
const widthToCss = (w) => {
|
|
@@ -11654,7 +13192,7 @@ function CopilotSidebarViewInternal({ header, toggleButton, width, position = "r
|
|
|
11654
13192
|
paddingBottom: "env(safe-area-inset-bottom)"
|
|
11655
13193
|
},
|
|
11656
13194
|
"aria-hidden": !isSidebarOpen,
|
|
11657
|
-
"aria-label":
|
|
13195
|
+
"aria-label": configuration?.labels.sidebarLabel ?? CopilotChatDefaultLabels.sidebarLabel,
|
|
11658
13196
|
role: "complementary",
|
|
11659
13197
|
children: /* @__PURE__ */ jsxs("div", {
|
|
11660
13198
|
className: "cpk:flex cpk:h-full cpk:w-full cpk:flex-col cpk:overflow-hidden",
|
|
@@ -14483,5 +16021,5 @@ function validateProps(props) {
|
|
|
14483
16021
|
}
|
|
14484
16022
|
|
|
14485
16023
|
//#endregion
|
|
14486
|
-
export { INTERRUPT_EVENT_NAME as $,
|
|
14487
|
-
//# sourceMappingURL=copilotkit-
|
|
16024
|
+
export { INTERRUPT_EVENT_NAME as $, ɵphoenixSocket$ as $a, isAbortError as $i, MultiAgentCapabilitiesSchema as $n, TextMessageEndEventSchema as $r, AudioPartSchema as $t, CopilotChatMessageView as A, withAuthoritativeActivityTypes as Aa, createActionGroup as Ai, HttpAgent as An, RunHandler as Ar, ɵrunMcpFollowUp as At, CopilotChatReasoningMessage_default as B, ɵisHttpAgent$1 as Ba, emitInspectorViewThread as Bi, InputContentUrlSourceSchema as Bn, SubagentFinishedEventSchema as Br, AGUI_METADATA_KEY as Bt, CopilotModalHeader as C, splitA2UIMarkdown$1 as Ca, buildResumeArray as Ci, EventType as Cn, RunAgentInputSchema as Cr, OpenGenerativeUIContentSchema as Ct, CopilotChat as D, transformChunks as Da, contentHasMedia as Di, FilterToolCallsMiddleware as Dn, RunFinishedInterruptOutcomeSchema as Dr, MCPAppsActivityContentSchema as Dt, DefaultOpenIcon as E, tokenUsageFromLangChainMetadata as Ea, completePartialMarkdown as Ei, FileSourceSchema as En, RunFinishedEventSchema as Er, useSandboxFunctions as Et, getIntelligenceTurnAnchors as F, ɵTHREAD_REQUEST_TIMEOUT_MS as Fa, createSelector as Fi, ImageInputPartSchema as Fn, StateSchema as Fr, CopilotChatAudioRecorder as Ft, useLearningContainersInCurrentThread as G, ɵmemoryDomainEvents as Ga, ensureObjectArgs as Gi, JsonPointerSchema as Gn, SubagentRunIdSchema as Gr, AddOperationSchema as Gt, CopilotChatAttachmentRenderer as H, ɵjoinPhoenixChannel$ as Ha, empty as Hi, InterruptSchema as Hn, SubagentFinishedSuccessOutcomeSchema as Hr, ActivityDeltaEventSchema as Ht, IntelligenceIndicatorView as I, ɵcreateMemoryStore as Ia, createStore as Ii, ImagePartSchema as In, StateSnapshotEventSchema as Ir, A2UI_FENCE_LANGUAGE as It, useLearnFromUserActionInCurrentThread as J, ɵobservePhoenixEvent$ as Ja, extractStringField as Ji, MessageSchema as Jn, SystemMessageSchema as Jr, AgentThreadLockedError as Jt, useLearningContainers as K, ɵmemoryReducer as Ka, extractCompleteArrayItems as Ki, MEMORY_ERROR_REGISTRY as Kn, SubagentStartedEventSchema as Kr, AgentCapabilitiesSchema as Kt, CopilotChatWorkSummary as L, ɵcreateThreadSelectors as La, defaultApplyEvents as Li, InputContentDataSourceSchema as Ln, StepFinishedEventSchema as Lr, ACTIVITY_HISTORY_METADATA as Lt, messageRow as M, ɵInterruptState$1 as Ma, createEffect as Mi, INSPECTOR_THREAD_BRIDGE_PLUGIN_ID as Mn, StateCapabilitiesSchema as Mr, useRenderToolCall as Mt, INTELLIGENCE_TURN_HEAD as N, ɵMAX_SOCKET_RETRIES as Na, createInspectorThreadRequestId as Ni, IdentityCapabilitiesSchema as Nn, StateDeltaEventSchema as Nr, CopilotChatInput_default as Nt, CopilotChatView_default as O, transformHttpEventStream as Oa, contentToText$1 as Oi, FunctionCallSchema as On, RunFinishedOutcomeSchema as Or, MCPAppsActivityRenderer as Ot, IntelligenceIndicator as P, ɵRUNTIME_PROBE_TIMEOUT_MS as Pa, createReducer as Pi, ImageInputContentSchema as Pn, StateManager as Pr, AudioRecorderError as Pt, useInterrupt as Q, ɵphoenixChannel$ as Qa, getWebMCPModelContext as Qi, MoveOperationSchema as Qn, TextMessageContentEventSchema as Qr, AudioInputPartSchema as Qt, CopilotChatSuggestionView as R, ɵcreateThreadStore$1 as Ra, emitInspectorActiveThread$1 as Ri, InputContentSchema as Rn, StepStartedEventSchema as Rr, AGUIConnectNotImplementedError$1 as Rt, CopilotSidebarView as S, select as Sa, authoritativeActivityTypes as Si, EventSchemas as Sn, RoleSchema as Sr, OpenGenerativeUIActivityType as St, DefaultCloseIcon as T, tokenUsageFromAiSdkUsage as Ta, compactEvents as Ti, ExecutionCapabilitiesSchema as Tn, RunFinishedCancelledOutcomeSchema as Tr, SandboxFunctionsContext as Tt, CopilotChatAssistantMessage_default as U, ɵmapMemoryMetadataEvent as Ua, enforceEvents as Ui, JsonPatchOperationSchema as Un, SubagentFinishedSuspendedOutcomeSchema as Ur, ActivityMessageSchema as Ut, CopilotChatUserMessage_default as V, ɵisRetryableMemoryStatus as Va, emitInspectorViewThreadResult$1 as Vi, IntelligenceAgent as Vn, SubagentFinishedOutcomeSchema as Vr, AbstractAgent$1 as Vt, CopilotChatToolCallsView as W, ɵmemoryAdapterEvents as Wa, enforceOutgoingInput as Wi, JsonPatchSchema as Wn, SubagentInfoSchema as Wr, ActivitySnapshotEventSchema as Wt, useMemories as X, ɵobservePhoenixSocketHealth$ as Xa, getMarkdownOperationSurfaceId$1 as Xi, MetadataSchema as Xn, TextInputContentSchema as Xr, AttributableSchema as Xt, useLearnFromUserAction as Y, ɵobservePhoenixJoinOutcome$ as Ya, flattenInformationalCards$1 as Yi, MessagesSnapshotEventSchema as Yn, TestOperationSchema as Yr, AssistantMessageSchema as Yt, useThreads$1 as Z, ɵobservePhoenixSocketSignals$ as Za, getRunOutcome as Zi, Middleware as Zn, TextMessageChunkEventSchema as Zr, AudioInputContentSchema as Zt, WildcardToolCallRender as _, randomUUID$2 as _a, VideoInputContentSchema as _i, DeveloperMessageSchema as _n, ReasoningMessageStartEventSchema as _r, useLicenseContext$1 as _t, ThreadsProvider as a, ofType as aa, ToolCallChunkEventSchema as ai, CompatibilityBoundary as an, ɵselectMemoriesAvailable$1 as ao, PROTOCOL_VERSION as ar, useAgent as at, CopilotSidebar as b, runHttpRequest as ba, WebMCPRegistry as bi, DocumentPartSchema as bn, ReplaceOperationSchema as br, GenerateSandboxedUiArgsSchema as bt, CoAgentStateRendersProvider as c, onInspectorActiveThread as ca, ToolCallSchema as ci, ContextStore as cn, ɵselectMemoriesIsMutating as co, RawEventSchema as cr, CopilotChatToolCallGroup as ct, shouldShowDevConsole as d, onInspectorViewThreadResult as da, ToolMessageSchema as di, CopilotKitCoreRuntimeConnectionStatus$1 as dn, ɵselectThreadsError$1 as do, ReasoningEncryptedValueSubtypeSchema as dr, useFrontendTools as dt, isInspectorThreadBridgeEnabled$1 as ea, TextMessageRoleSchema as ei, BackwardCompatibility_0_0_39 as en, ɵselectFetchMoreError$1 as eo, MultimodalCapabilitiesSchema as er, useConfigureSuggestions as et, useToast as f, parseProtoStream as fa, ToolSchema as fi, CopilotKitHeaderResolutionError as fn, ɵselectThreadsIsLoading$1 as fo, ReasoningEndEventSchema as fr, useFrontendTool as ft, useCopilotContext as g, props as ga, UserMessageSchema as gi, DebugLogger as gn, ReasoningMessageSchema as gr, useCopilotKit$1 as gt, CopilotContext as h, prepareSurfaceOperations$1 as ha, UrlSourceSchema as hi, DataSourceSchema as hn, ReasoningMessageEndEventSchema as hr, CopilotKitProvider as ht, ThreadsContext as i, mergeMetadata as ia, ToolCallArgsEventSchema as ii, BaseMessageSchema as in, ɵselectMemories$1 as io, OutputCapabilitiesSchema as ir, UseAgentUpdate as it, messageGroup as j, ɵCOPILOTKIT_FEATURES as ja, createDebugLogger as ji, HumanInTheLoopCapabilitiesSchema as jn, RunStartedEventSchema as jr, CopilotKitInspector as jt, CopilotChatAttachmentQueue as k, verifyEvents as ka, convertToLegacyEvents as ki, FunctionMiddleware as kn, RunFinishedSuccessOutcomeSchema as kr, MCPAppsActivityType as kt, useCoAgentStateRenders as l, onInspectorStopViewing$1 as la, ToolCallStartEventSchema as li, CopilotKitCore$1 as ln, ɵselectMemoriesRealtimeStatus$1 as lo, ReasoningCapabilitiesSchema as lr, useRenderTool as lt, useCopilotMessagesContext as m, parseToolArguments as ma, TransportCapabilitiesSchema as mi, CustomEventSchema as mn, ɵwithHeaderDefaults$1 as mo, ReasoningMessageContentEventSchema as mr, useRenderCustomMessages as mt, defaultCopilotContextCategories as n, isRecognizedEvent as na, TextPartSchema as ni, BackwardCompatibility_0_0_57 as nn, ɵselectIsFetchingNextPage$1 as no, MultimodalOutputCapabilitiesSchema as nr, useAgentContext as nt, useThreads as o, omitOptionalNulls as oa, ToolCallEndEventSchema as oi, ContentPartSchema as on, ɵselectMemoriesError$1 as oo, PartSourceSchema as or, useHumanInTheLoop as ot, CopilotMessagesContext as p, parseSSEStream as pa, ToolsCapabilitiesSchema as pi, CopyOperationSchema as pn, ɵthreadAdapterEvents as po, ReasoningMessageChunkEventSchema as pr, useRenderActivityMessage as pt, useAttachments as q, ɵmemoryRestEvents as qa, extractFenceOperations$1 as qi, MemoryError as qn, SuggestionEngine as qr, AgentRegistry as qt, CoAgentStateRenderBridge as r, isRunCompletionAware$1 as ra, TokenUsageSchema as ri, BaseEventSchema as rn, ɵselectIsMutating$1 as ro, OptionalMetadataSchema as rr, useCapabilities as rt, CoAgentStateRendersContext as s, on as sa, ToolCallResultEventSchema as si, ContextSchema as sn, ɵselectMemoriesIsLoading$1 as so, ProxiedCopilotRuntimeAgent$1 as sr, useDefaultRenderTool as st, CopilotKit as t, isInterruptExpired as ta, TextMessageStartEventSchema as ti, BackwardCompatibility_0_0_45 as tn, ɵselectHasNextPage$1 as to, MultimodalInputCapabilitiesSchema as tr, useSuggestions as tt, useAsyncCallback as u, onInspectorViewThread$1 as ua, ToolCallStatus$1 as ui, CopilotKitCoreErrorCode$1 as un, ɵselectThreads$1 as uo, ReasoningEncryptedValueEventSchema as ur, useComponent as ut, CopilotThreadsDrawer as v, resolveAgentDebugConfig as va, VideoInputPartSchema as vi, DocumentInputContentSchema as vn, ReasoningStartEventSchema as vr, CopilotKitCoreReact as vt, CopilotChatToggleButton as w, structuredClone_ as wa, classifySurfaceCards as wi, EventTypeSchema as wn, RunErrorEventSchema as wr, OpenGenerativeUIToolRenderer as wt, CopilotPopupView as x, segmentSurfaceProse$1 as xa, aggregateTokenUsage as xi, EventSchema as xn, ResumeEntrySchema as xr, OpenGenerativeUIActivityRenderer as xt, CopilotPopup as y, resolveDebugLogger as ya, VideoPartSchema as yi, DocumentInputPartSchema as yn, RemoveOperationSchema as yr, createA2UIMessageRenderer as yt, CopilotChatSuggestionPill as z, ɵisCopilotKitFeature as za, emitInspectorStopViewing as zi, InputContentSourceSchema as zn, SubagentErrorEventSchema as zr, AGUIError as zt };
|
|
16025
|
+
//# sourceMappingURL=copilotkit-DDReN1Px.mjs.map
|