@copilotkit/core 1.63.1 → 1.63.2-canary.1784918757

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
@@ -1,5 +1,5 @@
1
1
  import { Throttler } from "@tanstack/pacer";
2
- import { AbstractAgent, EventType, HttpAgent, randomUUID, runHttpRequest, structuredClone_, transformChunks, transformHttpEventStream } from "@ag-ui/client";
2
+ import { AbstractAgent, EventType, HttpAgent, buildResumeArray, isInterruptExpired, randomUUID, runHttpRequest, structuredClone_, transformChunks, transformHttpEventStream } from "@ag-ui/client";
3
3
  import { RUNTIME_MODE_INTELLIGENCE, RUNTIME_MODE_SSE, logger, partialJSONParse, phoenixExponentialBackoff, randomUUID as randomUUID$1, resolveDebugConfig, schemaToJsonSchema } from "@copilotkit/shared";
4
4
  import { BehaviorSubject, EMPTY, NEVER, Notification, Observable, Subject, Subscription, asapScheduler, combineLatest, concat, defer, dematerialize, firstValueFrom, from, lastValueFrom, merge, observeOn, of, switchMap, throwError } from "rxjs";
5
5
  import { catchError, concatWith, delay, distinctUntilChanged, endWith, filter, finalize, ignoreElements, map, mergeMap, observeOn as observeOn$1, scan, share, shareReplay, switchMap as switchMap$1, take, takeUntil, tap, timeout, withLatestFrom } from "rxjs/operators";
@@ -601,6 +601,12 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends HttpAg
601
601
  get capabilities() {
602
602
  return this._capabilities;
603
603
  }
604
+ requestInit(input) {
605
+ return {
606
+ ...super.requestInit(input),
607
+ ...this.credentials ? { credentials: this.credentials } : {}
608
+ };
609
+ }
604
610
  async getCapabilities() {
605
611
  return this._capabilities ?? {};
606
612
  }
@@ -694,10 +700,12 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends HttpAg
694
700
  }
695
701
  }
696
702
  connect(input) {
703
+ if (this.runtimeMode === "pending" || this.transport === "auto" && this.runtimeMode !== RUNTIME_MODE_INTELLIGENCE) return defer(() => from(this.ensureRuntimeConfiguration())).pipe(switchMap$1(() => this.connect(input)));
697
704
  if (this.runtimeMode === RUNTIME_MODE_INTELLIGENCE) return this.#connectViaDelegate(input);
698
705
  return this.#connectViaHttp(input);
699
706
  }
700
707
  run(input) {
708
+ if (this.runtimeMode === "pending" || this.transport === "auto" && this.runtimeMode !== RUNTIME_MODE_INTELLIGENCE) return defer(() => from(this.ensureRuntimeConfiguration())).pipe(switchMap$1(() => this.run(input)));
701
709
  if (this.runtimeMode === RUNTIME_MODE_INTELLIGENCE) return this.#runViaDelegate(input);
702
710
  return this.#runViaHttp(input);
703
711
  }
@@ -767,7 +775,7 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends HttpAg
767
775
  this.delegate?.clearReconnectCursor?.(threadId);
768
776
  }
