@copilotkitnext/core 1.54.1-next.5 → 1.54.1

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,19 @@ 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
+ metadataJoinCode: null,
2858
+ nextCursor: null
2815
2859
  };
2816
2860
  const threadAdapterEvents = createActionGroup("Thread Adapter", {
2817
2861
  started: empty(),
2818
2862
  stopped: empty(),
2819
2863
  contextChanged: props(),
2864
+ fetchNextPageRequested: empty(),
2820
2865
  renameRequested: props(),
2821
2866
  archiveRequested: props(),
2822
2867
  deleteRequested: props()
@@ -2825,6 +2870,8 @@ const threadRestEvents = createActionGroup("Thread REST", {
2825
2870
  listRequested: props(),
2826
2871
  listSucceeded: props(),
2827
2872
  listFailed: props(),
2873
+ nextPageSucceeded: props(),
2874
+ nextPageFailed: props(),
2828
2875
  metadataCredentialsRequested: props(),
2829
2876
  metadataCredentialsSucceeded: props(),
2830
2877
  metadataCredentialsFailed: props(),
@@ -2857,14 +2904,20 @@ const threadReducer = createReducer(initialThreadState, on(threadAdapterEvents.c
2857
2904
  sessionId: state.sessionId + 1,
2858
2905
  threads: [],
2859
2906
  isLoading: Boolean(context),
2907
+ isFetchingNextPage: false,
2860
2908
  error: null,
2861
- metadataCredentialsRequested: false
2909
+ metadataCredentialsRequested: false,
2910
+ metadataJoinCode: null,
2911
+ nextCursor: null
2862
2912
  })), on(threadAdapterEvents.stopped, (state) => ({
2863
2913
  ...state,
2864
2914
  threads: [],
2865
2915
  isLoading: false,
2916
+ isFetchingNextPage: false,
2866
2917
  error: null,
2867
- metadataCredentialsRequested: false
2918
+ metadataCredentialsRequested: false,
2919
+ metadataJoinCode: null,
2920
+ nextCursor: null
2868
2921
  })), on(threadRestEvents.listRequested, (state, { sessionId }) => {
2869
2922
  if (sessionId !== state.sessionId || !state.context) return state;
2870
2923
  return {
@@ -2872,13 +2925,15 @@ const threadReducer = createReducer(initialThreadState, on(threadAdapterEvents.c
2872
2925
  isLoading: true,
2873
2926
  error: null
2874
2927
  };
2875
- }), on(threadRestEvents.listSucceeded, (state, { sessionId, threads }) => {
2928
+ }), on(threadRestEvents.listSucceeded, (state, { sessionId, threads, joinCode, nextCursor }) => {
2876
2929
  if (sessionId !== state.sessionId) return state;
2877
2930
  return {
2878
2931
  ...state,
2879
2932
  threads: sortThreadsByUpdatedAt(threads),
2880
2933
  isLoading: false,
2881
- error: null
2934
+ error: null,
2935
+ metadataJoinCode: joinCode,
2936
+ nextCursor
2882
2937
  };
2883
2938
  }), on(threadRestEvents.listFailed, (state, { sessionId, error }) => {
2884
2939
  if (sessionId !== state.sessionId) return state;
@@ -2887,6 +2942,23 @@ const threadReducer = createReducer(initialThreadState, on(threadAdapterEvents.c
2887
2942
  isLoading: false,
2888
2943
  error
2889
2944
  };
2945
+ }), on(threadRestEvents.nextPageSucceeded, (state, { sessionId, threads, nextCursor }) => {
2946
+ if (sessionId !== state.sessionId) return state;
2947
+ let merged = state.threads;
2948
+ for (const thread of threads) merged = upsertThread(merged, thread);
2949
+ return {
2950
+ ...state,
2951
+ threads: merged,
2952
+ isFetchingNextPage: false,
2953
+ nextCursor
2954
+ };
2955
+ }), on(threadRestEvents.nextPageFailed, (state, { sessionId, error }) => {
2956
+ if (sessionId !== state.sessionId) return state;
2957
+ return {
2958
+ ...state,
2959
+ isFetchingNextPage: false,
2960
+ error
2961
+ };
2890
2962
  }), on(threadRestEvents.metadataCredentialsFailed, (state, { sessionId, error }) => {
2891
2963
  if (sessionId !== state.sessionId) return state;
2892
2964
  return {
@@ -2899,6 +2971,12 @@ const threadReducer = createReducer(initialThreadState, on(threadAdapterEvents.c
2899
2971
  ...state,
2900
2972
  metadataCredentialsRequested: true
2901
2973
  };
2974
+ }), on(threadAdapterEvents.fetchNextPageRequested, (state) => {
2975
+ if (!state.nextCursor || state.isFetchingNextPage) return state;
2976
+ return {
2977
+ ...state,
2978
+ isFetchingNextPage: true
2979
+ };
2902
2980
  }), on(threadRestEvents.mutationFinished, (state, { outcome }) => ({
2903
2981
  ...state,
2904
2982
  error: outcome.ok ? state.error : outcome.error
@@ -2918,6 +2996,8 @@ const threadReducer = createReducer(initialThreadState, on(threadAdapterEvents.c
2918
2996
  const selectThreads = createSelector((state) => state.threads);
2919
2997
  const selectThreadsIsLoading = createSelector((state) => state.isLoading);
2920
2998
  const selectThreadsError = createSelector((state) => state.error);
2999
+ const selectHasNextPage = createSelector((state) => state.nextCursor != null);
3000
+ const selectIsFetchingNextPage = createSelector((state) => state.isFetchingNextPage);
2921
3001
  let threadRequestId = 0;
2922
3002
  function createThreadRequestId() {
2923
3003
  threadRequestId += 1;
@@ -2925,11 +3005,11 @@ function createThreadRequestId() {
2925
3005
  }
2926
3006
  function createThreadFetchObservable(environment, context, sessionId) {
2927
3007
  return (0, rxjs.defer)(() => {
2928
- const params = new URLSearchParams({
2929
- userId: context.userId,
2930
- agentId: context.agentId
2931
- });
2932
- return (0, rxjs_fetch.fromFetch)(`${context.runtimeUrl}/threads?${params.toString()}`, {
3008
+ const params = { agentId: context.agentId };
3009
+ if (context.includeArchived) params.includeArchived = "true";
3010
+ if (context.limit != null) params.limit = String(context.limit);
3011
+ const qs = new URLSearchParams(params);
3012
+ return (0, rxjs_fetch.fromFetch)(`${context.runtimeUrl}/threads?${qs.toString()}`, {
2933
3013
  selector: (response) => {
2934
3014
  if (!response.ok) throw new Error(`Failed to fetch threads: ${response.status}`);
2935
3015
  return response.json();
@@ -2944,7 +3024,9 @@ function createThreadFetchObservable(environment, context, sessionId) {
2944
3024
  }
2945
3025
  }), (0, rxjs_operators.map)((data) => threadRestEvents.listSucceeded({
2946
3026
  sessionId,
2947
- threads: data.threads
3027
+ threads: data.threads,
3028
+ joinCode: typeof data.joinCode === "string" && data.joinCode.length > 0 ? data.joinCode : null,
3029
+ nextCursor: data.nextCursor ?? null
2948
3030
  })), (0, rxjs_operators.catchError)((error) => {
2949
3031
  return (0, rxjs.of)(threadRestEvents.listFailed({
2950
3032
  sessionId,
@@ -2966,7 +3048,7 @@ function createThreadMetadataCredentialsObservable(environment, context, session
2966
3048
  ...context.headers,
2967
3049
  "Content-Type": "application/json"
2968
3050
  },
2969
- body: JSON.stringify({ userId: context.userId })
3051
+ body: JSON.stringify({})
2970
3052
  }).pipe((0, rxjs_operators.timeout)({
2971
3053
  first: REQUEST_TIMEOUT_MS,
2972
3054
  with: () => {
@@ -3022,7 +3104,7 @@ function createThreadStore(environment) {
3022
3104
  context
3023
3105
  })), (0, rxjs_operators.takeUntil)(actions$.pipe(ofType(threadAdapterEvents.contextChanged, threadAdapterEvents.stopped))), (0, rxjs_operators.switchMap)(({ action: currentAction, context }) => createThreadFetchObservable(environment, context, currentAction.sessionId)))))),
3024
3106
  createEffect((actions$, state$) => actions$.pipe(ofType(threadRestEvents.listSucceeded), (0, rxjs_operators.withLatestFrom)(state$), (0, rxjs_operators.filter)(([action, state]) => {
3025
- return action.sessionId === state.sessionId && !state.metadataCredentialsRequested && Boolean(state.context?.wsUrl);
3107
+ return action.sessionId === state.sessionId && !state.metadataCredentialsRequested && Boolean(state.context?.wsUrl) && Boolean(state.metadataJoinCode);
3026
3108
  }), (0, rxjs_operators.map)(([action]) => threadRestEvents.metadataCredentialsRequested({ sessionId: action.sessionId })))),
3027
3109
  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) => ({
3028
3110
  action,
@@ -3033,6 +3115,7 @@ function createThreadStore(environment) {
3033
3115
  }), (0, rxjs_operators.switchMap)(([action, state]) => {
3034
3116
  const context = state.context;
3035
3117
  const joinToken = action.joinToken;
3118
+ const joinCode = state.metadataJoinCode;
3036
3119
  const shutdown$ = actions$.pipe(ofType(threadAdapterEvents.contextChanged, threadAdapterEvents.stopped));
3037
3120
  return (0, rxjs.defer)(() => {
3038
3121
  const socket$ = ɵphoenixSocket$({
@@ -3048,7 +3131,7 @@ function createThreadStore(environment) {
3048
3131
  }));
3049
3132
  const channel$ = ɵphoenixChannel$({
3050
3133
  socket$,
3051
- topic: `user_meta:${context.userId}`
3134
+ topic: `user_meta:${joinCode}`
3052
3135
  }).pipe((0, rxjs_operators.shareReplay)({
3053
3136
  bufferSize: 1,
3054
3137
  refCount: true
@@ -3064,18 +3147,50 @@ function createThreadStore(environment) {
3064
3147
  }))), ɵobservePhoenixJoinOutcome$(channel$).pipe((0, rxjs_operators.filter)((outcome) => outcome.type !== "joined"), (0, rxjs_operators.map)((outcome) => outcome.type === "timeout" ? threadSocketEvents.joinTimedOut({ sessionId: action.sessionId }) : threadSocketEvents.joinFailed({ sessionId: action.sessionId })))).pipe((0, rxjs_operators.takeUntil)((0, rxjs.merge)(shutdown$, fatalSocketShutdown$)));
3065
3148
  });
3066
3149
  }))),
3067
- createEffect((actions$, state$) => actions$.pipe(ofType(threadSocketEvents.metadataReceived), (0, rxjs_operators.withLatestFrom)(state$), (0, rxjs_operators.filter)(([action, state]) => {
3068
- return action.sessionId === state.sessionId && action.payload.userId === state.context?.userId;
3069
- }), (0, rxjs_operators.map)(([action]) => {
3150
+ 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]) => {
3070
3151
  if (action.payload.operation === "deleted") return threadDomainEvents.threadDeleted({
3071
3152
  sessionId: action.sessionId,
3072
3153
  threadId: action.payload.deleted.id
3073
3154
  });
3155
+ if (action.payload.operation === "archived" && !state.context?.includeArchived) return threadDomainEvents.threadDeleted({
3156
+ sessionId: action.sessionId,
3157
+ threadId: action.payload.threadId
3158
+ });
3074
3159
  return threadDomainEvents.threadUpserted({
3075
3160
  sessionId: action.sessionId,
3076
3161
  thread: action.payload.thread
3077
3162
  });
3078
3163
  }))),
3164
+ 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]) => {
3165
+ const context = state.context;
3166
+ const params = {
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) {
@@ -3086,10 +3201,7 @@ function createThreadStore(environment) {
3086
3201
  error: /* @__PURE__ */ new Error("Runtime URL is not configured")
3087
3202
  } }));
3088
3203
  }
3089
- const commonBody = {
3090
- userId: context.userId,
3091
- agentId: context.agentId
3092
- };
3204
+ const commonBody = { agentId: context.agentId };
3093
3205
  if (threadAdapterEvents.renameRequested.match(action)) return createThreadMutationObservable(environment, context, {
3094
3206
  requestId: action.requestId,
3095
3207
  method: "PATCH",
@@ -3138,6 +3250,9 @@ function createThreadStore(environment) {
3138
3250
  setContext(context) {
3139
3251
  store.dispatch(threadAdapterEvents.contextChanged({ context }));
3140
3252
  },
3253
+ fetchNextPage() {
3254
+ store.dispatch(threadAdapterEvents.fetchNextPageRequested());
3255
+ },
3141
3256
  renameThread(threadId, name) {
3142
3257
  return trackMutation(threadAdapterEvents.renameRequested({
3143
3258
  requestId: createThreadRequestId(),
@@ -3167,6 +3282,8 @@ const ɵthreadAdapterEvents = threadAdapterEvents;
3167
3282
  const ɵselectThreads = selectThreads;
3168
3283
  const ɵselectThreadsIsLoading = selectThreadsIsLoading;
3169
3284
  const ɵselectThreadsError = selectThreadsError;
3285
+ const ɵselectHasNextPage = selectHasNextPage;
3286
+ const ɵselectIsFetchingNextPage = selectIsFetchingNextPage;
3170
3287
 
3171
3288
  //#endregion
3172
3289
  exports.AgentRegistry = AgentRegistry;
@@ -3201,6 +3318,8 @@ exports.ɵobservePhoenixSocketHealth$ = ɵobservePhoenixSocketHealth$;
3201
3318
  exports.ɵobservePhoenixSocketSignals$ = ɵobservePhoenixSocketSignals$;
3202
3319
  exports.ɵphoenixChannel$ = ɵphoenixChannel$;
3203
3320
  exports.ɵphoenixSocket$ = ɵphoenixSocket$;
3321
+ exports.ɵselectHasNextPage = ɵselectHasNextPage;
3322
+ exports.ɵselectIsFetchingNextPage = ɵselectIsFetchingNextPage;
3204
3323
  exports.ɵselectThreads = ɵselectThreads;
3205
3324
  exports.ɵselectThreadsError = ɵselectThreadsError;
3206
3325
  exports.ɵselectThreadsIsLoading = ɵselectThreadsIsLoading;