@copilotkit/core 1.62.2-canary.1783457132 → 1.62.2-canary.1785518626

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
@@ -2510,6 +2510,124 @@ var StateManager = class {
2510
2510
  }
2511
2511
  };
2512
2512
 
2513
+ //#endregion
2514
+ //#region src/core/subagent-registry.ts
2515
+ /**
2516
+ * Tracks subagent lifecycle events (SUBAGENT_STARTED / FINISHED / ERROR) per
2517
+ * owning agent so consumers can resolve a message's `subagentId` to a name,
2518
+ * description, and running status.
2519
+ *
2520
+ * Modeled on {@link SuggestionEngine}: an in-memory `Record` keyed by (owning)
2521
+ * agentId, mutated from streamed AG-UI events, made reactive by calling
2522
+ * `notifySubscribers(onSubagentsChanged)` after every change. It owns its own
2523
+ * per-agent `agent.subscribe` (like {@link StateManager}) so it is fully
2524
+ * self-contained and adds no coupling to the state/message tracking path.
2525
+ *
2526
+ * No-op for runs without subagents (a normal LangGraph run never emits
2527
+ * SUBAGENT_* events), so the registry simply stays empty.
2528
+ */
2529
+ var SubagentRegistry = class {
2530
+ _subagents = {};
2531
+ agentSubscriptions = /* @__PURE__ */ new Map();
2532
+ constructor(core) {
2533
+ this.core = core;
2534
+ }
2535
+ /**
2536
+ * Subscribe to an agent's subagent lifecycle events. Idempotent per agentId:
2537
+ * an existing subscription for the same agent is revoked and replaced.
2538
+ */
2539
+ subscribeToAgent(agent) {
2540
+ if (!agent.agentId) return;
2541
+ const agentId = agent.agentId;
2542
+ const existingUnsubscribe = this.agentSubscriptions.get(agentId);
2543
+ if (existingUnsubscribe) {
2544
+ existingUnsubscribe();
2545
+ this.agentSubscriptions.delete(agentId);
2546
+ }
2547
+ let revoked = false;
2548
+ const { unsubscribe } = agent.subscribe({
2549
+ onSubagentStartedEvent: ({ event }) => {
2550
+ if (revoked) return;
2551
+ this.handleStarted(agentId, event);
2552
+ },
2553
+ onSubagentFinishedEvent: ({ event }) => {
2554
+ if (revoked) return;
2555
+ this.handleFinished(agentId, event);
2556
+ },
2557
+ onSubagentErrorEvent: ({ event }) => {
2558
+ if (revoked) return;
2559
+ this.handleError(agentId, event);
2560
+ }
2561
+ });
2562
+ this.agentSubscriptions.set(agentId, () => {
2563
+ revoked = true;
2564
+ unsubscribe();
2565
+ });
2566
+ }
2567
+ /**
2568
+ * Unsubscribe an agent's subscription (symmetric with StateManager cleanup).
2569
+ */
2570
+ unsubscribeFromAgent(agentId) {
2571
+ const unsubscribe = this.agentSubscriptions.get(agentId);
2572
+ if (unsubscribe) {
2573
+ unsubscribe();
2574
+ this.agentSubscriptions.delete(agentId);
2575
+ }
2576
+ }
2577
+ /**
2578
+ * Get the subagents observed for an owning agent, keyed by subagentId.
2579
+ * Returns a fresh shallow copy each call so consumers (and React state) see
2580
+ * a new reference when anything changed.
2581
+ */
2582
+ getSubagents(agentId) {
2583
+ return { ...this._subagents[agentId] };
2584
+ }
2585
+ handleStarted(agentId, event) {
2586
+ const bucket = this._subagents[agentId] ??= {};
2587
+ bucket[event.subagentId] = {
2588
+ subagentId: event.subagentId,
2589
+ name: event.name,
2590
+ description: event.description,
2591
+ parentSubagentId: event.parentSubagentId,
2592
+ status: "running"
2593
+ };
2594
+ this.notifySubagentsChanged(agentId);
2595
+ }
2596
+ handleFinished(agentId, event) {
2597
+ const bucket = this._subagents[agentId];
2598
+ const existing = bucket?.[event.subagentId];
2599
+ if (!bucket || !existing) return;
2600
+ bucket[event.subagentId] = {
2601
+ ...existing,
2602
+ status: "finished"
2603
+ };
2604
+ this.notifySubagentsChanged(agentId);
2605
+ }
2606
+ handleError(agentId, event) {
2607
+ const bucket = this._subagents[agentId] ??= {};
2608
+ const existing = bucket[event.subagentId];
2609
+ bucket[event.subagentId] = existing ? {
2610
+ ...existing,
2611
+ status: "error",
2612
+ error: event.message
2613
+ } : {
2614
+ subagentId: event.subagentId,
2615
+ name: event.subagentId,
2616
+ status: "error",
2617
+ error: event.message
2618
+ };
2619
+ this.notifySubagentsChanged(agentId);
2620
+ }
2621
+ async notifySubagentsChanged(agentId) {
2622
+ const subagents = this.getSubagents(agentId);
2623
+ await this.core.notifySubscribers((subscriber) => subscriber.onSubagentsChanged?.({
2624
+ copilotkit: this.core,
2625
+ agentId,
2626
+ subagents
2627
+ }), "Subscriber onSubagentsChanged error:");
2628
+ }
2629
+ };
2630
+
2513
2631
  //#endregion
