@copilotkit/core 1.61.1 → 1.62.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/index.umd.js CHANGED
@@ -193,16 +193,6 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
193
193
  _defineProperty(this, "activeChannel", null);
194
194
  _defineProperty(this, "canonicalRunId", null);
195
195
  _defineProperty(this, "sharedState", void 0);
196
- _defineProperty(
197
- this,
198
- /**
199
- * Resolves when the active run's pipeline finalizes; `undefined` between runs.
200
- * Set/cleared inside {@link connectAgent}'s observable lifecycle. Declared
201
- * here so {@link RunCompletionAware} consumers can read it without a cast.
202
- */
203
- "activeRunCompletionPromise",
204
- void 0
205
- );
206
196
  this.config = config;
207
197
  this.sharedState = sharedState;
208
198
  }
@@ -247,7 +237,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
247
237
  const previousMessageIds = new Set(this.messages.map((m) => m.id));
248
238
  const subscribers = [
249
239
  { onRunFinishedEvent: (event) => {
250
- result = event.result;
240
+ if (event.outcome === "success") result = event.result;
251
241
  } },
252
242
  ...this.subscribers,
253
243
  subscriber !== null && subscriber !== void 0 ? subscriber : {}
@@ -255,10 +245,10 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
255
245
  await this.onInitialize(input, subscribers);
256
246
  self.activeRunDetach$ = new rxjs.Subject();
257
247
  let resolveCompletion;
258
- this.activeRunCompletionPromise = new Promise((resolve) => {
248
+ self.activeRunCompletionPromise = new Promise((resolve) => {
259
249
  resolveCompletion = resolve;
260
250
  });
261
- const source$ = (0, rxjs.defer)(() => this.connect(input)).pipe((0, _ag_ui_client.transformChunks)(this.debug), (0, rxjs_operators.takeUntil)(self.activeRunDetach$));
251
+ const source$ = (0, rxjs.defer)(() => this.connect(input)).pipe((0, _ag_ui_client.transformChunks)(this.debugLogger), (0, rxjs_operators.takeUntil)(self.activeRunDetach$));
262
252
  const applied$ = this.apply(input, source$, subscribers);
263
253
  await (0, rxjs.lastValueFrom)(this.processApplyEvents(input, applied$, subscribers).pipe((0, rxjs_operators.catchError)((error) => {
264
254
  this.isRunning = false;
@@ -268,7 +258,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
268
258
  this.onFinalize(input, subscribers);
269
259
  resolveCompletion === null || resolveCompletion === void 0 || resolveCompletion();
270
260
  resolveCompletion = void 0;
271
- this.activeRunCompletionPromise = void 0;
261
+ self.activeRunCompletionPromise = void 0;
272
262
  self.activeRunDetach$ = void 0;
273
263
  })), { defaultValue: void 0 });
274
264
  const newMessages = (0, _ag_ui_client.structuredClone_)(this.messages).filter((m) => !previousMessageIds.has(m.id));
@@ -810,8 +800,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
810
800
  cloned.setState(this.state);
811
801
  cloned.setMessages(this.messages);
812
802
  if (this.delegate) {
813
- cloned.delegate = this.delegate.clone();
814
- cloned.syncDelegate(cloned.delegate);
803
+ const clonedDelegate = this.delegate.clone();
804
+ cloned.delegate = clonedDelegate;
805
+ cloned.syncDelegate(clonedDelegate);
815
806
  }
816
807
  return cloned;
817
808
  }
@@ -1000,6 +991,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1000
991
  _defineProperty(this, "_openGenerativeUIEnabled", false);
1001
992
  _defineProperty(this, "_licenseStatus", void 0);
1002
993
  _defineProperty(this, "_telemetryDisabled", false);
994
+ _defineProperty(this, "agentOwnHeaders", /* @__PURE__ */ new WeakMap());
1003
995
  }
1004
996
  /**
1005
997
  * Get all agents as a readonly record
@@ -1170,10 +1162,19 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1170
1162
  console.warn(`Agent ${id} not found`);
1171
1163
  }
1172
1164
  /**
1173
- * Apply current headers to an agent
1165
+ * Apply current core headers to an agent, merged ON TOP of the agent's own
1166
+ * construction-time headers (the per-agent baseline in `agentOwnHeaders`).
1167
+ * Core wins on a key conflict. Non-`HttpAgent` agents are left untouched
1168
+ * because only `HttpAgent` carries a `headers` field. See #5635.
1174
1169
  */
1175
1170
  applyHeadersToAgent(agent) {
1176
- if (agent instanceof _ag_ui_client.HttpAgent) agent.headers = { ...this.core.headers };
1171
+ if (agent instanceof _ag_ui_client.HttpAgent) {
1172
+ if (!this.agentOwnHeaders.has(agent)) this.agentOwnHeaders.set(agent, { ...agent.headers });
1173
+ agent.headers = {
1174
+ ...this.agentOwnHeaders.get(agent),
1175
+ ...this.core.headers
1176
+ };
1177
+ }
1177
1178
  }
1178
1179
  /**
1179
1180
  * Apply current headers to all agents
@@ -1852,7 +1853,14 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1852
1853
  const proxied = agent;
1853
1854
  if (incomingThreadId && typeof proxied.clearReplayCursor === "function") proxied.clearReplayCursor(incomingThreadId);
1854
1855
  }
1855
- if (agent instanceof _ag_ui_client.HttpAgent) agent.headers = { ...this._internal.headers };
1856
+ this._internal.applyHeadersToAgent(agent);
1857
+ await this._internal.notifySubscribers((subscriber) => {
1858
+ var _subscriber$onAgentRu;
1859
+ return (_subscriber$onAgentRu = subscriber.onAgentRunStarted) === null || _subscriber$onAgentRu === void 0 ? void 0 : _subscriber$onAgentRu.call(subscriber, {
1860
+ copilotkit: this.core,
1861
+ agent
1862
+ });
1863
+ }, "Subscriber onAgentRunStarted error:");
1856
1864
  const runAgentResult = await agent.connectAgent({
1857
1865
  forwardedProps: this._internal.properties,
1858
1866
  tools: this.buildFrontendTools(agent.agentId),
@@ -1873,15 +1881,18 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1873
1881
  context
1874
1882
  });
1875
1883
  }
1876
- return { newMessages: [] };
1884
+ return {
1885
+ result: void 0,
1886
+ newMessages: []
1887
+ };
1877
1888
  }
1878
1889
  }
1879
1890
  /**
1880
1891
  * Run an agent
1881
1892
  */
1882
- async runAgent({ agent, forwardedProps }) {
1893
+ async runAgent({ agent, forwardedProps, resume }) {
1883
1894
  if (agent.agentId) this._internal.suggestionEngine.clearSuggestions(agent.agentId);
1884
- if (agent instanceof _ag_ui_client.HttpAgent) agent.headers = { ...this._internal.headers };
1895
+ this._internal.applyHeadersToAgent(agent);
1885
1896
  if (agent.detachActiveRun) await agent.detachActiveRun();
1886
1897
  const isTopLevel = this._runDepth === 0;
1887
1898
  let originalAbortRun;
@@ -1893,6 +1904,13 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1893
1904
  controller.abort();
1894
1905
  originalAbortRun();
1895
1906
  };
1907
+ await this._internal.notifySubscribers((subscriber) => {
1908
+ var _subscriber$onAgentRu2;
1909
+ return (_subscriber$onAgentRu2 = subscriber.onAgentRunStarted) === null || _subscriber$onAgentRu2 === void 0 ? void 0 : _subscriber$onAgentRu2.call(subscriber, {
1910
+ copilotkit: this.core,
1911
+ agent
1912
+ });
1913
+ }, "Subscriber onAgentRunStarted error:");
1896
1914
  }
1897
1915
  this._runDepth++;
1898
1916
  try {
@@ -1901,6 +1919,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1901
1919
  ...this._internal.properties,
1902
1920
  ...forwardedProps
1903
1921
  },
1922
+ ...resume !== void 0 ? { resume } : {},
1904
1923
  tools: this.buildFrontendTools(agent.agentId),
1905
1924
  context: this._internal.getContextForAgent(agent.agentId)
1906
1925
  }, this.createAgentErrorSubscriber(agent));
