@copilotkitnext/core 1.54.1-next.5 → 1.54.1-next.6

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.cjs CHANGED
@@ -492,9 +492,12 @@ function hasCredentials(agent) {
492
492
  function isZodError(error) {
493
493
  return error !== null && typeof error === "object" && "name" in error && error.name === "ZodError";
494
494
  }
495
+ function isAbortError(error) {
496
+ return (error instanceof DOMException || error instanceof Error) && error.name === "AbortError";
497
+ }
495
498
  function withAbortErrorHandling(observable) {
496
499
  return observable.pipe((0, rxjs_operators.catchError)((error) => {
497
- if (isZodError(error)) return rxjs.EMPTY;
500
+ if (isZodError(error) || isAbortError(error)) return rxjs.EMPTY;
498
501
  throw error;
499
502
  }));
500
503
  }
@@ -1371,10 +1374,31 @@ const SUGGEST_TOOL = {
1371
1374
  */
1372
1375
  var RunHandler = class {
1373
1376
  _tools = [];
1377
+ /**
1378
+ * Tracks whether the current run (including in-flight tool execution)
1379
+ * has been aborted via `stopAgent()` or `agent.abortRun()`. Created
1380
+ * fresh in `runAgent()`, aborted by `abortCurrentRun()`.
1381
+ */
1382
+ _runAbortController = null;
1383
+ /**
1384
+ * Tracks recursive `runAgent` depth so that the abort controller and
1385
+ * `agent.abortRun()` intercept are only set up / torn down at the
1386
+ * top-level call, not on follow-up recursive calls from
1387
+ * `processAgentResult`.
1388
+ */
1389
+ _runDepth = 0;
1374
1390
  constructor(core) {
1375
1391
  this.core = core;
1376
1392
  }
1377
1393
  /**
1394
+ * Abort the current run. Called by `CopilotKitCore.stopAgent()` to signal
1395
+ * that in-flight tool handlers should stop and `processAgentResult` should
1396
+ * not start a follow-up run.
1397
+ */
1398
+ abortCurrentRun() {
1399
+ this._runAbortController?.abort();
1400
+ }
1401
+ /**
1378
1402
  * Typed access to CopilotKitCore's internal ("friend") methods.
1379
1403
  * Centralises the single unavoidable cast so call-sites stay clean.
1380
1404
  */
@@ -1468,6 +1492,18 @@ var RunHandler = class {
1468
1492
  if (agent.agentId) this._internal.suggestionEngine.clearSuggestions(agent.agentId);
1469
1493
  if (agent instanceof _ag_ui_client.HttpAgent) agent.headers = { ...this._internal.headers };
1470
1494
  if (agent.detachActiveRun) await agent.detachActiveRun();
1495
+ const isTopLevel = this._runDepth === 0;
1496
+ let originalAbortRun;
1497
+ if (isTopLevel) {
1498
+ this._runAbortController = new AbortController();
1499
+ const controller = this._runAbortController;
1500
+ originalAbortRun = agent.abortRun.bind(agent);
1501
+ agent.abortRun = () => {
1502
+ controller.abort();
1503
+ originalAbortRun();
1504
+ };
1505
+ }
1506
+ this._runDepth++;
1471
1507
  try {
1472
1508
  const runAgentResult = await agent.runAgent({
1473
1509
  forwardedProps: {
@@ -1477,7 +1513,7 @@ var RunHandler = class {
1477
1513
  tools: this.buildFrontendTools(agent.agentId),
1478
1514
  context: Object.values(this._internal.context)
1479
1515
  }, this.createAgentErrorSubscriber(agent));
1480
- return this.processAgentResult({
1516
+ return await this.processAgentResult({
1481
1517
  runAgentResult,
1482
1518
  agent
1483
1519
  });
@@ -1491,6 +1527,9 @@ var RunHandler = class {
1491
1527
  context
1492
1528
  });
1493
1529
  return { newMessages: [] };
1530
+ } finally {
1531
+ this._runDepth--;
1532
+ if (isTopLevel && originalAbortRun) agent.abortRun = originalAbortRun;
1494
1533
  }
1495
1534
  }
1496
1535
  /**
@@ -1519,7 +1558,7 @@ var RunHandler = class {
1519
1558
  }
1520
1559
  }
1521
1560
  }
1522
- if (needsFollowUp) {
1561
+ if (needsFollowUp && !this._runAbortController?.signal.aborted) {
1523
1562
  await this._internal.waitForPendingFrameworkUpdates();
1524
1563
  return await this.runAgent({ agent });
1525
1564
  }
@@ -1565,7 +1604,8 @@ var RunHandler = class {
1565
1604
  if (!errorMessage) try {
1566
1605
  const result = await tool.handler(parsedArgs, {
1567
1606
  toolCall,
1568
- agent
1607
+ agent,
1608
+ signal: this._runAbortController?.signal
1569
1609
  });
1570
1610
  if (result === void 0 || result === null) toolCallResult = "";
1571
1611
  else if (typeof result === "string") toolCallResult = result;
@@ -2311,6 +2351,7 @@ var CopilotKitCore = class {
2311
2351
  return this.runHandler.connectAgent(params);
2312
2352
  }
2313
2353
  stopAgent(params) {
2354
+ this.runHandler.abortCurrentRun();
2314
2355
  params.agent.abortRun();
2315
2356
  }
2316
2357
  async runAgent(params) {
@@ -2808,15 +2849,18 @@ const REQUEST_TIMEOUT_MS = 15e3;
2808
2849
  const initialThreadState = {
2809
2850
  threads: [],
2810
2851
  isLoading: false,
2852
+ isFetchingNextPage: false,
2811
2853
  error: null,
2812
2854
  context: null,
2813
2855
  sessionId: 0,
2814
- metadataCredentialsRequested: false
2856
+ metadataCredentialsRequested: false,
2857
+ nextCursor: null
2815
2858
  };
2816
2859
  const threadAdapterEvents = createActionGroup("Thread Adapter", {
2817
2860
  started: empty(),
2818
2861
  stopped: empty(),
2819
2862
  contextChanged: props(),
2863
+ fetchNextPageRequested: empty(),
2820
2864
  renameRequested: props(),
2821
2865
  archiveRequested: props(),
2822
2866
  deleteRequested: props()
@@ -2825,6 +2869,8 @@ const threadRestEvents = createActionGroup("Thread REST", {
2825
2869
  listRequested: props(),
2826
2870
  listSucceeded: props(),
2827
2871
  listFailed: props(),
2872
+ nextPageSucceeded: props(),
2873
+ nextPageFailed: props(),
2828
2874
  metadataCredentialsRequested: props(),
2829
2875
  metadataCredentialsSucceeded: props(),
2830
2876
  metadataCredentialsFailed: props(),
@@ -2857,14 +2903,18 @@ const threadReducer = createReducer(initialThreadState, on(threadAdapterEvents.c
2857
2903
  sessionId: state.sessionId + 1,
2858
2904
  threads: [],
2859
2905
  isLoading: Boolean(context),
2906
+ isFetchingNextPage: false,
2860
2907
  error: null,
2861
- metadataCredentialsRequested: false
2908
+ metadataCredentialsRequested: false,
2909
+ nextCursor: null
2862
2910
  })), on(threadAdapterEvents.stopped, (state) => ({
2863
2911
  ...state,
2864
2912
  threads: [],
2865
2913
  isLoading: false,
2914
+ isFetchingNextPage: false,
2866
2915
  error: null,
2867
- metadataCredentialsRequested: false
2916
+ metadataCredentialsRequested: false,
2917
+ nextCursor: null
2868
2918
  })), on(threadRestEvents.listRequested, (state, { sessionId }) => {
2869
2919
  if (sessionId !== state.sessionId || !state.context) return state;
2870
2920
  return {
@@ -2872,13 +2922,14 @@ const threadReducer = createReducer(initialThreadState, on(threadAdapterEvents.c
2872
2922
  isLoading: true,
2873
2923
  error: null
2874
2924
  };
2875
- }), on(threadRestEvents.listSucceeded, (state, { sessionId, threads }) => {
2925
+ }), on(threadRestEvents.listSucceeded, (state, { sessionId, threads, nextCursor }) => {
2876
2926
  if (sessionId !== state.sessionId) return state;
2877
2927
  return {
2878
2928
  ...state,
2879
2929
  threads: sortThreadsByUpdatedAt(threads),
2880
2930
  isLoading: false,
2881
- error: null
2931
+ error: null,
2932
+ nextCursor
2882
2933
  };
2883
2934
  }), on(threadRestEvents.listFailed, (state, { sessionId, error }) => {
2884
2935
  if (sessionId !== state.sessionId) return state;
@@ -2887,6 +2938,23 @@ const threadReducer = createReducer(initialThreadState, on(threadAdapterEvents.c
2887
2938
  isLoading: false,
2888
2939
  error
2889
2940
  };
2941
+ }), on(threadRestEvents.nextPageSucceeded, (state, { sessionId, threads, nextCursor }) => {
2942
+ if (sessionId !== state.sessionId) return state;
2943
+ let merged = state.threads;
2944
+ for (const thread of threads) merged = upsertThread(merged, thread);
2945
+ return {
2946
+ ...state,
2947
+ threads: merged,
2948
+ isFetchingNextPage: false,
2949
+ nextCursor
2950
+ };
2951
+ }), on(threadRestEvents.nextPageFailed, (state, { sessionId, error }) => {
2952
+ if (sessionId !== state.sessionId) return state;
2953
+ return {
2954
+ ...state,
2955
+ isFetchingNextPage: false,
2956
+ error
2957
+ };
2890
2958
  }), on(threadRestEvents.metadataCredentialsFailed, (state, { sessionId, error }) => {
2891
2959
  if (sessionId !== state.sessionId) return state;
2892
2960
  return {
@@ -2899,6 +2967,12 @@ const threadReducer = createReducer(initialThreadState, on(threadAdapterEvents.c
2899
2967
  ...state,
2900
2968
  metadataCredentialsRequested: true
2901
2969
  };
2970
+ }), on(threadAdapterEvents.fetchNextPageRequested, (state) => {
2971
+ if (!state.nextCursor || state.isFetchingNextPage) return state;
2972
+ return {
2973
+ ...state,
2974
+ isFetchingNextPage: true
2975
+ };
2902
2976
  }), on(threadRestEvents.mutationFinished, (state, { outcome }) => ({
2903
2977
  ...state,
2904
2978
  error: outcome.ok ? state.error : outcome.error
@@ -2918,6 +2992,8 @@ const threadReducer = createReducer(initialThreadState, on(threadAdapterEvents.c
2918
2992
  const selectThreads = createSelector((state) => state.threads);
2919
2993
  const selectThreadsIsLoading = createSelector((state) => state.isLoading);
2920
2994
  const selectThreadsError = createSelector((state) => state.error);
2995
+ const selectHasNextPage = createSelector((state) => state.nextCursor != null);
2996
+ const selectIsFetchingNextPage = createSelector((state) => state.isFetchingNextPage);
2921
2997
  let threadRequestId = 0;
2922
2998
  function createThreadRequestId() {
2923
2999
  threadRequestId += 1;
@@ -2925,11 +3001,14 @@ function createThreadRequestId() {
2925
3001
  }
2926
3002
  function createThreadFetchObservable(environment, context, sessionId) {
2927
3003
  return (0, rxjs.defer)(() => {
2928
- const params = new URLSearchParams({
3004
+ const params = {
2929
3005
  userId: context.userId,
2930
3006
  agentId: context.agentId
2931
- });
2932
- return (0, rxjs_fetch.fromFetch)(`${context.runtimeUrl}/threads?${params.toString()}`, {
3007
+ };
3008
+ if (context.includeArchived) params.includeArchived = "true";
3009
+ if (context.limit != null) params.limit = String(context.limit);
3010
+ const qs = new URLSearchParams(params);
3011
+ return (0, rxjs_fetch.fromFetch)(`${context.runtimeUrl}/threads?${qs.toString()}`, {
2933
3012
  selector: (response) => {
2934
3013
  if (!response.ok) throw new Error(`Failed to fetch threads: ${response.status}`);
2935
3014
  return response.json();
@@ -2944,7 +3023,8 @@ function createThreadFetchObservable(environment, context, sessionId) {
2944
3023
  }
2945
3024
  }), (0, rxjs_operators.map)((data) => threadRestEvents.listSucceeded({
2946
3025
  sessionId,
2947
- threads: data.threads
3026
+ threads: data.threads,
3027
+ nextCursor: data.nextCursor ?? null
2948
3028
  })), (0, rxjs_operators.catchError)((error) => {
2949
3029
  return (0, rxjs.of)(threadRestEvents.listFailed({
2950
3030
  sessionId,
@@ -3066,16 +3146,51 @@ function createThreadStore(environment) {
3066
3146
  }))),
3067
3147
  createEffect((actions$, state$) => actions$.pipe(ofType(threadSocketEvents.metadataReceived), (0, rxjs_operators.withLatestFrom)(state$), (0, rxjs_operators.filter)(([action, state]) => {
3068
3148
  return action.sessionId === state.sessionId && action.payload.userId === state.context?.userId;
3069
- }), (0, rxjs_operators.map)(([action]) => {
3149
+ }), (0, rxjs_operators.map)(([action, state]) => {
3070
3150
  if (action.payload.operation === "deleted") return threadDomainEvents.threadDeleted({
3071
3151
  sessionId: action.sessionId,
3072
3152
  threadId: action.payload.deleted.id
3073
3153
  });
3154
+ if (action.payload.operation === "archived" && !state.context?.includeArchived) return threadDomainEvents.threadDeleted({
3155
+ sessionId: action.sessionId,
3156
+ threadId: action.payload.threadId
3157
+ });
3074
3158
  return threadDomainEvents.threadUpserted({
3075
3159
  sessionId: action.sessionId,
3076
3160
  thread: action.payload.thread
3077
3161
  });
3078
3162
  }))),
3163
+ 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]) => {
3164
+ const context = state.context;
3165
+ const params = {
3166
+ userId: context.userId,
3167
+ agentId: context.agentId,
3168
+ cursor: state.nextCursor
3169
+ };
3170
+ if (context.includeArchived) params.includeArchived = "true";
3171
+ if (context.limit != null) params.limit = String(context.limit);
3172
+ return (0, rxjs_fetch.fromFetch)(`${context.runtimeUrl}/threads?${new URLSearchParams(params).toString()}`, {
3173
+ selector: (response) => {
3174
+ if (!response.ok) throw new Error(`Failed to fetch next page: ${response.status}`);
3175
+ return response.json();
3176
+ },
3177
+ fetch: environment.fetch,
3178
+ method: "GET",
3179
+ headers: { ...context.headers }
3180
+ }).pipe((0, rxjs_operators.timeout)({
3181
+ first: REQUEST_TIMEOUT_MS,
3182
+ with: () => {
3183
+ throw new Error("Request timed out");
3184
+ }
3185
+ }), (0, rxjs_operators.map)((data) => threadRestEvents.nextPageSucceeded({
3186
+ sessionId: state.sessionId,
3187
+ threads: data.threads,
3188
+ nextCursor: data.nextCursor ?? null
3189
+ })), (0, rxjs_operators.catchError)((error) => (0, rxjs.of)(threadRestEvents.nextPageFailed({
3190
+ sessionId: state.sessionId,
3191
+ error: error instanceof Error ? error : new Error(String(error))
3192
+ }))), (0, rxjs_operators.takeUntil)(actions$.pipe(ofType(threadAdapterEvents.contextChanged, threadAdapterEvents.stopped))));
3193
+ }))),
3079
3194
  createEffect((actions$, state$) => actions$.pipe(ofType(threadAdapterEvents.renameRequested, threadAdapterEvents.archiveRequested, threadAdapterEvents.deleteRequested), (0, rxjs_operators.withLatestFrom)(state$), (0, rxjs_operators.mergeMap)(([action, state]) => {
3080
3195
  const context = state.context;
3081
3196
  if (!context?.runtimeUrl) {
@@ -3138,6 +3253,9 @@ function createThreadStore(environment) {
3138
3253
  setContext(context) {
3139
3254
  store.dispatch(threadAdapterEvents.contextChanged({ context }));
3140
3255
  },
3256
+ fetchNextPage() {
3257
+ store.dispatch(threadAdapterEvents.fetchNextPageRequested());
3258
+ },
3141
3259
  renameThread(threadId, name) {
3142
3260
  return trackMutation(threadAdapterEvents.renameRequested({
3143
3261
  requestId: createThreadRequestId(),
@@ -3167,6 +3285,8 @@ const ɵthreadAdapterEvents = threadAdapterEvents;
3167
3285
  const ɵselectThreads = selectThreads;
3168
3286
  const ɵselectThreadsIsLoading = selectThreadsIsLoading;
3169
3287
  const ɵselectThreadsError = selectThreadsError;
3288
+ const ɵselectHasNextPage = selectHasNextPage;
3289
+ const ɵselectIsFetchingNextPage = selectIsFetchingNextPage;
3170
3290
 
3171
3291
  //#endregion
3172
3292
  exports.AgentRegistry = AgentRegistry;
@@ -3201,6 +3321,8 @@ exports.ɵobservePhoenixSocketHealth$ = ɵobservePhoenixSocketHealth$;
3201
3321
  exports.ɵobservePhoenixSocketSignals$ = ɵobservePhoenixSocketSignals$;
3202
3322
  exports.ɵphoenixChannel$ = ɵphoenixChannel$;
3203
3323
  exports.ɵphoenixSocket$ = ɵphoenixSocket$;
3324
+ exports.ɵselectHasNextPage = ɵselectHasNextPage;
3325
+ exports.ɵselectIsFetchingNextPage = ɵselectIsFetchingNextPage;
3204
3326
  exports.ɵselectThreads = ɵselectThreads;
3205
3327
  exports.ɵselectThreadsError = ɵselectThreadsError;
3206
3328
  exports.ɵselectThreadsIsLoading = ɵselectThreadsIsLoading;