@copilotkit/vue 1.67.0 → 1.68.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.
Files changed (27) hide show
  1. package/PARITY.md +2 -2
  2. package/dist/index.cjs +1 -1
  3. package/dist/index.mjs +2 -2
  4. package/dist/{use-render-activity-message-CaArNmtw.js → use-render-activity-message-DljRBrXN.js} +3401 -3370
  5. package/dist/use-render-activity-message-DljRBrXN.js.map +1 -0
  6. package/dist/use-render-activity-message-bkrPa-92.cjs +85 -0
  7. package/dist/use-render-activity-message-bkrPa-92.cjs.map +1 -0
  8. package/dist/v2/components/chat/CopilotChat.vue.d.ts.map +1 -1
  9. package/dist/v2/components/chat/CopilotChatMessageView.vue.d.ts.map +1 -1
  10. package/dist/v2/hooks/use-agent.d.ts +66 -5
  11. package/dist/v2/hooks/use-agent.d.ts.map +1 -1
  12. package/dist/v2/index.cjs +1 -1
  13. package/dist/v2/index.mjs +1 -1
  14. package/package.json +5 -5
  15. package/src/v2/components/chat/CopilotChat.vue +14 -1
  16. package/src/v2/components/chat/CopilotChatMessageView.vue +5 -7
  17. package/src/v2/components/chat/__tests__/CopilotChat.clearOnFresh.test.ts +14 -25
  18. package/src/v2/components/chat/__tests__/CopilotChat.slots.e2e.test.ts +1 -2
  19. package/src/v2/components/chat/__tests__/CopilotChat.test.ts +2 -3
  20. package/src/v2/components/chat/__tests__/CopilotChatActivityRendering.e2e.test.ts +6 -6
  21. package/src/v2/components/chat/__tests__/MCPAppsUiMessage.e2e.test.ts +14 -0
  22. package/src/v2/hooks/__tests__/use-agent-thread-pinning.test.ts +179 -0
  23. package/src/v2/hooks/use-agent.ts +205 -78
  24. package/dist/use-render-activity-message-CNbp9Fob.cjs +0 -85
  25. package/dist/use-render-activity-message-CNbp9Fob.cjs.map +0 -1
  26. package/dist/use-render-activity-message-CaArNmtw.js.map +0 -1
  27. package/src/v2/hooks/__tests__/use-agent-thread-isolation.test.ts +0 -433