@@ -1917,7 +1936,10 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1917
1936
  code: CopilotKitCoreErrorCode.AGENT_RUN_FAILED,
1918
1937
  context
1919
1938
  });
1920
- return { newMessages: [] };
1939
+ return {
1940
+ result: void 0,
1941
+ newMessages: []
1942
+ };
1921
1943
  } finally {
1922
1944
  this._runDepth--;
1923
1945
  if (isTopLevel && originalAbortRun) agent.abortRun = originalAbortRun;
@@ -2203,18 +2225,19 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2203
2225
  throw error;
2204
2226
  }
2205
2227
  const toolCallId = (0, _copilotkit_shared.randomUUID)();
2228
+ const assistantToolCall = {
2229
+ id: toolCallId,
2230
+ type: "function",
2231
+ function: {
2232
+ name,
2233
+ arguments: JSON.stringify(parameters)
2234
+ }
2235
+ };
2206
2236
  const assistantMessage = {
2207
2237
  id: (0, _copilotkit_shared.randomUUID)(),
2208
2238
  role: "assistant",
2209
2239
  content: "",
2210
- toolCalls: [{
2211
- id: toolCallId,
2212
- type: "function",
2213
- function: {
2214
- name,
2215
- arguments: JSON.stringify(parameters)
2216
- }
2217
- }]
2240
+ toolCalls: [assistantToolCall]
2218
2241
  };
2219
2242
  agent.messages.push(assistantMessage);
2220
2243
  let handlerResult = {
@@ -2224,7 +2247,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2224
2247
  };
