@copilotkit/react-core 1.80.0 → 1.81.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-D-OkjUpU.cjs +3807 -0
- package/dist/MarkdownSurfaces-D-OkjUpU.cjs.map +1 -0
- package/dist/MarkdownSurfaces-L67964_B.mjs +3522 -0
- package/dist/MarkdownSurfaces-L67964_B.mjs.map +1 -0
- package/dist/{copilotkit-CWOSXhRO.d.mts → copilotkit-BEcaM4L4.d.mts} +25 -34
- package/dist/copilotkit-BEcaM4L4.d.mts.map +1 -0
- package/dist/{copilotkit-DKICi3nC.cjs → copilotkit-BjllYYjw.cjs} +2022 -600
- package/dist/copilotkit-BjllYYjw.cjs.map +1 -0
- package/dist/{copilotkit-Dfw9HzO9.d.cts → copilotkit-D9jIImy9.d.cts} +25 -34
- package/dist/copilotkit-D9jIImy9.d.cts.map +1 -0
- package/dist/{copilotkit-BNLtgOyD.mjs → copilotkit-fKrKqoiP.mjs} +1966 -493
- package/dist/copilotkit-fKrKqoiP.mjs.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 +4463 -9
- 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/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 +4832 -180
- 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-L67964_B.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;
|
|
@@ -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.81.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;
|
|
@@ -3207,108 +2858,1908 @@ function getOperationSurfaceId(operation) {
|
|
|
3207
2858
|
}
|
|
3208
2859
|
|
|
3209
2860
|
//#endregion
|
|
3210
|
-
//#region src/v2/
|
|
3211
|
-
|
|
3212
|
-
|
|
2861
|
+
//#region src/v2/a2ui/A2UIToolCallRenderer.tsx
|
|
2862
|
+
/**
|
|
2863
|
+
* Tool name used by the dynamic A2UI generation secondary LLM.
|
|
2864
|
+
*/
|
|
2865
|
+
const RENDER_A2UI_TOOL_NAME = "render_a2ui";
|
|
2866
|
+
/**
|
|
2867
|
+
* Registers a no-op renderer for the `render_a2ui` tool call so its raw streamed
|
|
2868
|
+
* args are never surfaced in the transcript.
|
|
2869
|
+
*
|
|
2870
|
+
* The generation skeleton / retry / failure UX is NO LONGER owned here (OSS-162):
|
|
2871
|
+
* the A2UI middleware drives the whole lifecycle on the `a2ui-surface` activity
|
|
2872
|
+
* (one stable messageId, building → retrying → failed → painted), rendered in
|
|
2873
|
+
* place by `createA2UIMessageRenderer`. Owning a skeleton per tool call caused a
|
|
2874
|
+
* duplicate skeleton on retries / multi-call generations and a skeleton that
|
|
2875
|
+
* lingered after the surface painted — both fixed by retiring it here.
|
|
2876
|
+
*
|
|
2877
|
+
* Users can still override with their own `useRenderTool({ name: "render_a2ui" })`
|
|
2878
|
+
* (hook-based entries take priority over this prop-based registration).
|
|
2879
|
+
*/
|
|
2880
|
+
function A2UIBuiltInToolCallRenderer() {
|
|
2881
|
+
const { copilotkit } = useCopilotKit$1();
|
|
2882
|
+
useEffect(() => {
|
|
2883
|
+
const renderer = defineToolCallRenderer({
|
|
2884
|
+
name: RENDER_A2UI_TOOL_NAME,
|
|
2885
|
+
args: z.any(),
|
|
2886
|
+
render: () => /* @__PURE__ */ jsx(Fragment$1, {})
|
|
2887
|
+
});
|
|
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), [catalog]);
|
|
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
|
+
};
|
|
3213
4283
|
return {
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
...def.agentId ? { agentId: def.agentId } : {},
|
|
3218
|
-
...def.group ? { group: true } : {}
|
|
4284
|
+
transport: "tool",
|
|
4285
|
+
includeCatalog: true,
|
|
4286
|
+
contextSent: false
|
|
3219
4287
|
};
|
|
3220
4288
|
}
|
|
3221
|
-
|
|
3222
|
-
//#endregion
|
|
3223
|
-
//#region src/v2/a2ui/A2UIToolCallRenderer.tsx
|
|
3224
|
-
/**
|
|
3225
|
-
* Tool name used by the dynamic A2UI generation secondary LLM.
|
|
3226
|
-
*/
|
|
3227
|
-
const RENDER_A2UI_TOOL_NAME = "render_a2ui";
|
|
3228
4289
|
/**
|
|
3229
|
-
*
|
|
3230
|
-
*
|
|
3231
|
-
*
|
|
3232
|
-
* The generation skeleton / retry / failure UX is NO LONGER owned here (OSS-162):
|
|
3233
|
-
* the A2UI middleware drives the whole lifecycle on the `a2ui-surface` activity
|
|
3234
|
-
* (one stable messageId, building → retrying → failed → painted), rendered in
|
|
3235
|
-
* place by `createA2UIMessageRenderer`. Owning a skeleton per tool call caused a
|
|
3236
|
-
* duplicate skeleton on retries / multi-call generations and a skeleton that
|
|
3237
|
-
* lingered after the surface painted — both fixed by retiring it here.
|
|
3238
|
-
*
|
|
3239
|
-
* Users can still override with their own `useRenderTool({ name: "render_a2ui" })`
|
|
3240
|
-
* (hook-based entries take priority over this prop-based registration).
|
|
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.
|
|
3241
4292
|
*/
|
|
3242
|
-
function
|
|
3243
|
-
const
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
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
|
+
}
|
|
3249
4350
|
});
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
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,
|
|
@@ -7605,7 +9064,10 @@ function CopilotChatAssistantMessage({ message, messages, isRunning, isLatest, o
|
|
|
7605
9064
|
}
|
|
7606
9065
|
};
|
|
7607
9066
|
};
|
|
7608
|
-
const boundMarkdownRenderer = renderSlot(markdownRenderer, CopilotChatAssistantMessage.MarkdownRenderer, {
|
|
9067
|
+
const boundMarkdownRenderer = renderSlot(markdownRenderer, CopilotChatAssistantMessage.MarkdownRenderer, {
|
|
9068
|
+
content: message.content || "",
|
|
9069
|
+
messageId: message.id
|
|
9070
|
+
});
|
|
7609
9071
|
const boundCopyButton = renderSlot(copyButton, CopilotChatAssistantMessage.CopyButton, { onClick: async () => {
|
|
7610
9072
|
if (message.content) return await copyToClipboard(message.content);
|
|
7611
9073
|
return false;
|
|
@@ -7715,11 +9177,19 @@ function CopilotChatAssistantMessage({ message, messages, isRunning, isLatest, o
|
|
|
7715
9177
|
});
|
|
7716
9178
|
}
|
|
7717
9179
|
(function(_CopilotChatAssistantMessage) {
|
|
7718
|
-
_CopilotChatAssistantMessage.MarkdownRenderer = ({ content, className, ...props }) =>
|
|
7719
|
-
|
|
7720
|
-
|
|
7721
|
-
|
|
7722
|
-
|
|
9180
|
+
_CopilotChatAssistantMessage.MarkdownRenderer = ({ content, className, messageId, ...props }) => {
|
|
9181
|
+
if (useGenerativeUIRuntime()?.transport === "markdown" && messageId !== void 0) return /* @__PURE__ */ jsx(MarkdownSurfaces, {
|
|
9182
|
+
content: content ?? "",
|
|
9183
|
+
messageId,
|
|
9184
|
+
className,
|
|
9185
|
+
...props
|
|
9186
|
+
});
|
|
9187
|
+
return /* @__PURE__ */ jsx(Streamdown, {
|
|
9188
|
+
className,
|
|
9189
|
+
...props,
|
|
9190
|
+
children: content ?? ""
|
|
9191
|
+
});
|
|
9192
|
+
};
|
|
7723
9193
|
_CopilotChatAssistantMessage.Toolbar = ({ className, ...props }) => /* @__PURE__ */ jsx("div", {
|
|
7724
9194
|
"data-testid": "copilot-assistant-toolbar",
|
|
7725
9195
|
className: twMerge("cpk:w-full cpk:bg-transparent cpk:flex cpk:items-center cpk:-ml-[5px] cpk:-mt-[0px]", className),
|
|
@@ -10655,7 +12125,7 @@ function useInspectorThreadOverride(args) {
|
|
|
10655
12125
|
|
|
10656
12126
|
//#endregion
|
|
10657
12127
|
//#region src/v2/components/chat/CopilotChat.tsx
|
|
10658
|
-
function CopilotChat({ agentId, threadId, labels, inspectorTools, chatView, isModalDefaultOpen, attachments: attachmentsConfig, onError, throttleMs, ...props }) {
|
|
12128
|
+
function CopilotChat({ agentId, threadId, labels, inspectorTools, chatView, isModalDefaultOpen, attachments: attachmentsConfig, onError, throttleMs, generativeUISurface, ...props }) {
|
|
10659
12129
|
const existingConfig = useCopilotChatConfiguration();
|
|
10660
12130
|
const inspector = useCopilotKitInspector();
|
|
10661
12131
|
const inspectorContextValue = useMemo(() => ({
|
|
@@ -11334,7 +12804,10 @@ function CopilotChat({ agentId, threadId, labels, inspectorTools, chatView, isMo
|
|
|
11334
12804
|
value: lastUserMessageState,
|
|
11335
12805
|
children: /* @__PURE__ */ jsx(CopilotKitInspectorContextProvider, {
|
|
11336
12806
|
value: inspectorContextValue,
|
|
11337
|
-
children:
|
|
12807
|
+
children: /* @__PURE__ */ jsx(GenerativeUIChatSlotContext.Provider, {
|
|
12808
|
+
value: generativeUISurface,
|
|
12809
|
+
children: RenderedChatView
|
|
12810
|
+
})
|
|
11338
12811
|
})
|
|
11339
12812
|
})
|
|
11340
12813
|
]
|
|
@@ -14483,5 +15956,5 @@ function validateProps(props) {
|
|
|
14483
15956
|
}
|
|
14484
15957
|
|
|
14485
15958
|
//#endregion
|
|
14486
|
-
export { INTERRUPT_EVENT_NAME as $,
|
|
14487
|
-
//# sourceMappingURL=copilotkit-
|
|
15959
|
+
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 };
|
|
15960
|
+
//# sourceMappingURL=copilotkit-fKrKqoiP.mjs.map
|