2514
2632
  //#region src/core/thread-store-registry.ts
2515
2633
  var ThreadStoreRegistry = class {
@@ -3612,6 +3730,7 @@ var CopilotKitCore = class {
3612
3730
  suggestionEngine;
3613
3731
  runHandler;
3614
3732
  stateManager;
3733
+ subagentRegistry;
3615
3734
  threadStoreRegistry;
3616
3735
  /**
3617
3736
  * The single core-owned memory store, created lazily on first
@@ -3637,6 +3756,7 @@ var CopilotKitCore = class {
3637
3756
  this.suggestionEngine = new SuggestionEngine(this);
3638
3757
  this.runHandler = new RunHandler(this);
3639
3758
  this.stateManager = new StateManager(this);
3759
+ this.subagentRegistry = new SubagentRegistry(this);
3640
3760
  this.threadStoreRegistry = new ThreadStoreRegistry(this);
3641
3761
  this.agentRegistry.initialize(agents__unsafe_dev_only);
3642
3762
  this.runHandler.initialize(tools);
@@ -3651,7 +3771,10 @@ var CopilotKitCore = class {
3651
3771
  },
3652
3772
  onAgentsChanged: ({ agents }) => {
3653
3773
  Object.values(agents).forEach((agent) => {
3654
- if (agent.agentId) this.stateManager.subscribeToAgent(agent);
3774
+ if (agent.agentId) {
3775
+ this.stateManager.subscribeToAgent(agent);
3776
+ this.subagentRegistry.subscribeToAgent(agent);
3777
+ }
3655
3778
  });
3656
3779
  const currentAgentIds = new Set(Object.keys(agents));
3657
3780
  for (const agentId of Object.keys(this.threadStoreRegistry.getAll())) if (this.previousAgentIds.has(agentId) && !currentAgentIds.has(agentId)) try {
@@ -3659,10 +3782,17 @@ var CopilotKitCore = class {
3659
3782
  } catch (err) {
3660
3783
  console.error(`CopilotKitCore.onAgentsChanged: threadStoreRegistry.unregister failed for "${agentId}":`, err);
3661
3784
  }
3662
- for (const agentId of this.previousAgentIds) if (!currentAgentIds.has(agentId)) try {
3663
- this.stateManager.unsubscribeFromAgent(agentId);
3664
- } catch (err) {
3665
- console.error(`CopilotKitCore.onAgentsChanged: stateManager.unsubscribeFromAgent failed for "${agentId}":`, err);
3785
+ for (const agentId of this.previousAgentIds) if (!currentAgentIds.has(agentId)) {
3786
+ try {
3787
+ this.stateManager.unsubscribeFromAgent(agentId);
3788
+ } catch (err) {
3789
+ console.error(`CopilotKitCore.onAgentsChanged: stateManager.unsubscribeFromAgent failed for "${agentId}":`, err);
3790
+ }
3791
+ try {
3792
+ this.subagentRegistry.unsubscribeFromAgent(agentId);
3793
+ } catch (err) {
3794
+ console.error(`CopilotKitCore.onAgentsChanged: subagentRegistry.unsubscribeFromAgent failed for "${agentId}":`, err);
3795
+ }
3666
3796
  }
3667
3797
  this.previousAgentIds = currentAgentIds;
3668
3798
  }
@@ -4004,6 +4134,16 @@ var CopilotKitCore = class {
4004
4134
  return this.suggestionEngine.getSuggestions(agentId);
4005
4135
  }
4006
4136
  /**
4137
+ * Subagent registry (delegated to SubagentRegistry).
4138
+ *
4139
+ * Returns the subagents observed for an owning agent during its run(s),
4140
+ * keyed by `subagentId`, each carrying `name` / `description` / `status`.
4141
+ * Empty for runs that never emit SUBAGENT_* events.
4142
+ */
4143
+ getSubagents(agentId) {
4144
+ return this.subagentRegistry.getSubagents(agentId);
4145
+ }
4146
+ /**
4007
4147
  * Tool management (delegated to RunHandler)
4008
4148
  */
4009
4149
  addTool(tool) {
@@ -4409,6 +4549,7 @@ const initialThreadState = {
4409
4549
  isLoading: false,
4410
4550
  isFetchingNextPage: false,
4411
4551
  error: null,
4552
+ fetchMoreError: null,
4412
4553
  context: null,
4413
4554
  sessionId: 0,
4414
4555
  metadataCredentialsRequested: false,
@@ -4494,6 +4635,7 @@ const threadReducer = createReducer(initialThreadState, on(threadAdapterEvents.c
4494
4635
  isLoading: Boolean(context),
4495
4636
  isFetchingNextPage: false,
4496
4637
  error: null,
4638
+ fetchMoreError: null,
4497
4639
  metadataCredentialsRequested: false,
4498
4640
  metadataJoinCode: null,
4499
4641
  nextCursor: null,
@@ -4505,6 +4647,7 @@ const threadReducer = createReducer(initialThreadState, on(threadAdapterEvents.c
4505
4647
  isLoading: false,
4506
4648
  isFetchingNextPage: false,
4507
4649
  error: null,
4650
+ fetchMoreError: null,
4508
4651
  metadataCredentialsRequested: false,
4509
4652
  metadataJoinCode: null,
4510
4653
  nextCursor: null,
@@ -4515,7 +4658,8 @@ const threadReducer = createReducer(initialThreadState, on(threadAdapterEvents.c
4515
4658
  return {
4516
4659
  ...state,
4517
4660
  isLoading: true,
4518
- error: null
4661
+ error: null,
4662
+ fetchMoreError: null
4519
4663
  };
4520
4664
  }), on(threadRestEvents.listSucceeded, (state, { sessionId, threads, joinCode, nextCursor }) => {
4521
4665
  if (sessionId !== state.sessionId) return state;
@@ -4525,6 +4669,7 @@ const threadReducer = createReducer(initialThreadState, on(threadAdapterEvents.c
4525
4669
  threads: sortThreadsByRecency(threads),
4526
4670
  isLoading: false,
4527
4671
  error: null,
4672
+ fetchMoreError: null,
4528
4673
  metadataJoinCode: joinCode,
4529
4674
  metadataCredentialsRequested: joinCodeChanged ? false : state.metadataCredentialsRequested,
4530
4675
  nextCursor
@@ -4544,6 +4689,7 @@ const threadReducer = createReducer(initialThreadState, on(threadAdapterEvents.c
4544
4689
  ...state,
4545
4690
  threads: merged,
4546
4691
  isFetchingNextPage: false,
4692
+ fetchMoreError: null,
4547
4693
  nextCursor
4548
4694
  };
4549
4695
  }), on(threadRestEvents.nextPageFailed, (state, { sessionId, error }) => {
@@ -4551,7 +4697,7 @@ const threadReducer = createReducer(initialThreadState, on(threadAdapterEvents.c
4551
4697
  return {
4552
4698
  ...state,
4553
4699
  isFetchingNextPage: false,
4554
- error
4700
+ fetchMoreError: error
4555
4701
  };
4556
4702
  }), on(threadRestEvents.metadataCredentialsFailed, (state, { sessionId }) => {
4557
4703
  if (sessionId !== state.sessionId) return state;
@@ -4569,7 +4715,8 @@ const threadReducer = createReducer(initialThreadState, on(threadAdapterEvents.c
4569
4715
  if (!state.nextCursor || state.isFetchingNextPage) return state;
4570
4716
  return {
4571
4717
  ...state,
4572
- isFetchingNextPage: true
4718
+ isFetchingNextPage: true,
4719
+ fetchMoreError: null
4573
4720
  };
4574
4721
  }), on(threadAdapterEvents.renameRequested, (state, { threadId, name }) => {
4575
4722
  const existing = state.threads.find((thread) => thread.id === threadId);
@@ -4698,6 +4845,7 @@ function createThreadSelectors() {
4698
4845
  threads: createSelector((state) => state.threads),
4699
4846
  isLoading: createSelector((state) => state.isLoading),
4700
4847
  error: createSelector((state) => state.error),
4848
+ fetchMoreError: createSelector((state) => state.fetchMoreError),
4701
4849
  hasNextPage: createSelector((state) => state.nextCursor != null),
4702
4850
  isFetchingNextPage: createSelector((state) => state.isFetchingNextPage),
4703
4851
  isMutating: createSelector((state) => state.inFlightMutationCount > 0)
@@ -4707,6 +4855,7 @@ const standaloneSelectors = createThreadSelectors();
4707
4855
  const selectThreads = standaloneSelectors.threads;
4708
4856
  const selectThreadsIsLoading = standaloneSelectors.isLoading;
4709
4857
  const selectThreadsError = standaloneSelectors.error;
4858
+ const selectFetchMoreError = standaloneSelectors.fetchMoreError;
4710
4859
  const selectHasNextPage = standaloneSelectors.hasNextPage;
4711
4860
  const selectIsFetchingNextPage = standaloneSelectors.isFetchingNextPage;
4712
4861
  const selectIsMutating = standaloneSelectors.isMutating;
@@ -5080,6 +5229,7 @@ const ɵcreateThreadSelectors = createThreadSelectors;
5080
5229
  const ɵselectThreads = selectThreads;
5081
5230
  const ɵselectThreadsIsLoading = selectThreadsIsLoading;
5082
5231
  const ɵselectThreadsError = selectThreadsError;
5232
+ const ɵselectFetchMoreError = selectFetchMoreError;
5083
5233
  const ɵselectHasNextPage = selectHasNextPage;
5084
5234
  const ɵselectIsFetchingNextPage = selectIsFetchingNextPage;
5085
5235
  const ɵselectIsMutating = selectIsMutating;
@@ -5149,6 +5299,7 @@ exports.MemoryError = MemoryError;
5149
5299
  exports.ProxiedCopilotRuntimeAgent = ProxiedCopilotRuntimeAgent;
5150
5300
  exports.RunHandler = RunHandler;
5151
5301
  exports.StateManager = StateManager;
5302
+ exports.SubagentRegistry = SubagentRegistry;
5152
5303
  exports.SuggestionEngine = SuggestionEngine;
5153
5304
  exports.ToolCallStatus = ToolCallStatus;
5154
5305
  exports.completePartialMarkdown = completePartialMarkdown;
@@ -5184,6 +5335,7 @@ exports.ɵobservePhoenixSocketHealth$ = ɵobservePhoenixSocketHealth$;
5184
5335
  exports.ɵobservePhoenixSocketSignals$ = ɵobservePhoenixSocketSignals$;
5185
5336
  exports.ɵphoenixChannel$ = ɵphoenixChannel$;
5186
5337
  exports.ɵphoenixSocket$ = ɵphoenixSocket$;
5338
+ exports.ɵselectFetchMoreError = ɵselectFetchMoreError;
5187
5339
  exports.ɵselectHasNextPage = ɵselectHasNextPage;
5188
5340
  exports.ɵselectIsFetchingNextPage = ɵselectIsFetchingNextPage;
5189
5341
  exports.ɵselectIsMutating = ɵselectIsMutating;