@@ -1 +1 @@
1
- {"version":3,"file":"CopilotChat.vue.d.ts","sourceRoot":"","sources":["../../../../src/v2/components/chat/CopilotChat.vue"],"names":[],"mappings":"AAkzBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAiBnD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,KAAK,EACV,yBAAyB,EACzB,gBAAgB,EAChB,6BAA6B,EAC7B,kCAAkC,EAClC,gCAAgC,EAChC,iCAAiC,EAClC,MAAM,SAAS,CAAC;AAcjB,KAAK,WAAW,GAAG;IACjB,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,gCAAgC,KAAK,OAAO,CAAC;IACnE,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE;QACvB,QAAQ,EAAE,OAAO,EAAE,CAAC;QACpB,SAAS,EAAE,OAAO,CAAC;KACpB,KAAK,OAAO,CAAC;IACd,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,6BAA6B,KAAK,OAAO,CAAC;IAC9D,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,yBAAyB,KAAK,OAAO,CAAC;IACtD,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,kCAAkC,KAAK,OAAO,CAAC;IAC3E,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,iCAAiC,KAAK,OAAO,CAAC;IACzE,iBAAiB,CAAC,EAAE,MAAM,OAAO,CAAC;IAElC,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,SAAS,CAAC;CACtD,CAAC;AA2yBF,QAAA,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;6EAQnB,CAAC;wBACkB,eAAe,CAAC,OAAO,eAAe,EAAE,WAAW,CAAC;AAAzE,wBAA0E;AAa1E,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KAEV,CAAA;CACD,CAAC"}
1
+ {"version":3,"file":"CopilotChat.vue.d.ts","sourceRoot":"","sources":["../../../../src/v2/components/chat/CopilotChat.vue"],"names":[],"mappings":"AA+zBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAiBnD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,KAAK,EACV,yBAAyB,EACzB,gBAAgB,EAChB,6BAA6B,EAC7B,kCAAkC,EAClC,gCAAgC,EAChC,iCAAiC,EAClC,MAAM,SAAS,CAAC;AAcjB,KAAK,WAAW,GAAG;IACjB,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,gCAAgC,KAAK,OAAO,CAAC;IACnE,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE;QACvB,QAAQ,EAAE,OAAO,EAAE,CAAC;QACpB,SAAS,EAAE,OAAO,CAAC;KACpB,KAAK,OAAO,CAAC;IACd,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,6BAA6B,KAAK,OAAO,CAAC;IAC9D,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,yBAAyB,KAAK,OAAO,CAAC;IACtD,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,kCAAkC,KAAK,OAAO,CAAC;IAC3E,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,iCAAiC,KAAK,OAAO,CAAC;IACzE,iBAAiB,CAAC,EAAE,MAAM,OAAO,CAAC;IAElC,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,SAAS,CAAC;CACtD,CAAC;AAwzBF,QAAA,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;6EAQnB,CAAC;wBACkB,eAAe,CAAC,OAAO,eAAe,EAAE,WAAW,CAAC;AAAzE,wBAA0E;AAa1E,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KAEV,CAAA;CACD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"CopilotChatMessageView.vue.d.ts","sourceRoot":"","sources":["../../../../src/v2/components/chat/CopilotChatMessageView.vue"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"CopilotChatMessageView.vue.d.ts","sourceRoot":"","sources":["../../../../src/v2/components/chat/CopilotChatMessageView.vue"],"names":[],"mappings":"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"}
@@ -5,9 +5,7 @@ export declare enum UseAgentUpdate {
5
5
  OnStateChanged = "OnStateChanged",
6
6
  OnRunStatusChanged = "OnRunStatusChanged"
7
7
  }
8
- export interface UseAgentProps {
9
- agentId?: MaybeRefOrGetter<string | undefined>;
10
- threadId?: MaybeRefOrGetter<string | undefined>;
8
+ interface UseAgentPropsBase {
11
9
  updates?: UseAgentUpdate[];
12
10
  /**
13
11
  * Throttle interval (in milliseconds) for re-renders triggered by
@@ -33,8 +31,70 @@ export interface UseAgentProps {
33
31
  */
34
32
  throttleMs?: MaybeRefOrGetter<number | undefined>;
35
33
  }
36
- export declare const globalThreadCloneMap: WeakMap<AbstractAgent, Map<string, AbstractAgent>>;
37
- export declare function getThreadClone(registryAgent: AbstractAgent | undefined | null, threadId: string | undefined | null): AbstractAgent | undefined;
34
+ /**
35
+ * Thread-scoped variant. `agentId`, `runtimeAgentId` and `threadId` are a matched
36
+ * set: together they give this hook a private proxied agent — registered under the
37
+ * local `agentId`, routing outbound to `runtimeAgentId` — that is safe to pin a
38
+ * thread onto. Mirrors React's `UseAgentThreadScopedProps`.
39
+ */
40
+ interface UseAgentThreadScopedProps {
41
+ /**
42
+ * The *local* registry id to register this hook's proxied agent under. Required
43
+ * here: the usual fallbacks (chat configuration, then `DEFAULT_AGENT_ID`) name
44
+ * agents that already exist, and registering over one of those throws.
45
+ */
46
+ agentId: MaybeRefOrGetter<string>;
47
+ /**
48
+ * The runtime agent to route outbound requests to while this hook exposes a
49
+ * distinct local `agentId`. Registers a proxied agent via
50
+ * `CopilotKitCore.registerProxiedAgent`, so several frontend agents (e.g. one
51
+ * per open thread) can mount against one runtime agent.
52
+ *
53
+ * REQUIRES `threadId` — a private agent with no thread to scope behaves like
54
+ * the shared one, minus a registration and a local id to keep unique.
55
+ */
56
+ runtimeAgentId: MaybeRefOrGetter<string>;
57
+ /**
58
+ * Thread to scope the agent's run to. Written onto the underlying agent, so
59
+ * `/agent/run`, `/agent/connect` and `/agent/stop` address this thread.
60
+ *
61
+ * REQUIRES `runtimeAgentId` — an agent resolved by `agentId` alone is shared,
62
+ * so a per-hook thread written onto it would clobber every other holder.
63
+ */
64
+ threadId: MaybeRefOrGetter<string>;
65
+ }
66
+ /**
67
+ * Default variant: no thread scoping. Binds to the shared agent registered under
68
+ * `agentId` and takes its thread from the surrounding chat configuration, gated
69
+ * on `hasExplicitThreadId`. Mirrors React's `UseAgentUnscopedProps`.
70
+ *
71
+ * `threadId` and `runtimeAgentId` are typed `undefined` rather than omitted so
72
+ * that supplying either alone matches *neither* branch — that is the type-level
73
+ * enforcement of the all-or-nothing rule.
74
+ */
75
+ interface UseAgentUnscopedProps {
76
+ /**
77
+ * Agent to bind to. Resolution precedence: this property, then the surrounding
78
+ * chat configuration's agentId, then the global default.
79
+ */
80
+ agentId?: MaybeRefOrGetter<string | undefined>;
81
+ /** Requires `runtimeAgentId`. See {@link UseAgentThreadScopedProps.threadId}. */
82
+ threadId?: undefined;
83
+ /** Requires `threadId`. See {@link UseAgentThreadScopedProps.runtimeAgentId}. */
84
+ runtimeAgentId?: undefined;
85
+ }
86
+ /**
87
+ * Props for {@link useAgent}. Two valid shapes, nothing in between:
88
+ *
89
+ * - **Bind to an agent** — `useAgent()`, `useAgent({ agentId })`. The shared
90
+ * registry instance; the thread comes from the chat configuration.
91
+ * - **Bind a private agent to a thread** —
92
+ * `useAgent({ agentId, runtimeAgentId, threadId })`. All three required.
93
+ *
94
+ * So `{ agentId, threadId }`, `{ agentId, runtimeAgentId }` and
95
+ * `{ runtimeAgentId, threadId }` are all compile errors, matching React.
96
+ */
97
+ export type UseAgentProps = UseAgentPropsBase & (UseAgentThreadScopedProps | UseAgentUnscopedProps);
38
98
  /**
39
99
  * Resolves and subscribes to a CopilotKit agent for the current Vue scope.
40
100
  *
@@ -50,4 +110,5 @@ export declare function getThreadClone(registryAgent: AbstractAgent | undefined
50
110
  export declare function useAgent(props?: UseAgentProps): {
51
111
  agent: import("vue").ShallowRef<AbstractAgent | null, AbstractAgent | null>;
52
112
  };
113
+ export {};
53
114
  //# sourceMappingURL=use-agent.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-agent.d.ts","sourceRoot":"","sources":["../../../src/v2/hooks/use-agent.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,KAAK,CAAC;AAG5C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAYnD,oBAAY,cAAc;IACxB,iBAAiB,sBAAsB;IACvC,cAAc,mBAAmB;IACjC,kBAAkB,uBAAuB;CAC1C;AAQD,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,gBAAgB,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAC/C,QAAQ,CAAC,EAAE,gBAAgB,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAChD,OAAO,CAAC,EAAE,cAAc,EAAE,CAAC;IAC3B;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,UAAU,CAAC,EAAE,gBAAgB,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;CACnD;AAwBD,eAAO,MAAM,oBAAoB,oDAG9B,CAAC;AAEJ,wBAAgB,cAAc,CAC5B,aAAa,EAAE,aAAa,GAAG,SAAS,GAAG,IAAI,EAC/C,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAClC,aAAa,GAAG,SAAS,CAG3B;AA2BD;;;;;;;;;;;GAWG;AACH,wBAAgB,QAAQ,CAAC,KAAK,GAAE,aAAkB;;EA0NjD"}
1
+ {"version":3,"file":"use-agent.d.ts","sourceRoot":"","sources":["../../../src/v2/hooks/use-agent.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,KAAK,CAAC;AAG5C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAYnD,oBAAY,cAAc;IACxB,iBAAiB,sBAAsB;IACvC,cAAc,mBAAmB;IACjC,kBAAkB,uBAAuB;CAC1C;AAQD,UAAU,iBAAiB;IACzB,OAAO,CAAC,EAAE,cAAc,EAAE,CAAC;IAC3B;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,UAAU,CAAC,EAAE,gBAAgB,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;CACnD;AAED;;;;;GAKG;AACH,UAAU,yBAAyB;IACjC;;;;OAIG;IACH,OAAO,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAClC;;;;;;;;OAQG;IACH,cAAc,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACzC;;;;;;OAMG;IACH,QAAQ,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC;CACpC;AAED;;;;;;;;GAQG;AACH,UAAU,qBAAqB;IAC7B;;;OAGG;IACH,OAAO,CAAC,EAAE,gBAAgB,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAC/C,iFAAiF;IACjF,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,iFAAiF;IACjF,cAAc,CAAC,EAAE,SAAS,CAAC;CAC5B;AAED;;;;;;;;;;GAUG;AACH,MAAM,MAAM,aAAa,GAAG,iBAAiB,GAC3C,CAAC,yBAAyB,GAAG,qBAAqB,CAAC,CAAC;AAEtD;;;;;;;;;;;GAWG;AACH,wBAAgB,QAAQ,CAAC,KAAK,GAAE,aAAkB;;EAmVjD"}
package/dist/v2/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("@copilotkit/core"),i=require("@ag-ui/client"),e=require("../use-render-activity-message-CNbp9Fob.cjs"),n=require("@copilotkit/shared");exports.A2UIActivityContentSchema=e.A2UIActivityContentSchema;exports.A2UISurfaceActivityRenderer=e._sfc_main;exports.A2UISurfaceActivityType=e.A2UISurfaceActivityType;exports.CopilotChat=e.CopilotChat;exports.CopilotChatAssistantMessage=e._sfc_main$1;exports.CopilotChatAttachmentQueue=e._sfc_main$2;exports.CopilotChatAttachmentRenderer=e._sfc_main$3;exports.CopilotChatAudioRecorder=e._sfc_main$4;exports.CopilotChatConfigurationProvider=e._sfc_main$5;exports.CopilotChatDefaultLabels=e.CopilotChatDefaultLabels;exports.CopilotChatInput=e._sfc_main$6;exports.CopilotChatMessageView=e._sfc_main$7;exports.CopilotChatReasoningMessage=e._sfc_main$8;exports.CopilotChatSuggestionPill=e._sfc_main$9;exports.CopilotChatSuggestionView=e._sfc_main$10;exports.CopilotChatToggleButton=e.CopilotChatToggleButton;exports.CopilotChatToggleButtonCloseIcon=e.CopilotChatToggleButtonCloseIcon;exports.CopilotChatToggleButtonOpenIcon=e.CopilotChatToggleButtonOpenIcon;exports.CopilotChatToolCallsView=e._sfc_main$11;exports.CopilotChatUserMessage=e._sfc_main$12;exports.CopilotChatView=e._sfc_main$13;exports.CopilotKitCoreVue=e.CopilotKitCoreVue;exports.CopilotKitInspector=e._sfc_main$14;exports.CopilotKitProvider=e._sfc_main$15;exports.CopilotModalHeader=e.CopilotModalHeader;exports.CopilotPopup=e._sfc_main$16;exports.CopilotPopupView=e.CopilotPopupView;exports.CopilotSidebar=e._sfc_main$17;exports.CopilotSidebarView=e.CopilotSidebarView;exports.CopilotThreadsDrawer=e._sfc_main$18;exports.GenerateSandboxedUiArgsSchema=e.GenerateSandboxedUiArgsSchema;exports.LicenseContextKey=e.LicenseContextKey;exports.MCPAppsActivityContentSchema=e.MCPAppsActivityContentSchema;exports.MCPAppsActivityRenderer=e.MCPAppsActivityRenderer;exports.MCPAppsActivityType=e.MCPAppsActivityType;exports.OpenGenerativeUIActivityRenderer=e.OpenGenerativeUIActivityRenderer;exports.OpenGenerativeUIActivityType=e.OpenGenerativeUIActivityType;exports.OpenGenerativeUIContentSchema=e.OpenGenerativeUIContentSchema;exports.OpenGenerativeUIRenderer=e.OpenGenerativeUIRenderer;exports.OpenGenerativeUIToolRenderer=e.OpenGenerativeUIToolRenderer;exports.UseAgentUpdate=e.UseAgentUpdate;exports.createA2UIMessageRenderer=e.createA2UIMessageRenderer;exports.createDefaultLicenseRef=e.createDefaultLicenseRef;exports.defineToolCallRenderer=e.defineToolCallRenderer;exports.extractCompleteStyles=e.extractCompleteStyles;exports.getOperationSurfaceId=e.getOperationSurfaceId;exports.processPartialHtml=e.processPartialHtml;exports.useAgent=e.useAgent;exports.useAgentContext=e.useAgentContext;exports.useAttachments=e.useAttachments;exports.useCapabilities=e.useCapabilities;exports.useComponent=e.useComponent;exports.useConfigureSuggestions=e.useConfigureSuggestions;exports.useCopilotChatConfiguration=e.useCopilotChatConfiguration;exports.useCopilotKit=e.useCopilotKit;exports.useDefaultRenderTool=e.useDefaultRenderTool;exports.useFrontendTool=e.useFrontendTool;exports.useHumanInTheLoop=e.useHumanInTheLoop;exports.useInterrupt=e.useInterrupt;exports.useKatexStyles=e.useKatexStyles;exports.useKeyboardHeight=e.useKeyboardHeight;exports.useLicenseContext=e.useLicenseContext;exports.useRenderActivityMessage=e.useRenderActivityMessage;exports.useRenderCustomMessages=e.useRenderCustomMessages;exports.useRenderTool=e.useRenderTool;exports.useSandboxFunctions=e.useSandboxFunctions;exports.useSuggestions=e.useSuggestions;exports.useThreads=e.useThreads;exports.vueBasicCatalog=e.vueBasicCatalog;Object.defineProperty(exports,"createLicenseContextValue",{enumerable:!0,get:()=>n.createLicenseContextValue});Object.keys(o).forEach(t=>{t!=="default"&&!Object.prototype.hasOwnProperty.call(exports,t)&&Object.defineProperty(exports,t,{enumerable:!0,get:()=>o[t]})});Object.keys(i).forEach(t=>{t!=="default"&&!Object.prototype.hasOwnProperty.call(exports,t)&&Object.defineProperty(exports,t,{enumerable:!0,get:()=>i[t]})});
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("@copilotkit/core"),i=require("@ag-ui/client"),e=require("../use-render-activity-message-bkrPa-92.cjs"),n=require("@copilotkit/shared");exports.A2UIActivityContentSchema=e.A2UIActivityContentSchema;exports.A2UISurfaceActivityRenderer=e._sfc_main;exports.A2UISurfaceActivityType=e.A2UISurfaceActivityType;exports.CopilotChat=e.CopilotChat;exports.CopilotChatAssistantMessage=e._sfc_main$1;exports.CopilotChatAttachmentQueue=e._sfc_main$2;exports.CopilotChatAttachmentRenderer=e._sfc_main$3;exports.CopilotChatAudioRecorder=e._sfc_main$4;exports.CopilotChatConfigurationProvider=e._sfc_main$5;exports.CopilotChatDefaultLabels=e.CopilotChatDefaultLabels;exports.CopilotChatInput=e._sfc_main$6;exports.CopilotChatMessageView=e._sfc_main$7;exports.CopilotChatReasoningMessage=e._sfc_main$8;exports.CopilotChatSuggestionPill=e._sfc_main$9;exports.CopilotChatSuggestionView=e._sfc_main$10;exports.CopilotChatToggleButton=e.CopilotChatToggleButton;exports.CopilotChatToggleButtonCloseIcon=e.CopilotChatToggleButtonCloseIcon;exports.CopilotChatToggleButtonOpenIcon=e.CopilotChatToggleButtonOpenIcon;exports.CopilotChatToolCallsView=e._sfc_main$11;exports.CopilotChatUserMessage=e._sfc_main$12;exports.CopilotChatView=e._sfc_main$13;exports.CopilotKitCoreVue=e.CopilotKitCoreVue;exports.CopilotKitInspector=e._sfc_main$14;exports.CopilotKitProvider=e._sfc_main$15;exports.CopilotModalHeader=e.CopilotModalHeader;exports.CopilotPopup=e._sfc_main$16;exports.CopilotPopupView=e.CopilotPopupView;exports.CopilotSidebar=e._sfc_main$17;exports.CopilotSidebarView=e.CopilotSidebarView;exports.CopilotThreadsDrawer=e._sfc_main$18;exports.GenerateSandboxedUiArgsSchema=e.GenerateSandboxedUiArgsSchema;exports.LicenseContextKey=e.LicenseContextKey;exports.MCPAppsActivityContentSchema=e.MCPAppsActivityContentSchema;exports.MCPAppsActivityRenderer=e.MCPAppsActivityRenderer;exports.MCPAppsActivityType=e.MCPAppsActivityType;exports.OpenGenerativeUIActivityRenderer=e.OpenGenerativeUIActivityRenderer;exports.OpenGenerativeUIActivityType=e.OpenGenerativeUIActivityType;exports.OpenGenerativeUIContentSchema=e.OpenGenerativeUIContentSchema;exports.OpenGenerativeUIRenderer=e.OpenGenerativeUIRenderer;exports.OpenGenerativeUIToolRenderer=e.OpenGenerativeUIToolRenderer;exports.UseAgentUpdate=e.UseAgentUpdate;exports.createA2UIMessageRenderer=e.createA2UIMessageRenderer;exports.createDefaultLicenseRef=e.createDefaultLicenseRef;exports.defineToolCallRenderer=e.defineToolCallRenderer;exports.extractCompleteStyles=e.extractCompleteStyles;exports.getOperationSurfaceId=e.getOperationSurfaceId;exports.processPartialHtml=e.processPartialHtml;exports.useAgent=e.useAgent;exports.useAgentContext=e.useAgentContext;exports.useAttachments=e.useAttachments;exports.useCapabilities=e.useCapabilities;exports.useComponent=e.useComponent;exports.useConfigureSuggestions=e.useConfigureSuggestions;exports.useCopilotChatConfiguration=e.useCopilotChatConfiguration;exports.useCopilotKit=e.useCopilotKit;exports.useDefaultRenderTool=e.useDefaultRenderTool;exports.useFrontendTool=e.useFrontendTool;exports.useHumanInTheLoop=e.useHumanInTheLoop;exports.useInterrupt=e.useInterrupt;exports.useKatexStyles=e.useKatexStyles;exports.useKeyboardHeight=e.useKeyboardHeight;exports.useLicenseContext=e.useLicenseContext;exports.useRenderActivityMessage=e.useRenderActivityMessage;exports.useRenderCustomMessages=e.useRenderCustomMessages;exports.useRenderTool=e.useRenderTool;exports.useSandboxFunctions=e.useSandboxFunctions;exports.useSuggestions=e.useSuggestions;exports.useThreads=e.useThreads;exports.vueBasicCatalog=e.vueBasicCatalog;Object.defineProperty(exports,"createLicenseContextValue",{enumerable:!0,get:()=>n.createLicenseContextValue});Object.keys(o).forEach(t=>{t!=="default"&&!Object.prototype.hasOwnProperty.call(exports,t)&&Object.defineProperty(exports,t,{enumerable:!0,get:()=>o[t]})});Object.keys(i).forEach(t=>{t!=="default"&&!Object.prototype.hasOwnProperty.call(exports,t)&&Object.defineProperty(exports,t,{enumerable:!0,get:()=>i[t]})});
2
2
  //# sourceMappingURL=index.cjs.map
package/dist/v2/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  export * from "@copilotkit/core";
2
2
  export * from "@ag-ui/client";
3
- import { A as o, _ as i, a as n, C, b as r, c as p, d as l, e as u, f as c, g, h as d, i as h, j as A, k as v, l as S, m, n as y, o as I, p as f, q as R, r as T, s as U, t as x, u as M, v as P, w as b, x as V, y as w, z as K, B as O, G, L, M as B, D, E as H, O as F, F as Q, H as j, I as k, J as q, U as z, K as E, N as J, P as N, Q as W, R as X, S as Y, T as Z, V as _, W as $, X as ee, Y as ae, Z as te, $ as se, a0 as oe, a1 as ie, a2 as ne, a3 as Ce, a4 as re, a5 as pe, a6 as le, a7 as ue, a8 as ce, a9 as ge, aa as de, ab as he, ac as Ae, ad as ve, ae as Se } from "../use-render-activity-message-CaArNmtw.js";
3
+ import { A as o, _ as i, a as n, C, b as r, c as p, d as l, e as u, f as c, g, h as d, i as h, j as A, k as v, l as S, m, n as y, o as I, p as f, q as R, r as T, s as U, t as x, u as M, v as P, w as b, x as V, y as w, z as K, B as O, G, L, M as B, D, E as H, O as F, F as Q, H as j, I as k, J as q, U as z, K as E, N as J, P as N, Q as W, R as X, S as Y, T as Z, V as _, W as $, X as ee, Y as ae, Z as te, $ as se, a0 as oe, a1 as ie, a2 as ne, a3 as Ce, a4 as re, a5 as pe, a6 as le, a7 as ue, a8 as ce, a9 as ge, aa as de, ab as he, ac as Ae, ad as ve, ae as Se } from "../use-render-activity-message-DljRBrXN.js";
4
4
  import { createLicenseContextValue as ye } from "@copilotkit/shared";
5
5
  export {
6
6
  o as A2UIActivityContentSchema,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@copilotkit/vue",
3
- "version": "1.67.0",
3
+ "version": "1.68.0",
4
4
  "private": false,
5
5
  "description": "Vue 3 components and composables for CopilotKit",
6
6
  "keywords": [
@@ -70,10 +70,10 @@
70
70
  "streamdown-vue": "^1.0.29",
71
71
  "zod": "^3.25.75",
72
72
  "zod-to-json-schema": "^3.24.5",
73
- "@copilotkit/core": "1.67.0",
74
- "@copilotkit/web-components": "1.67.0",
75
- "@copilotkit/shared": "1.67.0",
76
- "@copilotkit/web-inspector": "1.67.0"
73
+ "@copilotkit/core": "1.68.0",
74
+ "@copilotkit/shared": "1.68.0",
75
+ "@copilotkit/web-components": "1.68.0",
76
+ "@copilotkit/web-inspector": "1.68.0"
77
77
  },
78
78
  "devDependencies": {
79
79
  "@eslint/js": "^9.39.2",
@@ -141,9 +141,12 @@ const isConnecting = computed(
141
141
  const stableLabels = useShallowStableRef(computed(() => props.labels));
142
142
  const resolvedLabels = computed(() => stableLabels.value);
143
143
 
144
+ // `useAgent` takes no threadId: it pins one only from a surrounding chat
145
+ // configuration, and this call sits outside the provider rendered in this
146
+ // component's template, so it would never see the thread being rendered. The
147
+ // thread is assigned in the connect watcher below, mirroring React's CopilotChat.
144
148
  const { agent } = useAgent({
145
149
  agentId: resolvedAgentId,
146
- threadId: resolvedThreadId,
147
150
  throttleMs: computed(() => props.throttleMs),
148
151
  });
149
152
  const { suggestions: autoSuggestions } = useSuggestions({
@@ -312,6 +315,16 @@ watch(
312
315
  if (!currentAgent) {
313
316
  return;
314
317
  }
318
+
319
+ // Pin the thread this chat renders onto its agent, before anything issues a
320
+ // request. `CopilotKitCore.connectAgent` reads `agent.threadId` synchronously
321
+ // to decide whether this is a fresh restore, so a later assignment would let
322
+ // /connect address the previous thread. Assigning inside this callback — as
323
+ // React does — makes the ordering unconditional instead of depending on
324
+ // watcher scheduling. Non-explicit threads skip /connect below, but the first
325
+ // runAgent still has to ship the thread the UI is rendering.
326
+ currentAgent.threadId = threadId;
327
+
315
328
  // When the caller hasn't picked a specific thread, resolvedThreadId is
316
329
  // a UUID minted locally. The backend has never seen it, so /connect
317
330
  // would always 404 — skip the call. A real thread is only created
@@ -14,7 +14,6 @@ import type {
14
14
  InterruptRenderProps,
15
15
  VueCustomMessageRendererProps,
16
16
  } from "../../types";
17
- import { getThreadClone } from "../../hooks/use-agent";
18
17
  import { useCopilotKit } from "../../providers/useCopilotKit";
19
18
  import { useCopilotChatConfiguration } from "../../providers/useCopilotChatConfiguration";
20
19
  import CopilotChatAssistantMessage from "./CopilotChatAssistantMessage.vue";
@@ -105,9 +104,9 @@ const resolvedAgentId = computed(
105
104
  () => config.value?.agentId ?? DEFAULT_AGENT_ID,
106
105
  );
107
106
  const resolvedThreadAgent = computed(() => {
108
- const agentId = resolvedAgentId.value;
109
- const registryAgent = copilotkit.value.getAgent(agentId);
110
- return getThreadClone(registryAgent, config.value?.threadId) ?? registryAgent;
107
+ // Read the registry so this recomputes when agents are added or replaced.
108
+ void copilotkit.value.agents;
109
+ return copilotkit.value.getAgent(resolvedAgentId.value);
111
110
  });
112
111
 
113
112
  watch(
@@ -117,9 +116,8 @@ watch(
117
116
  () => copilotkit.value,
118
117
  () => copilotkit.value.runtimeConnectionStatus,
119
118
  ],
120
- ([_agentId, threadId], _prev, onCleanup) => {
121
- const registryAgent = copilotkit.value.getAgent(resolvedAgentId.value);
122
- const agent = getThreadClone(registryAgent, threadId) ?? registryAgent;
119
+ (_values, _prev, onCleanup) => {
120
+ const agent = resolvedThreadAgent.value;
123
121
  if (!agent) return;
124
122
 
125
123
  const sub = agent.subscribe({
@@ -7,7 +7,6 @@ import { useCopilotChatConfiguration } from "../../../providers/useCopilotChatCo
7
7
  import { useCopilotKit } from "../../../providers/useCopilotKit";
8
8
  import { StateCapturingAgent } from "../../../__tests__/utils/agents";
9
9
  import CopilotChat from "../CopilotChat.vue";
10
- import { getThreadClone } from "../../../hooks/use-agent";
11
10
 
12
11
  // Proves the clear-on-fresh watch introduced in CopilotChat.vue:
13
12
  // - does NOT clear messages on initial mount
@@ -17,6 +16,9 @@ import { getThreadClone } from "../../../hooks/use-agent";
17
16
  describe("CopilotChat clear-on-fresh", () => {
18
17
  it("does not clear messages on initial mount", async () => {
19
18
  const agent = new StateCapturingAgent();
19
+ // Spy before mount: attaching afterwards can never observe a mount-time
20
+ // clear, which is exactly what this test exists to rule out.
21
+ const setMessagesSpy = vi.spyOn(agent, "setMessages");
20
22
 
21
23
  let core:
22
24
  | ReturnType<typeof useCopilotKit>["copilotkit"]["value"]
@@ -49,15 +51,9 @@ describe("CopilotChat clear-on-fresh", () => {
49
51
  await flushPromises();
50
52
  await nextTick();
51
53
 
52
- const registryAgent = core?.getAgent("default");
53
- const resolvedAgent = getThreadClone(registryAgent, "seed");
54
+ const resolvedAgent = core?.getAgent("default");
54
55
  expect(resolvedAgent).toBeDefined();
55
-
56
- // Attach the spy only after mount has settled so the clone's own
57
- // construction-time `setMessages([])` reset (in `cloneForThread`,
58
- // unrelated to the clear-on-fresh watch) isn't mistaken for a clear.
59
- const setMessagesSpy = vi.spyOn(resolvedAgent!, "setMessages");
60
- await nextTick();
56
+ expect(setMessagesSpy).not.toHaveBeenCalled();
61
57
 
62
58
  expect(setMessagesSpy).not.toHaveBeenCalled();
63
59
  });
@@ -110,7 +106,7 @@ describe("CopilotChat clear-on-fresh", () => {
110
106
  await nextTick();
111
107
 
112
108
  const registryAgent = core?.getAgent("default");
113
- const seedAgent = getThreadClone(registryAgent, "seed");
109
+ const seedAgent = registryAgent;
114
110
  expect(seedAgent).toBeDefined();
115
111
  expect(currentThreadId).toBe("seed");
116
112
 
@@ -122,19 +118,15 @@ describe("CopilotChat clear-on-fresh", () => {
122
118
  expect(currentThreadId).toBeDefined();
123
119
  expect(currentThreadId).not.toBe("seed");
124
120
  const newAgentThreadId = currentThreadId!;
125
- const newAgent = getThreadClone(registryAgent, newAgentThreadId);
121
+ const newAgent = registryAgent;
126
122
  expect(newAgent).toBeDefined();
127
- expect(newAgent).not.toBe(seedAgent);
128
123
 
129
- // Primary, behavioral assertion: the new agent ends with no messages
130
- // after the fresh switch (this alone doesn't distinguish the watch from
131
- // clone construction, since `cloneForThread` also resets to `[]`).
124
+ // The agent ends with no messages after the fresh switch. With one shared
125
+ // instance the clear-on-fresh watch is the only thing that can empty it.
132
126
  expect(newAgent!.messages).toEqual([]);
133
127
 
134
- // Move to a third, unrelated non-explicit thread so `newAgent` is no
135
- // longer the active agent, then dirty it directly (bypassing
136
- // `cloneForThread`'s construction reset entirely, since the clone
137
- // already exists in the cache).
128
+ // Move to a third, unrelated non-explicit thread, then dirty the agent
129
+ // directly so the next transition has something real to clear.
138
130
  expect(setActiveThreadId).toBeDefined();
139
131
  setActiveThreadId!("elsewhere", { explicit: false });
140
132
  await flushPromises();
@@ -144,12 +136,9 @@ describe("CopilotChat clear-on-fresh", () => {
144
136
  newAgent!.setMessages([{ id: "m1", role: "user", content: "hi" } as never]);
145
137
  expect(newAgent!.messages.length).toBe(1);
146
138
 
147
- // Switch back to `newAgent`'s thread id, non-explicitly. Because the
148
- // clone already exists in the cache, `getOrCreateThreadClone` returns it
149
- // without reconstructing it — so any `setMessages([])` observed here
150
- // must come from the clear-on-fresh watch, not from clone construction.
151
- // This fails (messages stay dirty) if the watch's
152
- // `currentAgent.setMessages([])` call is removed.
139
+ // Switch back non-explicitly. Any `setMessages([])` observed here must come
140
+ // from the clear-on-fresh watch; this fails (messages stay dirty) if the
141
+ // watch's `currentAgent.setMessages([])` call is removed.
153
142
  setActiveThreadId!(newAgentThreadId, { explicit: false });
154
143
  await flushPromises();
155
144
  await nextTick();
@@ -4,7 +4,6 @@ import { h } from "vue";
4
4
  import CopilotChat from "../CopilotChat.vue";
5
5
  import { renderWithCopilotKit } from "../../../__tests__/utils/mount";
6
6
  import { StateCapturingAgent } from "../../../__tests__/utils/agents";
7
- import { getThreadClone } from "../../../hooks/use-agent";
8
7
 
9
8
  describe("CopilotChat.slots.e2e", () => {
10
9
  it("supports full chat-view override with callback payload", async () => {
@@ -133,7 +132,7 @@ describe("CopilotChat.slots.e2e", () => {
133
132
  await flushPromises();
134
133
 
135
134
  const registryAgent = getCore().getAgent("custom-agent");
136
- const resolvedAgent = getThreadClone(registryAgent, "explicit-thread");
135
+ const resolvedAgent = registryAgent;
137
136
  expect(defaultAgent.messages).toHaveLength(0);
138
137
  expect(resolvedAgent?.threadId).toBe("explicit-thread");
139
138
  expect(resolvedAgent?.messages.some((m) => m.role === "user")).toBe(true);
@@ -9,7 +9,6 @@ import { useCopilotKit } from "../../../providers/useCopilotKit";
9
9
  import { CopilotKitCoreVue } from "../../../lib/vue-core";
10
10
  import CopilotChat from "../CopilotChat.vue";
11
11
  import CopilotChatView from "../CopilotChatView.vue";
12
- import { getThreadClone } from "../../../hooks/use-agent";
13
12
 
14
13
  function mountChat(
15
14
  props: Record<string, unknown> = {},
@@ -178,7 +177,7 @@ describe("CopilotChat", () => {
178
177
  await flushPromises();
179
178
 
180
179
  const registryAgent = core?.getAgent("custom-agent");
181
- const resolvedAgent = getThreadClone(registryAgent, "explicit-thread");
180
+ const resolvedAgent = registryAgent;
182
181
  expect(resolvedAgent?.threadId).toBe("explicit-thread");
183
182
  expect(resolvedAgent?.messages.some((m) => m.role === "user")).toBe(true);
184
183
  expect(defaultAgent.messages).toHaveLength(0);
@@ -230,7 +229,7 @@ describe("CopilotChat", () => {
230
229
  await flushPromises();
231
230
 
232
231
  const registryAgent = core?.getAgent("default");
233
- const resolvedAgent = getThreadClone(registryAgent, "stop-thread");
232
+ const resolvedAgent = registryAgent;
234
233
  const abortRun = vi.fn();
235
234
  if (registryAgent) {
236
235
  registryAgent.abortRun = abortRun;
@@ -14,7 +14,6 @@ import { IntelligenceAgent } from "@copilotkit/core";
14
14
  import CopilotChat from "../CopilotChat.vue";
15
15
  import CopilotKitProvider from "../../../providers/CopilotKitProvider.vue";
16
16
  import CopilotChatConfigurationProvider from "../../../providers/CopilotChatConfigurationProvider.vue";
17
- import { getThreadClone } from "../../../hooks/use-agent";
18
17
  import { useCopilotKit } from "../../../providers/useCopilotKit";
19
18
  import { createA2UIMessageRenderer } from "../../../components/A2UIMessageRenderer";
20
19
  import {
@@ -315,7 +314,7 @@ describe("CopilotChat activity message rendering", () => {
315
314
  expect(screen.getByTestId("copilotkit-probe").textContent).toBe("true");
316
315
  });
317
316
 
318
- it("passes the per-thread clone (not the registry agent) to activity message renderers", async () => {
317
+ it("passes the registry agent to activity message renderers", async () => {
319
318
  const agent = new MockStepwiseAgent();
320
319
  const agentId = "action-agent";
321
320
  agent.agentId = agentId;
@@ -367,10 +366,11 @@ describe("CopilotChat activity message rendering", () => {
367
366
  expect(screen.getByTestId("action-button")).toBeDefined();
368
367
  });
369
368
 
370
- const clone = getThreadClone(agent, threadId);
371
- expect(clone).toBeDefined();
372
- expect(toRaw(capturedAgent.value!)).toBe(clone);
373
- expect(toRaw(capturedAgent.value!)).not.toBe(agent);
369
+ // Thread cloning is gone: renderers get the registry agent, with the
370
+ // thread pinned onto it rather than split across per-thread copies.
371
+ expect(capturedAgent.value).toBeDefined();
372
+ expect(toRaw(capturedAgent.value!)).toBe(agent);
373
+ expect(toRaw(capturedAgent.value!).threadId).toBe(threadId);
374
374
  });
375
375
 
376
376
  it("restores a completed A2UI surface after reconnect from an event-native baseline", async () => {
@@ -53,6 +53,20 @@ class MockMCPProxyAgent extends AbstractAgent {
53
53
  await flushVueUpdates();
54
54
  }
55
55
 
56
+ // Records what the renderer sent. This instrumentation also exists in the
57
+ // `clone()` override below, which is where it used to live exclusively — back
58
+ // when `useAgent` handed components a per-thread clone. Thread cloning is gone,
59
+ // so the class records for itself; `clone()` is left intact because
60
+ // `CopilotKitCore`'s SuggestionEngine still clones agents.
61
+ addMessage(message: Parameters<AbstractAgent["addMessage"]>[0]) {
62
+ this.addMessageCalls.push({
63
+ id: message.id,
64
+ role: message.role,
65
+ content: message.content,
66
+ });
67
+ return super.addMessage(message);
68
+ }
69
+
56
70
  clone(): MockMCPProxyAgent {
57
71
  const cloned = new MockMCPProxyAgent();
58
72
  cloned.agentId = this.agentId;
@@ -0,0 +1,179 @@
1
+ import { defineComponent, ref, shallowRef, toRaw } from "vue";
2
+ import { render, cleanup } from "@testing-library/vue";
3
+ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
4
+ import { AbstractAgent } from "@ag-ui/client";
5
+ import type { BaseEvent } from "@ag-ui/client";
6
+ import { CopilotKitCoreRuntimeConnectionStatus } from "@copilotkit/core";
7
+ import { Observable } from "rxjs";
8
+ import { useCopilotKit } from "../../providers/useCopilotKit";
9
+ import { useCopilotChatConfiguration } from "../../providers/useCopilotChatConfiguration";
10
+ import { useAgent } from "../use-agent";
11
+
12
+ vi.mock("../../providers/useCopilotKit", () => ({
13
+ useCopilotKit: vi.fn(),
14
+ }));
15
+ vi.mock("../../providers/useCopilotChatConfiguration", () => ({
16
+ useCopilotChatConfiguration: vi.fn(),
17
+ }));
18
+
19
+ const mockUseCopilotKit = useCopilotKit as ReturnType<typeof vi.fn>;
20
+ const mockUseChatConfig = useCopilotChatConfiguration as ReturnType<
21
+ typeof vi.fn
22
+ >;
23
+
24
+ class SimpleAgent extends AbstractAgent {
25
+ run(): Observable<BaseEvent> {
26
+ return new Observable();
27
+ }
28
+ }
29
+
30
+ /**
31
+ * Replaces `use-agent-thread-isolation.test.ts`, which pinned the per-thread
32
+ * *cloning* `useAgent` used to do. Cloning is gone; the hook mirrors React:
33
+ * one shared instance per agentId with the chat configuration's thread pinned
34
+ * onto it (gated on `hasExplicitThreadId`), or — with the all-or-nothing
35
+ * `{ agentId, runtimeAgentId, threadId }` set — a private proxied agent.
36
+ *
37
+ * The invariant under test: never a copy, and a caller-chosen thread lands on
38
+ * the agent while an auto-minted placeholder does not.
39
+ */
40
+ describe("useAgent agent resolution", () => {
41
+ let registryAgent: SimpleAgent;
42
+ let copilotkitRef: ReturnType<typeof shallowRef>;
43
+
44
+ beforeEach(() => {
45
+ registryAgent = new SimpleAgent();
46
+ registryAgent.agentId = "my-agent";
47
+ // `shallowRef`, matching production (`CopilotKitProvider.vue` provides
48
+ // `shallowRef<CopilotKitCoreVue>`). A deep `ref` would hand the hook
49
+ // reactive proxies of the core and of every agent, so the identity
50
+ // assertions below would compare proxies rather than the real instances.
51
+ copilotkitRef = shallowRef({
52
+ getAgent: vi.fn((id: string) =>
53
+ id === "my-agent" ? registryAgent : undefined,
54
+ ),
55
+ runtimeUrl: "http://localhost:3000/api/copilotkit",
56
+ runtimeConnectionStatus: CopilotKitCoreRuntimeConnectionStatus.Connected,
57
+ runtimeTransport: "rest",
58
+ headers: {},
59
+ agents: { "my-agent": registryAgent },
60
+ defaultThrottleMs: undefined,
61
+ subscribeToAgentWithOptions: vi.fn(() => ({ unsubscribe: vi.fn() })),
62
+ });
63
+ mockUseCopilotKit.mockReturnValue({
64
+ copilotkit: copilotkitRef,
65
+ executingToolCallIds: ref(new Set()),
66
+ });
67
+ mockUseChatConfig.mockReturnValue(ref(null));
68
+ });
69
+
70
+ afterEach(() => {
71
+ cleanup();
72
+ vi.restoreAllMocks();
73
+ });
74
+
75
+ const mountProbe = () => {
76
+ let captured: AbstractAgent | null = null;
77
+ const Probe = defineComponent({
78
+ setup() {
79
+ captured = useAgent({ agentId: "my-agent" }).agent.value;
80
+ return () => null;
81
+ },
82
+ });
83
+ render(Probe);
84
+ return () => captured;
85
+ };
86
+
87
+ it("returns the registry instance itself, never a copy", () => {
88
+ const captured = mountProbe();
89
+ expect(toRaw(captured()!)).toBe(registryAgent);
90
+ });
91
+
92
+ it("returns the same instance to two hooks sharing an agentId", () => {
93
+ let first: AbstractAgent | null = null;
94
+ let second: AbstractAgent | null = null;
95
+ const Probe = defineComponent({
96
+ setup() {
97
+ first = useAgent({ agentId: "my-agent" }).agent.value;
98
+ second = useAgent({ agentId: "my-agent" }).agent.value;
99
+ return () => null;
100
+ },
101
+ });
102
+
103
+ render(Probe);
104
+
105
+ // Cloning used to make these two different objects keyed by thread.
106
+ expect(toRaw(first!)).toBe(toRaw(second!));
107
+ expect(toRaw(first!)).toBe(registryAgent);
108
+ });
109
+
110
+ it("pins the chat configuration's thread when the caller chose it", () => {
111
+ mockUseChatConfig.mockReturnValue(
112
+ ref({
113
+ agentId: "my-agent",
114
+ threadId: "chosen-thread",
115
+ hasExplicitThreadId: true,
116
+ }),
117
+ );
118
+
119
+ mountProbe();
120
+
121
+ expect(registryAgent.threadId).toBe("chosen-thread");
122
+ });
123
+
124
+ it("leaves the agent's own thread alone for a non-explicit placeholder", () => {
125
+ // A ThreadsProvider-minted UUID is as meaningless to the backend as the
126
+ // agent's own, so it must not overwrite it.
127
+ const ownThreadId = registryAgent.threadId;
128
+ mockUseChatConfig.mockReturnValue(
129
+ ref({
130
+ agentId: "my-agent",
131
+ threadId: "placeholder-thread",
132
+ hasExplicitThreadId: false,
133
+ }),
134
+ );
135
+
136
+ mountProbe();
137
+
138
+ expect(registryAgent.threadId).toBe(ownThreadId);
139
+ expect(registryAgent.threadId).not.toBe("placeholder-thread");
140
+ });
141
+
142
+ describe("all-or-nothing thread scoping (mirrors React)", () => {
143
+ const expectSetupThrow = (setup: () => void, message: RegExp) => {
144
+ const Probe = defineComponent({
145
+ setup() {
146
+ setup();
147
+ return () => null;
148
+ },
149
+ });
150
+ const spy = vi.spyOn(console, "warn").mockImplementation(() => {});
151
+ try {
152
+ expect(() => render(Probe)).toThrow(message);
153
+ } finally {
154
+ spy.mockRestore();
155
+ }
156
+ };
157
+
158
+ it("throws when threadId is passed without runtimeAgentId", () => {
159
+ expectSetupThrow(() => {
160
+ // @ts-expect-error threadId requires runtimeAgentId
161
+ useAgent({ agentId: "my-agent", threadId: "t1" });
162
+ }, /`threadId` requires `runtimeAgentId`/);
163
+ });
164
+
165
+ it("throws when runtimeAgentId is passed without threadId", () => {
166
+ expectSetupThrow(() => {
167
+ // @ts-expect-error runtimeAgentId requires threadId
168
+ useAgent({ agentId: "chat-1", runtimeAgentId: "my-agent" });
169
+ }, /`runtimeAgentId` requires `threadId`/);
170
+ });
171
+
172
+ it("throws when runtimeAgentId is passed without an explicit agentId", () => {
173
+ expectSetupThrow(() => {
174
+ // @ts-expect-error runtimeAgentId requires an explicit agentId
175
+ useAgent({ runtimeAgentId: "my-agent", threadId: "t1" });
176
+ }, /requires an explicit `agentId`/);
177
+ });
178
+ });
179
+ });