2225
2248
  if (tool.handler) handlerResult = await this.executeToolHandler({
2226
2249
  tool,
2227
- toolCall: assistantMessage.toolCalls[0],
2250
+ toolCall: assistantToolCall,
2228
2251
  agent,
2229
2252
  agentId: resolvedAgentId,
2230
2253
  handlerArgs: parameters,
@@ -2314,9 +2337,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2314
2337
  */
2315
2338
  function createToolSchema(tool) {
2316
2339
  if (!tool.parameters) return { ...EMPTY_TOOL_SCHEMA };
2317
- const rawSchema = (0, _copilotkit_shared.schemaToJsonSchema)(tool.parameters, { zodToJsonSchema: zod_to_json_schema.zodToJsonSchema });
2340
+ const rawSchema = (0, _copilotkit_shared.schemaToJsonSchema)(tool.parameters, { zodToJsonSchema: (schema, options) => (0, zod_to_json_schema.zodToJsonSchema)(schema, options) });
2318
2341
  if (!rawSchema || typeof rawSchema !== "object") return { ...EMPTY_TOOL_SCHEMA };
2319
- const { $schema, ...schema } = rawSchema;
2342
+ const { $schema: _$schema, ...schema } = rawSchema;
2320
2343
  if (typeof schema.type !== "string") schema.type = "object";
2321
2344
  if (typeof schema.properties !== "object" || schema.properties === null) schema.properties = {};
2322
2345
  stripAdditionalProperties(schema);
@@ -2915,9 +2938,19 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2915
2938
  * });
2916
2939
  * ```
2917
2940
  *
2918
- * The resulting header set is also re-applied to every registered
2919
- * `HttpAgent`-derived agent (replacing its `headers`) and `onHeadersChanged`
2920
- * subscribers are notified.
2941
+ * The resulting header set is also re-applied to every agent in the registry
2942
+ * and `onHeadersChanged` subscribers are notified. These headers are merged
2943
+ * ON TOP of the headers each `HttpAgent` was constructed with, so per-agent
2944
+ * headers (e.g. an `Authorization` for a self-hosted backend) are preserved;
2945
+ * on a key conflict the core-level value wins.
2946
+ *
2947
+ * Because the agent's construction-time headers form the merge baseline, this
2948
+ * method can override a per-agent header but cannot REMOVE one: clearing a
2949
+ * core key here only drops the core-level override, after which the agent's
2950
+ * own value (if any) re-surfaces. To change a header an agent was constructed
2951
+ * with, set it at the provider/core level instead of on the agent, or update
2952
+ * it on the agent directly. The clear-on-logout pattern above is for
2953
+ * core-level headers.
2921
2954
  */
2922
2955
  setHeaders(headers) {
2923
2956
  this._headers = normalizeHeaders(headers);
@@ -2982,6 +3015,23 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2982
3015
  return this.agentRegistry.getAgent(id);
2983
3016
  }
2984
3017
  /**
3018
+ * Re-apply the current headers to a single agent (delegated to
3019
+ * AgentRegistry). Core headers are merged on top of the agent's own
3020
+ * construction-time headers rather than replacing them, so headers
3021
+ * configured directly on an `HttpAgent` (e.g. an `Authorization` for a
3022
+ * self-hosted backend) survive header updates instead of being silently
3023
+ * dropped (see #5635). On a key conflict the core-level value wins.
3024
+ *
3025
+ * The merge baseline is the agent's headers as captured the first time the
3026
+ * agent is applied (at registration), so the way to change headers
3027
+ * afterwards is `setHeaders` (which re-applies to every agent), not mutating
3028
+ * `agent.headers` directly — a direct mutation is overwritten on the next
3029
+ * re-apply.
3030
+ */
3031
+ applyHeadersToAgent(agent) {
3032
+ this.agentRegistry.applyHeadersToAgent(agent);
3033
+ }
3034
+ /**
2985
3035
  * Context management (delegated to ContextStore).
2986
3036
  * Pass `agentIds` to restrict the entry to runs of specific agents;
2987
3037
  * omit it for context every agent should receive.
@@ -3701,7 +3751,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3701
3751
  sessionId: 0,
3702
3752
  metadataCredentialsRequested: false,
3703
3753
  metadataJoinCode: null,
3704
- nextCursor: null
3754
+ nextCursor: null,
3755
+ inFlightMutationCount: 0,
3756
+ pendingDeletes: {}
3705
3757
  };
3706
3758
  const threadAdapterEvents = createActionGroup("Thread Adapter", {
3707
3759
  started: empty(),
@@ -3710,7 +3762,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3710
3762
  fetchNextPageRequested: empty(),
3711
3763
  renameRequested: props(),
3712
3764
  archiveRequested: props(),
3713
- deleteRequested: props()
3765
+ unarchiveRequested: props(),
3766
+ deleteRequested: props(),
3767
+ newThreadStarted: empty()
3714
3768
  });
3715
3769
  const threadRestEvents = createActionGroup("Thread REST", {
3716
3770
  listRequested: props(),
@@ -3758,7 +3812,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3758
3812
  error: null,
3759
3813
  metadataCredentialsRequested: false,
3760
3814
  metadataJoinCode: null,
3761
- nextCursor: null
3815
+ nextCursor: null,
3816
+ inFlightMutationCount: 0,
3817
+ pendingDeletes: {}
3762
3818
  })), on(threadAdapterEvents.stopped, (state) => ({
3763
3819
  ...state,
3764
3820
  threads: [],
@@ -3767,7 +3823,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3767
3823
  error: null,
3768
3824
  metadataCredentialsRequested: false,
3769
3825
  metadataJoinCode: null,
3770
- nextCursor: null
3826
+ nextCursor: null,
3827
+ inFlightMutationCount: 0,
3828
+ pendingDeletes: {}
3771
3829
  })), on(threadRestEvents.listRequested, (state, { sessionId }) => {
3772
3830
  if (sessionId !== state.sessionId || !state.context) return state;
3773
3831
  return {
@@ -3809,12 +3867,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3809
3867
  isFetchingNextPage: false,
3810
3868
  error
3811
3869
  };
3812
- }), on(threadRestEvents.metadataCredentialsFailed, (state, { sessionId, error }) => {
3870
+ }), on(threadRestEvents.metadataCredentialsFailed, (state, { sessionId }) => {
3813
3871
  if (sessionId !== state.sessionId) return state;
3814
- return {
3815
- ...state,
3816
- error
3817
- };
3872
+ return state;
3818
3873
  }), on(threadRestEvents.metadataCredentialsRequested, (state, { sessionId }) => {
3819
3874
  if (sessionId !== state.sessionId) return state;
3820
3875
  return {
@@ -3827,10 +3882,106 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3827
3882
  ...state,
3828
3883
  isFetchingNextPage: true
3829
3884
  };
3830
- }), on(threadRestEvents.mutationFinished, (state, { outcome }) => ({
3885
+ }), on(threadAdapterEvents.renameRequested, (state, { threadId, name }) => {
3886
+ const existing = state.threads.find((thread) => thread.id === threadId);
3887
+ const inFlightMutationCount = state.inFlightMutationCount + 1;
3888
+ if (!existing) return {
3889
+ ...state,
3890
+ inFlightMutationCount
3891
+ };
3892
+ return {
3893
+ ...state,
3894
+ threads: upsertThread(state.threads, {
3895
+ ...existing,
3896
+ name
3897
+ }),
3898
+ inFlightMutationCount
3899
+ };
3900
+ }), on(threadAdapterEvents.archiveRequested, (state, { threadId }) => {
3901
+ var _state$context;
3902
+ const existing = state.threads.find((thread) => thread.id === threadId);
3903
+ const inFlightMutationCount = state.inFlightMutationCount + 1;
3904
+ if (!existing) return {
3905
+ ...state,
3906
+ inFlightMutationCount
3907
+ };
3908
+ if (!((_state$context = state.context) === null || _state$context === void 0 ? void 0 : _state$context.includeArchived)) return {
3909
+ ...state,
3910
+ threads: state.threads.filter((thread) => thread.id !== threadId),
3911
+ inFlightMutationCount
3912
+ };
3913
+ return {
3914
+ ...state,
3915
+ threads: upsertThread(state.threads, {
3916
+ ...existing,
3917
+ archived: true
3918
+ }),
3919
+ inFlightMutationCount
3920
+ };
3921
+ }), on(threadAdapterEvents.unarchiveRequested, (state, { threadId }) => {
3922
+ const existing = state.threads.find((thread) => thread.id === threadId);
3923
+ const inFlightMutationCount = state.inFlightMutationCount + 1;
3924
+ if (!existing) return {
3925
+ ...state,
3926
+ inFlightMutationCount
3927
+ };
3928
+ return {
3929
+ ...state,
3930
+ threads: upsertThread(state.threads, {
3931
+ ...existing,
3932
+ archived: false
3933
+ }),
3934
+ inFlightMutationCount
3935
+ };
3936
+ }), on(threadAdapterEvents.deleteRequested, (state, { requestId, threadId }) => {
3937
+ const existing = state.threads.find((thread) => thread.id === threadId);
3938
+ const inFlightMutationCount = state.inFlightMutationCount + 1;
3939
+ if (!existing) return {
3940
+ ...state,
3941
+ inFlightMutationCount
3942
+ };
3943
+ return {
3944
+ ...state,
3945
+ threads: state.threads.filter((thread) => thread.id !== threadId),
3946
+ pendingDeletes: {
3947
+ ...state.pendingDeletes,
3948
+ [requestId]: existing
3949
+ },
3950
+ inFlightMutationCount
3951
+ };
3952
+ }), on(threadAdapterEvents.newThreadStarted, (state) => ({
3831
3953
  ...state,
3832
- error: outcome.ok ? state.error : outcome.error
3833
- })), on(threadDomainEvents.threadUpserted, (state, { sessionId, thread }) => {
3954
+ error: null
3955
+ })), on(threadRestEvents.mutationFinished, (state, { outcome }) => {
3956
+ if (outcome.sessionId !== state.sessionId) return state;
3957
+ const inFlightMutationCount = Math.max(0, state.inFlightMutationCount - 1);
3958
+ if (outcome.ok) {
3959
+ if (state.pendingDeletes[outcome.requestId] === void 0) return {
3960
+ ...state,
3961
+ inFlightMutationCount
3962
+ };
3963
+ const { [outcome.requestId]: _settled, ...rest } = state.pendingDeletes;
3964
+ return {
3965
+ ...state,
3966
+ inFlightMutationCount,
3967
+ pendingDeletes: rest
3968
+ };
3969
+ }
3970
+ const rolledBack = state.pendingDeletes[outcome.requestId];
3971
+ if (rolledBack === void 0) return {
3972
+ ...state,
3973
+ inFlightMutationCount,
3974
+ error: outcome.error
3975
+ };
3976
+ const { [outcome.requestId]: _restored, ...rest } = state.pendingDeletes;
3977
+ return {
3978
+ ...state,
3979
+ threads: upsertThread(state.threads, rolledBack),
3980
+ pendingDeletes: rest,
3981
+ inFlightMutationCount,
3982
+ error: outcome.error
3983
+ };
3984
+ }), on(threadDomainEvents.threadUpserted, (state, { sessionId, thread }) => {
3834
3985
  if (sessionId !== state.sessionId) return state;
3835
3986
  return {
3836
3987
  ...state,
@@ -3843,23 +3994,49 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3843
3994
  threads: state.threads.filter((thread) => thread.id !== threadId)
3844
3995
  };
3845
3996
  }));
3846
- const selectThreads = createSelector((state) => state.threads);
3847
- const selectThreadsIsLoading = createSelector((state) => state.isLoading);
3848
- const selectThreadsError = createSelector((state) => state.error);
3849
- const selectHasNextPage = createSelector((state) => state.nextCursor != null);
3850
- const selectIsFetchingNextPage = createSelector((state) => state.isFetchingNextPage);
3997
+ /**
3998
+ * Builds a fresh set of memoized thread selectors.
3999
+ *
4000
+ * Each `createSelector` closure owns a private one-entry cache. Sharing a
4001
+ * single module-level selector instance across multiple concurrent stores
4002
+ * (e.g. a `<CopilotThreadsDrawer>` plus an independent `useThreads`) makes every
4003
+ * cross-store emission a cache miss, defeating memoization and risking
4004
+ * emission instability for any future selector that allocates a new
4005
+ * object/array. Creating a per-store instance keeps each store's cache
4006
+ * isolated so concurrent stores never thrash one another.
4007
+ */
4008
+ function createThreadSelectors() {
4009
+ return {
4010
+ threads: createSelector((state) => state.threads),
4011
+ isLoading: createSelector((state) => state.isLoading),
4012
+ error: createSelector((state) => state.error),
4013
+ hasNextPage: createSelector((state) => state.nextCursor != null),
4014
+ isFetchingNextPage: createSelector((state) => state.isFetchingNextPage),
4015
+ isMutating: createSelector((state) => state.inFlightMutationCount > 0)
4016
+ };
4017
+ }
4018
+ const standaloneSelectors = createThreadSelectors();
4019
+ const selectThreads = standaloneSelectors.threads;
4020
+ const selectThreadsIsLoading = standaloneSelectors.isLoading;
4021
+ const selectThreadsError = standaloneSelectors.error;
4022
+ const selectHasNextPage = standaloneSelectors.hasNextPage;
4023
+ const selectIsFetchingNextPage = standaloneSelectors.isFetchingNextPage;
4024
+ const selectIsMutating = standaloneSelectors.isMutating;
3851
4025
  let threadRequestId = 0;
3852
4026
  function createThreadRequestId() {
3853
4027
  threadRequestId += 1;
3854
4028
  return `thread-request-${threadRequestId}`;
3855
4029
  }
4030
+ function threadFromFetch(input, init) {
4031
+ return (0, rxjs_fetch.fromFetch)(input, init);
4032
+ }
3856
4033
  function createThreadFetchObservable(environment, context, sessionId) {
3857
4034
  return (0, rxjs.defer)(() => {
3858
4035
  const params = { agentId: context.agentId };
3859
4036
  if (context.includeArchived) params.includeArchived = "true";
3860
4037
  if (context.limit != null) params.limit = String(context.limit);
3861
4038
  const qs = new URLSearchParams(params);
3862
- return (0, rxjs_fetch.fromFetch)(`${context.runtimeUrl}/threads?${qs.toString()}`, {
4039
+ return threadFromFetch(`${context.runtimeUrl}/threads?${qs.toString()}`, {
3863
4040
  selector: (response) => {
3864
4041
  if (!response.ok) throw new Error(`Failed to fetch threads: ${response.status}`);
3865
4042
  return response.json();
@@ -3890,7 +4067,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3890
4067
  }
3891
4068
  function createThreadMetadataCredentialsObservable(environment, context, sessionId) {
3892
4069
  return (0, rxjs.defer)(() => {
3893
- return (0, rxjs_fetch.fromFetch)(`${context.runtimeUrl}${THREAD_SUBSCRIBE_PATH}`, {
4070
+ return threadFromFetch(`${context.runtimeUrl}${THREAD_SUBSCRIBE_PATH}`, {
3894
4071
  selector: async (response) => {
3895
4072
  if (!response.ok) throw new Error(`Failed to fetch thread metadata credentials: ${response.status}`);
3896
4073
  return response.json();
@@ -3923,7 +4100,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3923
4100
  }
3924
4101
  function createThreadMutationObservable(environment, context, request) {
3925
4102
  return (0, rxjs.defer)(() => {
3926
- return (0, rxjs_fetch.fromFetch)(`${context.runtimeUrl}${request.path}`, {
4103
+ return threadFromFetch(`${context.runtimeUrl}${request.path}`, {
3927
4104
  selector: async (response) => {
3928
4105
  if (!response.ok) throw new Error(`Request failed: ${response.status}`);
3929
4106
  return null;
@@ -3937,10 +4114,12 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3937
4114
  body: JSON.stringify(request.body)
3938
4115
  }).pipe((0, rxjs_operators.map)(() => threadRestEvents.mutationFinished({ outcome: {
3939
4116
  requestId: request.requestId,
4117
+ sessionId: request.sessionId,
3940
4118
  ok: true
3941
4119
  } })), (0, rxjs_operators.catchError)((error) => {
3942
4120
  return (0, rxjs.of)(threadRestEvents.mutationFinished({ outcome: {
3943
4121
  requestId: request.requestId,
4122
+ sessionId: request.sessionId,
3944
4123
  ok: false,
3945
4124
  error: error instanceof Error ? error : new Error(String(error))
3946
4125
  } }));
@@ -3948,6 +4127,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3948
4127
  });
3949
4128
  }
3950
4129
  function createThreadStore(environment) {
4130
+ const selectors = createThreadSelectors();
3951
4131
  const store = createStore({
3952
4132
  reducer: threadReducer,
3953
4133
  effects: [
@@ -3957,16 +4137,16 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3957
4137
  context
3958
4138
  })), (0, rxjs_operators.takeUntil)(actions$.pipe(ofType(threadAdapterEvents.contextChanged, threadAdapterEvents.stopped))), (0, rxjs_operators.switchMap)(({ action: currentAction, context }) => createThreadFetchObservable(environment, context, currentAction.sessionId)))))),
3959
4139
  createEffect((actions$, state$) => actions$.pipe(ofType(threadRestEvents.listSucceeded), (0, rxjs_operators.withLatestFrom)(state$), (0, rxjs_operators.filter)(([action, state]) => {
3960
- var _state$context;
3961
- return action.sessionId === state.sessionId && !state.metadataCredentialsRequested && Boolean((_state$context = state.context) === null || _state$context === void 0 ? void 0 : _state$context.wsUrl) && Boolean(state.metadataJoinCode);
4140
+ var _state$context2;
4141
+ return action.sessionId === state.sessionId && !state.metadataCredentialsRequested && Boolean((_state$context2 = state.context) === null || _state$context2 === void 0 ? void 0 : _state$context2.wsUrl) && Boolean(state.metadataJoinCode);
3962
4142
  }), (0, rxjs_operators.map)(([action]) => threadRestEvents.metadataCredentialsRequested({ sessionId: action.sessionId })))),
3963
4143
  createEffect((actions$, state$) => actions$.pipe(ofType(threadRestEvents.metadataCredentialsRequested), (0, rxjs_operators.switchMap)((action) => state$.pipe((0, rxjs_operators.map)((state) => state.context), (0, rxjs_operators.filter)((context) => Boolean(context)), (0, rxjs_operators.take)(1), (0, rxjs_operators.map)((context) => ({
3964
4144
  action,
3965
4145
  context
3966
4146
  })), (0, rxjs_operators.takeUntil)(actions$.pipe(ofType(threadAdapterEvents.contextChanged, threadAdapterEvents.stopped))), (0, rxjs_operators.switchMap)(({ action: currentAction, context }) => createThreadMetadataCredentialsObservable(environment, context, currentAction.sessionId)))))),
3967
4147
  createEffect((actions$, state$) => actions$.pipe(ofType(threadRestEvents.metadataCredentialsSucceeded), (0, rxjs_operators.withLatestFrom)(state$), (0, rxjs_operators.filter)(([action, state]) => {
3968
- var _state$context2;
3969
- return action.sessionId === state.sessionId && Boolean((_state$context2 = state.context) === null || _state$context2 === void 0 ? void 0 : _state$context2.wsUrl);
4148
+ var _state$context3;
4149
+ return action.sessionId === state.sessionId && Boolean((_state$context3 = state.context) === null || _state$context3 === void 0 ? void 0 : _state$context3.wsUrl);
3970
4150
  }), (0, rxjs_operators.switchMap)(([action, state]) => {
3971
4151
  const context = state.context;
3972
4152
  const joinToken = action.joinToken;
@@ -4003,12 +4183,12 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4003
4183
  });
4004
4184
  }))),
4005
4185
  createEffect((actions$, state$) => actions$.pipe(ofType(threadSocketEvents.metadataReceived), (0, rxjs_operators.withLatestFrom)(state$), (0, rxjs_operators.filter)(([action, state]) => action.sessionId === state.sessionId), (0, rxjs_operators.map)(([action, state]) => {
4006
- var _state$context3;
4186
+ var _state$context4;
4007
4187
  if (action.payload.operation === "deleted") return threadDomainEvents.threadDeleted({
4008
4188
  sessionId: action.sessionId,
4009
4189
  threadId: action.payload.deleted.id
4010
4190
  });
4011
- if (action.payload.operation === "archived" && !((_state$context3 = state.context) === null || _state$context3 === void 0 ? void 0 : _state$context3.includeArchived)) return threadDomainEvents.threadDeleted({
4191
+ if (action.payload.operation === "archived" && !((_state$context4 = state.context) === null || _state$context4 === void 0 ? void 0 : _state$context4.includeArchived)) return threadDomainEvents.threadDeleted({
4012
4192
  sessionId: action.sessionId,
4013
4193
  threadId: action.payload.threadId
4014
4194
  });
@@ -4017,6 +4197,10 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4017
4197
  thread: action.payload.thread
4018
4198
  });
4019
4199
  }))),
4200
+ createEffect((actions$, state$) => actions$.pipe(ofType(threadSocketEvents.joinFailed, threadSocketEvents.joinTimedOut, threadSocketEvents.errored, threadRestEvents.metadataCredentialsFailed), (0, rxjs_operators.withLatestFrom)(state$), (0, rxjs_operators.filter)(([action, state]) => action.sessionId === state.sessionId), (0, rxjs_operators.tap)(([action]) => {
4201
+ const reason = threadSocketEvents.joinTimedOut.match(action) ? "channel join timed out" : threadSocketEvents.joinFailed.match(action) ? "channel join was rejected" : threadRestEvents.metadataCredentialsFailed.match(action) ? "metadata credentials fetch failed" : "socket errored";
4202
+ console.warn(`[threads] realtime ${reason}; the thread list may be stale until reconnect`);
4203
+ })), { dispatch: false }),
4020
4204
  createEffect((actions$, state$) => actions$.pipe(ofType(threadAdapterEvents.fetchNextPageRequested), (0, rxjs_operators.withLatestFrom)(state$), (0, rxjs_operators.filter)(([, state]) => Boolean(state.context) && Boolean(state.nextCursor)), (0, rxjs_operators.switchMap)(([, state]) => {
4021
4205
  const context = state.context;
4022
4206
  const params = {
@@ -4025,7 +4209,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4025
4209
  };
4026
4210
  if (context.includeArchived) params.includeArchived = "true";
4027
4211
  if (context.limit != null) params.limit = String(context.limit);
4028
- return (0, rxjs_fetch.fromFetch)(`${context.runtimeUrl}/threads?${new URLSearchParams(params).toString()}`, {
4212
+ return threadFromFetch(`${context.runtimeUrl}/threads?${new URLSearchParams(params).toString()}`, {
4029
4213
  selector: (response) => {
4030
4214
  if (!response.ok) throw new Error(`Failed to fetch next page: ${response.status}`);
4031
4215
  return response.json();
@@ -4050,12 +4234,14 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4050
4234
  error: error instanceof Error ? error : new Error(String(error))
4051
4235
  }))), (0, rxjs_operators.takeUntil)(actions$.pipe(ofType(threadAdapterEvents.contextChanged, threadAdapterEvents.stopped))));
4052
4236
  }))),
4053
- createEffect((actions$, state$) => actions$.pipe(ofType(threadAdapterEvents.renameRequested, threadAdapterEvents.archiveRequested, threadAdapterEvents.deleteRequested), (0, rxjs_operators.withLatestFrom)(state$), (0, rxjs_operators.mergeMap)(([action, state]) => {
4237
+ createEffect((actions$, state$) => actions$.pipe(ofType(threadAdapterEvents.renameRequested, threadAdapterEvents.archiveRequested, threadAdapterEvents.unarchiveRequested, threadAdapterEvents.deleteRequested), (0, rxjs_operators.withLatestFrom)(state$), (0, rxjs_operators.mergeMap)(([action, state]) => {
4238
+ const sessionId = state.sessionId;
4054
4239
  const context = state.context;
4055
4240
  if (!(context === null || context === void 0 ? void 0 : context.runtimeUrl)) {
4056
4241
  const requestId = action.requestId;
4057
4242
  return (0, rxjs.of)(threadRestEvents.mutationFinished({ outcome: {
4058
4243
  requestId,
4244
+ sessionId,
4059
4245
  ok: false,
4060
4246
  error: /* @__PURE__ */ new Error("Runtime URL is not configured")
4061
4247
  } }));
@@ -4063,6 +4249,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4063
4249
  const commonBody = { agentId: context.agentId };
4064
4250
  if (threadAdapterEvents.renameRequested.match(action)) return createThreadMutationObservable(environment, context, {
4065
4251
  requestId: action.requestId,
4252
+ sessionId,
4066
4253
  method: "PATCH",
4067
4254
  path: `/threads/${encodeURIComponent(action.threadId)}`,
4068
4255
  body: {
@@ -4072,12 +4259,24 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4072
4259
  });
4073
4260
  if (threadAdapterEvents.archiveRequested.match(action)) return createThreadMutationObservable(environment, context, {
4074
4261
  requestId: action.requestId,
4262
+ sessionId,
4075
4263
  method: "POST",
4076
4264
  path: `/threads/${encodeURIComponent(action.threadId)}/archive`,
4077
4265
  body: commonBody
4078
4266
  });
4267
+ if (threadAdapterEvents.unarchiveRequested.match(action)) return createThreadMutationObservable(environment, context, {
4268
+ requestId: action.requestId,
4269
+ sessionId,
4270
+ method: "PATCH",
4271
+ path: `/threads/${encodeURIComponent(action.threadId)}`,
4272
+ body: {
4273
+ ...commonBody,
4274
+ archived: false
4275
+ }
4276
+ });
4079
4277
  return createThreadMutationObservable(environment, context, {
4080
4278
  requestId: action.requestId,
4279
+ sessionId,
4081
4280
  method: "DELETE",
4082
4281
  path: `/threads/${encodeURIComponent(action.threadId)}`,
4083
4282
  body: commonBody
@@ -4088,6 +4287,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4088
4287
  function trackMutation(dispatchAction) {
4089
4288
  const resultPromise = (0, rxjs.firstValueFrom)((0, rxjs.merge)(store.actions$.pipe(ofType(threadRestEvents.mutationFinished), (0, rxjs_operators.filter)((action) => action.outcome.requestId === dispatchAction.requestId), (0, rxjs_operators.map)((action) => action.outcome)), store.actions$.pipe(ofType(threadAdapterEvents.stopped), (0, rxjs_operators.map)(() => ({
4090
4289
  requestId: dispatchAction.requestId,
4290
+ sessionId: store.getState().sessionId,
4091
4291
  ok: false,
4092
4292
  error: /* @__PURE__ */ new Error("Thread store stopped before mutation completed")
4093
4293
  })))).pipe((0, rxjs_operators.take)(1))).then((outcome) => {
@@ -4097,13 +4297,26 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4097
4297
  store.dispatch(dispatchAction);
4098
4298
  return resultPromise;
4099
4299
  }
4300
+ let errorSubscription = null;
4301
+ const subscribeErrors = () => {
4302
+ if (!environment.onError || errorSubscription) return;
4303
+ errorSubscription = store.actions$.pipe(ofType(threadRestEvents.mutationFinished), (0, rxjs_operators.filter)((action) => !action.outcome.ok && action.outcome.sessionId === store.getState().sessionId)).subscribe((action) => {
4304
+ if (!action.outcome.ok) {
4305
+ var _environment$onError;
4306
+ (_environment$onError = environment.onError) === null || _environment$onError === void 0 || _environment$onError.call(environment, action.outcome.error);
4307
+ }
4308
+ });
4309
+ };
4100
4310
  return {
4101
4311
  start() {
4102
4312
  store.init();
4313
+ subscribeErrors();
4103
4314
  store.dispatch(threadAdapterEvents.started());
4104
4315
  },
4105
4316
  stop() {
4106
4317
  store.dispatch(threadAdapterEvents.stopped());
4318
+ errorSubscription === null || errorSubscription === void 0 || errorSubscription.unsubscribe();
4319
+ errorSubscription = null;
4107
4320
  store.stop();
4108
4321
  },
4109
4322
  setContext(context) {
@@ -4114,6 +4327,14 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4114
4327
  if (!context) return;
4115
4328
  store.dispatch(threadRestEvents.listRequested({ sessionId }));
4116
4329
  },
4330
+ refetchThreads() {
4331
+ const { sessionId, context } = store.getState();
4332
+ if (!context) return;
4333
+ store.dispatch(threadRestEvents.listRequested({ sessionId }));
4334
+ },
4335
+ startNewThread() {
4336
+ store.dispatch(threadAdapterEvents.newThreadStarted());
4337
+ },
4117
4338
  fetchNextPage() {
4118
4339
  store.dispatch(threadAdapterEvents.fetchNextPageRequested());
4119
4340
  },
@@ -4130,6 +4351,12 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4130
4351
  threadId
4131
4352
  }));
4132
4353
  },
4354
+ unarchiveThread(threadId) {
4355
+ return trackMutation(threadAdapterEvents.unarchiveRequested({
4356
+ requestId: createThreadRequestId(),
4357
+ threadId
4358
+ }));
4359
+ },
4133
4360
  deleteThread(threadId) {
4134
4361
  return trackMutation(threadAdapterEvents.deleteRequested({
4135
4362
  requestId: createThreadRequestId(),
@@ -4139,15 +4366,21 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4139
4366
  getState() {
4140
4367
  return store.getState();
4141
4368
  },
4142
- select: store.select.bind(store)
4369
+ getServerState() {
4370
+ return initialThreadState;
4371
+ },
4372
+ select: store.select.bind(store),
4373
+ selectors
4143
4374
  };
4144
4375
  }
4145
4376
  const ɵthreadAdapterEvents = threadAdapterEvents;
4377
+ const ɵcreateThreadSelectors = createThreadSelectors;
4146
4378
  const ɵselectThreads = selectThreads;
4147
4379
  const ɵselectThreadsIsLoading = selectThreadsIsLoading;
4148
4380
  const ɵselectThreadsError = selectThreadsError;
4149
4381
  const ɵselectHasNextPage = selectHasNextPage;
4150
4382
  const ɵselectIsFetchingNextPage = selectIsFetchingNextPage;
4383
+ const ɵselectIsMutating = selectIsMutating;
4151
4384
  /**
4152
4385
  * Number of consecutive WebSocket connection failures after which the
4153
4386
  * threads channel tears itself down rather than retrying indefinitely.
@@ -4156,6 +4389,51 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4156
4389
  */
4157
4390
  const ɵMAX_SOCKET_RETRIES = MAX_SOCKET_RETRIES;
4158
4391
 
4392
+ //#endregion
4393
+ //#region src/features.ts
4394
+ /**
4395
+ * Central registry of CopilotKit feature names.
4396
+ *
4397
+ * Feature names are the strings passed to a license context's `checkFeature`
4398
+ * (see `@copilotkit/shared`'s `LicenseContextValue`). Historically the only
4399
+ * features referenced by literal were the chat surfaces (`chat`, `sidebar`,
4400
+ * `popup`); this module makes the set explicit and typed so new surfaces —
4401
+ * such as the threads drawer — register a real, discoverable feature name
4402
+ * rather than an ad-hoc string scattered across components.
4403
+ *
4404
+ * `checkFeature` itself still accepts any `string` for backward compatibility;
4405
+ * this registry simply documents and types the names CopilotKit recognises.
4406
+ */
4407
+ /**
4408
+ * The set of feature names CopilotKit recognises.
4409
+ *
4410
+ * Frozen so the array cannot be mutated at runtime. Add new surfaces here when
4411
+ * they begin gating behaviour on `checkFeature`.
4412
+ */
4413
+ const ɵCOPILOTKIT_FEATURES = Object.freeze([
4414
+ "chat",
4415
+ "sidebar",
4416
+ "popup",
4417
+ "threads"
4418
+ ]);
4419
+ const FEATURE_SET = new Set(ɵCOPILOTKIT_FEATURES);
4420
+ /**
4421
+ * Type guard: returns `true` when `name` is a recognised CopilotKit feature.
4422
+ *
4423
+ * @param name - Candidate feature name.
4424
+ * @returns Whether `name` is a registered feature.
4425
+ *
4426
+ * @example
4427
+ * ```ts
4428
+ * if (ɵisCopilotKitFeature("threads")) {
4429
+ * // narrowed to ɵCopilotKitFeature
4430
+ * }
4431
+ * ```
4432
+ */
4433
+ function ɵisCopilotKitFeature(name) {
4434
+ return FEATURE_SET.has(name);
4435
+ }
4436
+
4159
4437
  //#endregion
4160
4438
  exports.AgentRegistry = AgentRegistry;
4161
4439
  exports.AgentThreadLockedError = AgentThreadLockedError;
@@ -4183,8 +4461,11 @@ exports.on = on;
4183
4461
  exports.parseToolArguments = parseToolArguments;
4184
4462
  exports.props = props;
4185
4463
  exports.select = select;
4464
+ exports.ɵCOPILOTKIT_FEATURES = ɵCOPILOTKIT_FEATURES;
4186
4465
  exports.ɵMAX_SOCKET_RETRIES = ɵMAX_SOCKET_RETRIES;
4466
+ exports.ɵcreateThreadSelectors = ɵcreateThreadSelectors;
4187
4467
  exports.ɵcreateThreadStore = createThreadStore;
4468
+ exports.ɵisCopilotKitFeature = ɵisCopilotKitFeature;
4188
4469
  exports.ɵjoinPhoenixChannel$ = ɵjoinPhoenixChannel$;
4189
4470
  exports.ɵobservePhoenixEvent$ = ɵobservePhoenixEvent$;
4190
4471
  exports.ɵobservePhoenixJoinOutcome$ = ɵobservePhoenixJoinOutcome$;
@@ -4194,6 +4475,7 @@ exports.ɵphoenixChannel$ = ɵphoenixChannel$;
4194
4475
  exports.ɵphoenixSocket$ = ɵphoenixSocket$;
4195
4476
  exports.ɵselectHasNextPage = ɵselectHasNextPage;
4196
4477
  exports.ɵselectIsFetchingNextPage = ɵselectIsFetchingNextPage;
4478
+ exports.ɵselectIsMutating = ɵselectIsMutating;
4197
4479
  exports.ɵselectThreads = ɵselectThreads;
4198
4480
  exports.ɵselectThreadsError = ɵselectThreadsError;
4199
4481
  exports.ɵselectThreadsIsLoading = ɵselectThreadsIsLoading;