769
777
  async resolveDelegate() {
770
- await this.ensureRuntimeMode();
778
+ await this.ensureRuntimeConfiguration();
771
779
  if (!this.delegate) {
772
780
  if (this.runtimeMode !== RUNTIME_MODE_INTELLIGENCE) throw new Error("A delegate is only created for Intelligence mode");
773
781
  this.delegate = this.createIntelligenceDelegate();
@@ -775,14 +783,21 @@ var ProxiedCopilotRuntimeAgent = class ProxiedCopilotRuntimeAgent extends HttpAg
775
783
  this.syncDelegate(this.delegate);
776
784
  return this.delegate;
777
785
  }
778
- async ensureRuntimeMode() {
779
- if (this.runtimeMode !== "pending") return;
786
+ /** Resolve transport and runtime mode before the first outbound request. */
787
+ async ensureRuntimeConfiguration() {
788
+ if (this.runtimeMode === RUNTIME_MODE_INTELLIGENCE || this.runtimeMode !== "pending" && this.transport !== "auto") return;
780
789
  if (!this.runtimeUrl) throw new Error("Runtime URL is not set");
781
- this.runtimeInfoPromise ??= this.fetchRuntimeInfo().then((runtimeInfo) => {
790
+ const runtimeInfoPromise = this.runtimeInfoPromise ?? this.fetchRuntimeInfo().then((runtimeInfo) => {
782
791
  this.runtimeMode = runtimeInfo.mode ?? RUNTIME_MODE_SSE;
783
792
  this.intelligence = runtimeInfo.intelligence;
784
793
  });
785
- await this.runtimeInfoPromise;
794
+ this.runtimeInfoPromise = runtimeInfoPromise;
795
+ try {
796
+ await runtimeInfoPromise;
797
+ } catch (error) {
798
+ if (this.runtimeInfoPromise === runtimeInfoPromise) this.runtimeInfoPromise = void 0;
799
+ throw error;
800
+ }
786
801
  }
787
802
  async fetchRuntimeInfo() {
788
803
  const headers = { ...this.headers };
@@ -1737,6 +1752,19 @@ const SUGGEST_TOOL = {
1737
1752
  //#endregion
1738
1753
  //#region src/core/run-handler.ts
1739
1754
  /**
1755
+ * Absolute safety cap on the depth of recursive follow-up runs triggered by
1756
+ * `processAgentResult`. Without this, any scenario that keeps
1757
+ * `needsFollowUp = true` (e.g. the LLM repeatedly calling the same tool, a
1758
+ * backend that errors after receiving tool results, or input processors that
1759
+ * reprocess tool messages) would loop indefinitely, silently consuming API
1760
+ * quota and potentially DOS'ing the backend.
1761
+ *
1762
+ * The cap is deliberately high so that legitimate multi-step agent workflows
1763
+ * (search → fill form → confirm → update → send email, etc.) are never
1764
+ * affected; it only trips on runaway recursion.
1765
+ */
1766
+ const MAX_FOLLOW_UP_DEPTH = 100;
1767
+ /**
1740
1768
  * Handles agent execution, tool calling, and agent connectivity for CopilotKitCore.
1741
1769
  * Manages the complete lifecycle of agent runs including tool execution and follow-ups.
1742
1770
  */
@@ -1991,7 +2019,8 @@ var RunHandler = class {
1991
2019
  }
1992
2020
  }
1993
2021
  }
1994
- if (needsFollowUp && !this._runAbortController?.signal.aborted) {
2022
+ if (needsFollowUp && !this._runAbortController?.signal.aborted) if (this._runDepth >= MAX_FOLLOW_UP_DEPTH) logger.warn(`[CopilotKit] Follow-up depth limit (${MAX_FOLLOW_UP_DEPTH}) reached for agent "${agentId}". Stopping recursive follow-up runs to prevent an infinite loop. This usually indicates a tool that keeps requesting a follow-up (e.g. the LLM repeatedly calling the same tool). Consider setting "followUp: false" on the offending tool.`);
2023
+ else {
1995
2024
  await this._internal.waitForPendingFrameworkUpdates();
1996
2025
  return await this.runAgent({ agent });
1997
2026
  }
@@ -2314,6 +2343,7 @@ var RunHandler = class {
2314
2343
  await emitAgentError(error, error instanceof AgentThreadLockedError ? CopilotKitCoreErrorCode.AGENT_THREAD_LOCKED : CopilotKitCoreErrorCode.AGENT_RUN_FAILED_EVENT, { source: "onRunFailed" });
2315
2344
  },
2316
2345
  onRunErrorEvent: async ({ event }) => {
2346
+ if (this._runAbortController?.signal.aborted === true || event?.code === "abort") return;
2317
2347
  const eventError = event?.rawEvent instanceof Error ? event.rawEvent : event?.rawEvent?.error instanceof Error ? event.rawEvent.error : void 0;
2318
2348
  const errorMessage = typeof event?.rawEvent?.error === "string" ? event.rawEvent.error : event?.message ?? "Agent run error";
2319
2349
  const rawError = eventError ?? new Error(errorMessage);
@@ -5248,5 +5278,110 @@ function ɵisCopilotKitFeature(name) {
5248
5278
  }
5249
5279
 
5250
5280
  //#endregion
5251
- export { AgentRegistry, AgentThreadLockedError, ContextStore, CopilotKitCore, CopilotKitCoreErrorCode, CopilotKitCoreRuntimeConnectionStatus, IntelligenceAgent, MEMORY_ERROR_REGISTRY, MemoryError, ProxiedCopilotRuntimeAgent, RunHandler, StateManager, SuggestionEngine, ToolCallStatus, completePartialMarkdown, createActionGroup, createEffect, createReducer, createSelector, createStore, empty, ensureObjectArgs, isAbortError, isRunCompletionAware, ofType, on, parseToolArguments, props, select, ɵCOPILOTKIT_FEATURES, ɵMAX_SOCKET_RETRIES, createMemoryStore as ɵcreateMemoryStore, ɵcreateThreadSelectors, createThreadStore as ɵcreateThreadStore, ɵisCopilotKitFeature, isRetryableStatus as ɵisRetryableMemoryStatus, ɵjoinPhoenixChannel$, ɵmapMemoryMetadataEvent, ɵmemoryAdapterEvents, ɵmemoryDomainEvents, ɵmemoryReducer, ɵmemoryRestEvents, ɵobservePhoenixEvent$, ɵobservePhoenixJoinOutcome$, ɵobservePhoenixSocketHealth$, ɵobservePhoenixSocketSignals$, ɵphoenixChannel$, ɵphoenixSocket$, ɵselectFetchMoreError, ɵselectHasNextPage, ɵselectIsFetchingNextPage, ɵselectIsMutating, ɵselectMemories, ɵselectMemoriesAvailable, ɵselectMemoriesError, ɵselectMemoriesIsLoading, ɵselectMemoriesIsMutating, ɵselectMemoriesRealtimeStatus, ɵselectThreads, ɵselectThreadsError, ɵselectThreadsIsLoading, ɵthreadAdapterEvents };
5281
+ //#region src/interrupt-state.ts
5282
+ function toolResultContent(response) {
5283
+ if (response.status === "cancelled") return JSON.stringify({ status: "cancelled" });
5284
+ return JSON.stringify(response.payload ?? { status: "resolved" });
5285
+ }
5286
+ /**
5287
+ * @internal Framework-neutral interrupt response state shared by framework
5288
+ * adapters. Application authors must not depend on this API.
5289
+ */
5290
+ var ɵInterruptState = class {
5291
+ #responses = {};
5292
+ #pending = null;
5293
+ #sealed = false;
5294
+ /** Return the active normalized interrupt without exposing mutable state. */
5295
+ get pending() {
5296
+ const pending = this.#pending;
5297
+ if (pending?.kind === "standard") return {
5298
+ kind: "standard",
5299
+ interrupts: [...pending.interrupts]
5300
+ };
5301
+ return pending;
5302
+ }
5303
+ /** Replace the current interrupt with a legacy custom-event interrupt. */
5304
+ setLegacy(event) {
5305
+ this.#replace({
5306
+ kind: "legacy",
5307
+ event
5308
+ });
5309
+ }
5310
+ /** Replace the current interrupt with an AG-UI standard interrupt set. */
5311
+ setStandard(interrupts) {
5312
+ this.#replace({
5313
+ kind: "standard",
5314
+ interrupts: [...interrupts]
5315
+ });
5316
+ }
5317
+ /** Clear all pending interrupt data and accumulated responses. */
5318
+ clear() {
5319
+ this.#pending = null;
5320
+ this.#sealed = false;
5321
+ for (const id of Object.keys(this.#responses)) delete this.#responses[id];
5322
+ }
5323
+ /** Record a resolved response and return the next framework action. */
5324
+ resolve(payload, interruptId) {
5325
+ const pending = this.#pending;
5326
+ if (!pending || this.#sealed) return { kind: "ignored" };
5327
+ if (pending.kind === "legacy") {
5328
+ this.#sealed = true;
5329
+ return {
5330
+ kind: "legacy-resume",
5331
+ payload,
5332
+ interruptValue: pending.event.value
5333
+ };
5334
+ }
5335
+ return this.#respond(pending.interrupts, interruptId, {
5336
+ status: "resolved",
5337
+ payload
5338
+ });
5339
+ }
5340
+ /** Record a cancelled response and return the next framework action. */
5341
+ cancel(interruptId) {
5342
+ const pending = this.#pending;
5343
+ if (!pending || this.#sealed) return { kind: "ignored" };
5344
+ if (pending.kind === "legacy") {
5345
+ this.#sealed = true;
5346
+ return { kind: "dismiss" };
5347
+ }
5348
+ return this.#respond(pending.interrupts, interruptId, { status: "cancelled" });
5349
+ }
5350
+ #replace(pending) {
5351
+ this.clear();
5352
+ this.#pending = pending;
5353
+ }
5354
+ #respond(interrupts, interruptId, response) {
5355
+ const id = interruptId ?? interrupts[0]?.id;
5356
+ if (!id || !interrupts.some((interrupt) => interrupt.id === id)) return { kind: "ignored" };
5357
+ this.#responses[id] = response;
5358
+ if (!interrupts.every((interrupt) => this.#responses[interrupt.id])) return { kind: "waiting" };
5359
+ const expired = interrupts.find((interrupt) => isInterruptExpired(interrupt));
5360
+ if (expired) {
5361
+ this.#sealed = true;
5362
+ return {
5363
+ kind: "expired",
5364
+ interrupt: expired
5365
+ };
5366
+ }
5367
+ const mutableInterrupts = [...interrupts];
5368
+ const resume = buildResumeArray(mutableInterrupts, this.#responses);
5369
+ const toolResults = mutableInterrupts.flatMap((interrupt) => {
5370
+ if (!interrupt.toolCallId) return [];
5371
+ return [{
5372
+ toolCallId: interrupt.toolCallId,
5373
+ content: toolResultContent(this.#responses[interrupt.id])
5374
+ }];
5375
+ });
5376
+ this.#sealed = true;
5377
+ return {
5378
+ kind: "resume",
5379
+ resume,
5380
+ toolResults
5381
+ };
5382
+ }
5383
+ };
5384
+
5385
+ //#endregion
5386
+ export { AgentRegistry, AgentThreadLockedError, ContextStore, CopilotKitCore, CopilotKitCoreErrorCode, CopilotKitCoreRuntimeConnectionStatus, IntelligenceAgent, MEMORY_ERROR_REGISTRY, MemoryError, ProxiedCopilotRuntimeAgent, RunHandler, StateManager, SuggestionEngine, ToolCallStatus, completePartialMarkdown, createActionGroup, createEffect, createReducer, createSelector, createStore, empty, ensureObjectArgs, isAbortError, isRunCompletionAware, ofType, on, parseToolArguments, props, select, ɵCOPILOTKIT_FEATURES, ɵInterruptState, ɵMAX_SOCKET_RETRIES, createMemoryStore as ɵcreateMemoryStore, ɵcreateThreadSelectors, createThreadStore as ɵcreateThreadStore, ɵisCopilotKitFeature, isRetryableStatus as ɵisRetryableMemoryStatus, ɵjoinPhoenixChannel$, ɵmapMemoryMetadataEvent, ɵmemoryAdapterEvents, ɵmemoryDomainEvents, ɵmemoryReducer, ɵmemoryRestEvents, ɵobservePhoenixEvent$, ɵobservePhoenixJoinOutcome$, ɵobservePhoenixSocketHealth$, ɵobservePhoenixSocketSignals$, ɵphoenixChannel$, ɵphoenixSocket$, ɵselectFetchMoreError, ɵselectHasNextPage, ɵselectIsFetchingNextPage, ɵselectIsMutating, ɵselectMemories, ɵselectMemoriesAvailable, ɵselectMemoriesError, ɵselectMemoriesIsLoading, ɵselectMemoriesIsMutating, ɵselectMemoriesRealtimeStatus, ɵselectThreads, ɵselectThreadsError, ɵselectThreadsIsLoading, ɵthreadAdapterEvents };
5252
5387
  //# sourceMappingURL=index.mjs.map