@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.mjs CHANGED
@@ -491,9 +491,12 @@ function hasCredentials(agent) {
491
491
  function isZodError(error) {
492
492
  return error !== null && typeof error === "object" && "name" in error && error.name === "ZodError";
493
493
  }
494
+ function isAbortError(error) {
495
+ return (error instanceof DOMException || error instanceof Error) && error.name === "AbortError";
496
+ }
494
497
  function withAbortErrorHandling(observable) {
495
498
  return observable.pipe(catchError((error) => {
496
- if (isZodError(error)) return EMPTY;
499
+ if (isZodError(error) || isAbortError(error)) return EMPTY;
497
500
  throw error;
498
501
  }));
499
502
  }
@@ -1370,10 +1373,31 @@ const SUGGEST_TOOL = {
1370
1373
  */
1371
1374
  var RunHandler = class {
1372
1375
  _tools = [];
1376
+ /**
1377
+ * Tracks whether the current run (including in-flight tool execution)
1378
+ * has been aborted via `stopAgent()` or `agent.abortRun()`. Created
1379
+ * fresh in `runAgent()`, aborted by `abortCurrentRun()`.
1380
+ */
1381
+ _runAbortController = null;
1382
+ /**
1383
+ * Tracks recursive `runAgent` depth so that the abort controller and
1384
+ * `agent.abortRun()` intercept are only set up / torn down at the
1385
+ * top-level call, not on follow-up recursive calls from
1386
+ * `processAgentResult`.
1387
+ */
1388
+ _runDepth = 0;
1373
1389
  constructor(core) {
1374
1390
  this.core = core;
1375
1391
  }
1376
1392
  /**
1393
+ * Abort the current run. Called by `CopilotKitCore.stopAgent()` to signal
1394
+ * that in-flight tool handlers should stop and `processAgentResult` should
1395
+ * not start a follow-up run.
1396
+ */
1397
+ abortCurrentRun() {
1398
+ this._runAbortController?.abort();
1399
+ }
1400
+ /**
1377
1401
  * Typed access to CopilotKitCore's internal ("friend") methods.
1378
1402
  * Centralises the single unavoidable cast so call-sites stay clean.
1379
1403
  */
@@ -1467,6 +1491,18 @@ var RunHandler = class {
1467
1491
  if (agent.agentId) this._internal.suggestionEngine.clearSuggestions(agent.agentId);
1468
1492
  if (agent instanceof HttpAgent) agent.headers = { ...this._internal.headers };
1469
1493
  if (agent.detachActiveRun) await agent.detachActiveRun();
1494
+ const isTopLevel = this._runDepth === 0;
1495
+ let originalAbortRun;
1496
+ if (isTopLevel) {
1497
+ this._runAbortController = new AbortController();
1498
+ const controller = this._runAbortController;
1499
+ originalAbortRun = agent.abortRun.bind(agent);
1500
+ agent.abortRun = () => {
1501
+ controller.abort();
1502
+ originalAbortRun();
1503
+ };
1504
+ }
1505
+ this._runDepth++;
1470
1506
  try {
1471
1507
  const runAgentResult = await agent.runAgent({
1472
1508
  forwardedProps: {
@@ -1476,7 +1512,7 @@ var RunHandler = class {
1476
1512
  tools: this.buildFrontendTools(agent.agentId),
1477
1513
  context: Object.values(this._internal.context)
1478
1514
  }, this.createAgentErrorSubscriber(agent));
1479
- return this.processAgentResult({
1515
+ return await this.processAgentResult({
1480
1516
  runAgentResult,
1481
1517
  agent
1482
1518
  });
@@ -1490,6 +1526,9 @@ var RunHandler = class {
1490
1526
  context
1491
1527
  });
1492
1528
  return { newMessages: [] };
1529
+ } finally {
1530
+ this._runDepth--;
1531
+ if (isTopLevel && originalAbortRun) agent.abortRun = originalAbortRun;
1493
1532
  }
1494
1533
  }
1495
1534
  /**
@@ -1518,7 +1557,7 @@ var RunHandler = class {
1518
1557
  }
1519
1558
  }
1520
1559
  }
1521
- if (needsFollowUp) {
1560
+ if (needsFollowUp && !this._runAbortController?.signal.aborted) {
1522
1561
  await this._internal.waitForPendingFrameworkUpdates();
1523
1562
  return await this.runAgent({ agent });
1524
1563
  }
@@ -1564,7 +1603,8 @@ var RunHandler = class {
1564
1603
  if (!errorMessage) try {
1565
1604
  const result = await tool.handler(parsedArgs, {
1566
1605
  toolCall,
1567
- agent
1606
+ agent,
1607
+ signal: this._runAbortController?.signal
1568
1608
  });
1569
1609
  if (result === void 0 || result === null) toolCallResult = "";
1570
1610
  else if (typeof result === "string") toolCallResult = result;
@@ -2310,6 +2350,7 @@ var CopilotKitCore = class {
2310
2350
  return this.runHandler.connectAgent(params);
2311
2351
  }
2312
2352
  stopAgent(params) {
2353
+ this.runHandler.abortCurrentRun();
2313
2354
  params.agent.abortRun();
2314
2355
  }
2315
2356
  async runAgent(params) {
@@ -2807,15 +2848,19 @@ const REQUEST_TIMEOUT_MS = 15e3;
2807
2848
  const initialThreadState = {
2808
2849
  threads: [],
2809
2850
  isLoading: false,
2851
+ isFetchingNextPage: false,
2810
2852
  error: null,
2811
2853
  context: null,
2812
2854
  sessionId: 0,
2813
- metadataCredentialsRequested: false
2855
+ metadataCredentialsRequested: false,
2856
+ metadataJoinCode: null,
2857
+ nextCursor: null
2814
2858
  };
2815
2859
  const threadAdapterEvents = createActionGroup("Thread Adapter", {
2816
2860
  started: empty(),
2817
2861
  stopped: empty(),
2818
2862
  contextChanged: props(),
2863
+ fetchNextPageRequested: empty(),
2819
2864
  renameRequested: props(),
2820
2865
  archiveRequested: props(),
2821
2866
  deleteRequested: props()
@@ -2824,6 +2869,8 @@ const threadRestEvents = createActionGroup("Thread REST", {
2824
2869
  listRequested: props(),
2825
2870
  listSucceeded: props(),
2826
2871
  listFailed: props(),
2872
+ nextPageSucceeded: props(),
2873
+ nextPageFailed: props(),
2827
2874
  metadataCredentialsRequested: props(),
2828
2875
  metadataCredentialsSucceeded: props(),
2829
2876
  metadataCredentialsFailed: props(),
@@ -2856,14 +2903,20 @@ const threadReducer = createReducer(initialThreadState, on(threadAdapterEvents.c
2856
2903
  sessionId: state.sessionId + 1,
2857
2904
  threads: [],
2858
2905
  isLoading: Boolean(context),
2906
+ isFetchingNextPage: false,
2859
2907
  error: null,
2860
- metadataCredentialsRequested: false
2908
+ metadataCredentialsRequested: false,
2909
+ metadataJoinCode: null,
2910
+ nextCursor: null
2861
2911
  })), on(threadAdapterEvents.stopped, (state) => ({
2862
2912
  ...state,
2863
2913
  threads: [],
2864
2914
  isLoading: false,
2915
+ isFetchingNextPage: false,
2865
2916
  error: null,
2866
- metadataCredentialsRequested: false
2917
+ metadataCredentialsRequested: false,
2918
+ metadataJoinCode: null,
2919
+ nextCursor: null
2867
2920
  })), on(threadRestEvents.listRequested, (state, { sessionId }) => {
2868
2921
  if (sessionId !== state.sessionId || !state.context) return state;
2869
2922
  return {
@@ -2871,13 +2924,15 @@ const threadReducer = createReducer(initialThreadState, on(threadAdapterEvents.c
2871
2924
  isLoading: true,
2872
2925
  error: null
2873
2926
  };
2874
- }), on(threadRestEvents.listSucceeded, (state, { sessionId, threads }) => {
2927
+ }), on(threadRestEvents.listSucceeded, (state, { sessionId, threads, joinCode, nextCursor }) => {
2875
2928
  if (sessionId !== state.sessionId) return state;
2876
2929
  return {
2877
2930
  ...state,
2878
2931
  threads: sortThreadsByUpdatedAt(threads),
2879
2932
  isLoading: false,
2880
- error: null
2933
+ error: null,
2934
+ metadataJoinCode: joinCode,
2935
+ nextCursor
2881
2936
  };
2882
2937
  }), on(threadRestEvents.listFailed, (state, { sessionId, error }) => {
2883
2938
  if (sessionId !== state.sessionId) return state;
@@ -2886,6 +2941,23 @@ const threadReducer = createReducer(initialThreadState, on(threadAdapterEvents.c
2886
2941
  isLoading: false,
2887
2942
  error
2888
2943
  };
2944
+ }), on(threadRestEvents.nextPageSucceeded, (state, { sessionId, threads, nextCursor }) => {
2945
+ if (sessionId !== state.sessionId) return state;
2946
+ let merged = state.threads;
2947
+ for (const thread of threads) merged = upsertThread(merged, thread);
2948
+ return {
2949
+ ...state,
2950
+ threads: merged,
2951
+ isFetchingNextPage: false,
2952
+ nextCursor
2953
+ };
2954
+ }), on(threadRestEvents.nextPageFailed, (state, { sessionId, error }) => {
2955
+ if (sessionId !== state.sessionId) return state;
2956
+ return {
2957
+ ...state,
2958
+ isFetchingNextPage: false,
2959
+ error
2960
+ };
2889
2961
  }), on(threadRestEvents.metadataCredentialsFailed, (state, { sessionId, error }) => {
2890
2962
  if (sessionId !== state.sessionId) return state;
2891
2963
  return {
@@ -2898,6 +2970,12 @@ const threadReducer = createReducer(initialThreadState, on(threadAdapterEvents.c
2898
2970
  ...state,
2899
2971
  metadataCredentialsRequested: true
2900
2972
  };
2973
+ }), on(threadAdapterEvents.fetchNextPageRequested, (state) => {
2974
+ if (!state.nextCursor || state.isFetchingNextPage) return state;
2975
+ return {
2976
+ ...state,
2977
+ isFetchingNextPage: true
2978
+ };
2901
2979
  }), on(threadRestEvents.mutationFinished, (state, { outcome }) => ({
2902
2980
  ...state,
2903
2981
  error: outcome.ok ? state.error : outcome.error
@@ -2917,6 +2995,8 @@ const threadReducer = createReducer(initialThreadState, on(threadAdapterEvents.c
2917
2995
  const selectThreads = createSelector((state) => state.threads);
2918
2996
  const selectThreadsIsLoading = createSelector((state) => state.isLoading);
2919
2997
  const selectThreadsError = createSelector((state) => state.error);
2998
+ const selectHasNextPage = createSelector((state) => state.nextCursor != null);
2999
+ const selectIsFetchingNextPage = createSelector((state) => state.isFetchingNextPage);
2920
3000
  let threadRequestId = 0;
2921
3001
  function createThreadRequestId() {
2922
3002
  threadRequestId += 1;
@@ -2924,11 +3004,11 @@ function createThreadRequestId() {
2924
3004
  }
2925
3005
  function createThreadFetchObservable(environment, context, sessionId) {
2926
3006
  return defer(() => {
2927
- const params = new URLSearchParams({
2928
- userId: context.userId,
2929
- agentId: context.agentId
2930
- });
2931
- return fromFetch(`${context.runtimeUrl}/threads?${params.toString()}`, {
3007
+ const params = { agentId: context.agentId };
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 fromFetch(`${context.runtimeUrl}/threads?${qs.toString()}`, {
2932
3012
  selector: (response) => {
2933
3013
  if (!response.ok) throw new Error(`Failed to fetch threads: ${response.status}`);
2934
3014
  return response.json();
@@ -2943,7 +3023,9 @@ function createThreadFetchObservable(environment, context, sessionId) {
2943
3023
  }
2944
3024
  }), map((data) => threadRestEvents.listSucceeded({
2945
3025
  sessionId,
2946
- threads: data.threads
3026
+ threads: data.threads,
3027
+ joinCode: typeof data.joinCode === "string" && data.joinCode.length > 0 ? data.joinCode : null,
3028
+ nextCursor: data.nextCursor ?? null
2947
3029
  })), catchError((error) => {
2948
3030
  return of(threadRestEvents.listFailed({
2949
3031
  sessionId,
@@ -2965,7 +3047,7 @@ function createThreadMetadataCredentialsObservable(environment, context, session
2965
3047
  ...context.headers,
2966
3048
  "Content-Type": "application/json"
2967
3049
  },
2968
- body: JSON.stringify({ userId: context.userId })
3050
+ body: JSON.stringify({})
2969
3051
  }).pipe(timeout({
2970
3052
  first: REQUEST_TIMEOUT_MS,
2971
3053
  with: () => {
@@ -3021,7 +3103,7 @@ function createThreadStore(environment) {
3021
3103
  context
3022
3104
  })), takeUntil(actions$.pipe(ofType(threadAdapterEvents.contextChanged, threadAdapterEvents.stopped))), switchMap$1(({ action: currentAction, context }) => createThreadFetchObservable(environment, context, currentAction.sessionId)))))),
3023
3105
  createEffect((actions$, state$) => actions$.pipe(ofType(threadRestEvents.listSucceeded), withLatestFrom(state$), filter(([action, state]) => {
3024
- return action.sessionId === state.sessionId && !state.metadataCredentialsRequested && Boolean(state.context?.wsUrl);
3106
+ return action.sessionId === state.sessionId && !state.metadataCredentialsRequested && Boolean(state.context?.wsUrl) && Boolean(state.metadataJoinCode);
3025
3107
  }), map(([action]) => threadRestEvents.metadataCredentialsRequested({ sessionId: action.sessionId })))),
3026
3108
  createEffect((actions$, state$) => actions$.pipe(ofType(threadRestEvents.metadataCredentialsRequested), switchMap$1((action) => state$.pipe(map((state) => state.context), filter((context) => Boolean(context)), take(1), map((context) => ({
3027
3109
  action,
@@ -3032,6 +3114,7 @@ function createThreadStore(environment) {
3032
3114
  }), switchMap$1(([action, state]) => {
3033
3115
  const context = state.context;
3034
3116
  const joinToken = action.joinToken;
3117
+ const joinCode = state.metadataJoinCode;
3035
3118
  const shutdown$ = actions$.pipe(ofType(threadAdapterEvents.contextChanged, threadAdapterEvents.stopped));
3036
3119
  return defer(() => {
3037
3120
  const socket$ = ɵphoenixSocket$({
@@ -3047,7 +3130,7 @@ function createThreadStore(environment) {
3047
3130
  }));
3048
3131
  const channel$ = ɵphoenixChannel$({
3049
3132
  socket$,
3050
- topic: `user_meta:${context.userId}`
3133
+ topic: `user_meta:${joinCode}`
3051
3134
  }).pipe(shareReplay({
3052
3135
  bufferSize: 1,
3053
3136
  refCount: true
@@ -3063,18 +3146,50 @@ function createThreadStore(environment) {
3063
3146
  }))), ɵobservePhoenixJoinOutcome$(channel$).pipe(filter((outcome) => outcome.type !== "joined"), map((outcome) => outcome.type === "timeout" ? threadSocketEvents.joinTimedOut({ sessionId: action.sessionId }) : threadSocketEvents.joinFailed({ sessionId: action.sessionId })))).pipe(takeUntil(merge(shutdown$, fatalSocketShutdown$)));
3064
3147
  });
3065
3148
  }))),
3066
- createEffect((actions$, state$) => actions$.pipe(ofType(threadSocketEvents.metadataReceived), withLatestFrom(state$), filter(([action, state]) => {
3067
- return action.sessionId === state.sessionId && action.payload.userId === state.context?.userId;
3068
- }), map(([action]) => {
3149
+ createEffect((actions$, state$) => actions$.pipe(ofType(threadSocketEvents.metadataReceived), withLatestFrom(state$), filter(([action, state]) => action.sessionId === state.sessionId), map(([action, state]) => {
3069
3150
  if (action.payload.operation === "deleted") return threadDomainEvents.threadDeleted({
3070
3151
  sessionId: action.sessionId,
3071
3152
  threadId: action.payload.deleted.id
3072
3153
  });
3154
+ if (action.payload.operation === "archived" && !state.context?.includeArchived) return threadDomainEvents.threadDeleted({
3155
+ sessionId: action.sessionId,
3156
+ threadId: action.payload.threadId
3157
+ });
3073
3158
  return threadDomainEvents.threadUpserted({
3074
3159
  sessionId: action.sessionId,
3075
3160
  thread: action.payload.thread
3076
3161
  });
3077
3162
  }))),
3163
+ createEffect((actions$, state$) => actions$.pipe(ofType(threadAdapterEvents.fetchNextPageRequested), withLatestFrom(state$), filter(([, state]) => Boolean(state.context) && Boolean(state.nextCursor)), switchMap$1(([, state]) => {
3164
+ const context = state.context;
3165
+ const params = {
3166
+ agentId: context.agentId,
3167
+ cursor: state.nextCursor
3168
+ };
3169
+ if (context.includeArchived) params.includeArchived = "true";
3170
+ if (context.limit != null) params.limit = String(context.limit);
3171
+ return fromFetch(`${context.runtimeUrl}/threads?${new URLSearchParams(params).toString()}`, {
3172
+ selector: (response) => {
3173
+ if (!response.ok) throw new Error(`Failed to fetch next page: ${response.status}`);
3174
+ return response.json();
3175
+ },
3176
+ fetch: environment.fetch,
3177
+ method: "GET",
3178
+ headers: { ...context.headers }
3179
+ }).pipe(timeout({
3180
+ first: REQUEST_TIMEOUT_MS,
3181
+ with: () => {
3182
+ throw new Error("Request timed out");
3183
+ }
3184
+ }), map((data) => threadRestEvents.nextPageSucceeded({
3185
+ sessionId: state.sessionId,
3186
+ threads: data.threads,
3187
+ nextCursor: data.nextCursor ?? null
3188
+ })), catchError((error) => of(threadRestEvents.nextPageFailed({
3189
+ sessionId: state.sessionId,
3190
+ error: error instanceof Error ? error : new Error(String(error))
3191
+ }))), takeUntil(actions$.pipe(ofType(threadAdapterEvents.contextChanged, threadAdapterEvents.stopped))));
3192
+ }))),
3078
3193
  createEffect((actions$, state$) => actions$.pipe(ofType(threadAdapterEvents.renameRequested, threadAdapterEvents.archiveRequested, threadAdapterEvents.deleteRequested), withLatestFrom(state$), mergeMap(([action, state]) => {
3079
3194
  const context = state.context;
3080
3195
  if (!context?.runtimeUrl) {
@@ -3085,10 +3200,7 @@ function createThreadStore(environment) {
3085
3200
  error: /* @__PURE__ */ new Error("Runtime URL is not configured")
3086
3201
  } }));
3087
3202
  }
3088
- const commonBody = {
3089
- userId: context.userId,
3090
- agentId: context.agentId
3091
- };
3203
+ const commonBody = { agentId: context.agentId };
3092
3204
  if (threadAdapterEvents.renameRequested.match(action)) return createThreadMutationObservable(environment, context, {
3093
3205
  requestId: action.requestId,
3094
3206
  method: "PATCH",
@@ -3137,6 +3249,9 @@ function createThreadStore(environment) {
3137
3249
  setContext(context) {
3138
3250
  store.dispatch(threadAdapterEvents.contextChanged({ context }));
3139
3251
  },
3252
+ fetchNextPage() {
3253
+ store.dispatch(threadAdapterEvents.fetchNextPageRequested());
3254
+ },
3140
3255
  renameThread(threadId, name) {
3141
3256
  return trackMutation(threadAdapterEvents.renameRequested({
3142
3257
  requestId: createThreadRequestId(),
@@ -3166,7 +3281,9 @@ const ɵthreadAdapterEvents = threadAdapterEvents;
3166
3281
  const ɵselectThreads = selectThreads;
3167
3282
  const ɵselectThreadsIsLoading = selectThreadsIsLoading;
3168
3283
  const ɵselectThreadsError = selectThreadsError;
3284
+ const ɵselectHasNextPage = selectHasNextPage;
3285
+ const ɵselectIsFetchingNextPage = selectIsFetchingNextPage;
3169
3286
 
3170
3287
  //#endregion
3171
- export { AgentRegistry, ContextStore, CopilotKitCore, CopilotKitCoreErrorCode, CopilotKitCoreRuntimeConnectionStatus, IntelligenceAgent, ProxiedCopilotRuntimeAgent, RunHandler, StateManager, SuggestionEngine, ToolCallStatus, completePartialMarkdown, createActionGroup, createEffect, createReducer, createSelector, createStore, empty, ensureObjectArgs, ofType, on, parseToolArguments, props, select, createThreadStore as ɵcreateThreadStore, ɵjoinPhoenixChannel$, ɵobservePhoenixEvent$, ɵobservePhoenixJoinOutcome$, ɵobservePhoenixSocketHealth$, ɵobservePhoenixSocketSignals$, ɵphoenixChannel$, ɵphoenixSocket$, ɵselectThreads, ɵselectThreadsError, ɵselectThreadsIsLoading, ɵthreadAdapterEvents };
3288
+ export { AgentRegistry, ContextStore, CopilotKitCore, CopilotKitCoreErrorCode, CopilotKitCoreRuntimeConnectionStatus, IntelligenceAgent, ProxiedCopilotRuntimeAgent, RunHandler, StateManager, SuggestionEngine, ToolCallStatus, completePartialMarkdown, createActionGroup, createEffect, createReducer, createSelector, createStore, empty, ensureObjectArgs, ofType, on, parseToolArguments, props, select, createThreadStore as ɵcreateThreadStore, ɵjoinPhoenixChannel$, ɵobservePhoenixEvent$, ɵobservePhoenixJoinOutcome$, ɵobservePhoenixSocketHealth$, ɵobservePhoenixSocketSignals$, ɵphoenixChannel$, ɵphoenixSocket$, ɵselectHasNextPage, ɵselectIsFetchingNextPage, ɵselectThreads, ɵselectThreadsError, ɵselectThreadsIsLoading, ɵthreadAdapterEvents };
3172
3289
  //# sourceMappingURL=index.mjs.map