@copilotkit/core 1.76.0 → 1.77.0

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.umd.js CHANGED
@@ -1,8 +1,8 @@
1
1
  (function(global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@tanstack/pacer'), require('@ag-ui/client'), require('@copilotkit/shared'), require('rxjs'), require('rxjs/operators'), require('phoenix'), require('zod-to-json-schema')) :
3
- typeof define === 'function' && define.amd ? define(['exports', '@tanstack/pacer', '@ag-ui/client', '@copilotkit/shared', 'rxjs', 'rxjs/operators', 'phoenix', 'zod-to-json-schema'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.CopilotKitCore = {}), global._tanstack_pacer,global.AgUIClient,global.CopilotKitShared,global.rxjs,global.rxjs.operators,global.phoenix,global.zodToJsonSchema));
5
- })(this, function(exports, _tanstack_pacer, _ag_ui_client, _copilotkit_shared, rxjs, rxjs_operators, phoenix, zod_to_json_schema) {
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@tanstack/pacer'), require('@ag-ui/client'), require('@copilotkit/shared'), require('rxjs'), require('rxjs/operators'), require('phoenix'), require('zod-to-json-schema'), require('@copilotkit/learning')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', '@tanstack/pacer', '@ag-ui/client', '@copilotkit/shared', 'rxjs', 'rxjs/operators', 'phoenix', 'zod-to-json-schema', '@copilotkit/learning'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.CopilotKitCore = {}), global._tanstack_pacer,global.AgUIClient,global.CopilotKitShared,global.rxjs,global.rxjs.operators,global.phoenix,global.zodToJsonSchema,global._copilotkit_learning));
5
+ })(this, function(exports, _tanstack_pacer, _ag_ui_client, _copilotkit_shared, rxjs, rxjs_operators, phoenix, zod_to_json_schema, _copilotkit_learning) {
6
6
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
7
7
 
8
8
  //#region src/utils/http-agent.ts
@@ -2015,6 +2015,10 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2015
2015
  this.applyMessageFilterToAgent(agent);
2016
2016
  });
2017
2017
  }
2018
+ /** Preserve the exact configured URL when posting to a single endpoint. */
2019
+ get runtimeEndpointUrl() {
2020
+ return this._runtimeEndpointUrl;
2021
+ }
2018
2022
  createRuntimeFetch() {
2019
2023
  if (!this.runtimeFetch) this.runtimeFetch = (async (input, init) => {
2020
2024
  const meta = () => runtimeRequestMeta(init);
@@ -3080,6 +3084,68 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3080
3084
  function isForwardedToClientPlaceholder(content) {
3081
3085
  return normalizeToolResultContent(content) === FORWARDED_TO_CLIENT;
3082
3086
  }
3087
+ const MEDIA_PART_TYPES = new Set([
3088
+ "image",
3089
+ "audio",
3090
+ "video",
3091
+ "document"
3092
+ ]);
3093
+ function isOptionalString(value) {
3094
+ return value === void 0 || typeof value === "string";
3095
+ }
3096
+ function isPartSource(value) {
3097
+ if (!value || typeof value !== "object") return false;
3098
+ const source = value;
3099
+ if (typeof source.value !== "string") return false;
3100
+ switch (source.type) {
3101
+ case "data": return typeof source.mimeType === "string";
3102
+ case "url": return isOptionalString(source.mimeType);
3103
+ case "file": return isOptionalString(source.provider) && isOptionalString(source.mimeType);
3104
+ default: return false;
3105
+ }
3106
+ }
3107
+ /**
3108
+ * Mirrors `ContentPartSchema` from `@ag-ui/core/schemas`. The runtime parses
3109
+ * the request with that schema, and one invalid part there fails the whole run.
3110
+ * Core does not import the schema because the UMD build has no global for it.
3111
+ * A test checks this function against the schema.
3112
+ */
3113
+ function isContentPart(value) {
3114
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
3115
+ const part = value;
3116
+ if (!isOptionalString(part.id) || part.metadata === null) return false;
3117
+ if (part.type === "text") return typeof part.text === "string";
3118
+ return typeof part.type === "string" && MEDIA_PART_TYPES.has(part.type) && isPartSource(part.source);
3119
+ }
3120
+ /**
3121
+ * Converts what a frontend tool handler returned into tool message content.
3122
+ * A non-empty array of AG-UI content parts passes through unchanged, so an
3123
+ * image reaches the model as media. Everything else becomes a string, as before.
3124
+ *
3125
+ * `text` is the string form, for surfaces typed as `result: string`
3126
+ * (`runTool`, `onToolExecutionEnd`). For content parts it is the JSON text they
3127
+ * received before. It is computed here, so a part that cannot be serialized
3128
+ * throws inside the caller's handler error boundary.
3129
+ */
3130
+ function toToolResultContent(result) {
3131
+ if (result === void 0 || result === null) return {
3132
+ content: "",
3133
+ text: ""
3134
+ };
3135
+ if (typeof result === "string") return {
3136
+ content: result,
3137
+ text: result
3138
+ };
3139
+ const text = JSON.stringify(result);
3140
+ if (Array.isArray(result) && result.length > 0 && result.every(isContentPart)) return {
3141
+ content: result,
3142
+ text
3143
+ };
3144
+ return {
3145
+ content: text,
3146
+ text
3147
+ };
3148
+ }
3083
3149
 
3084
3150
  //#endregion
3085
3151
  //#region src/core/tool-schema.ts
@@ -3742,6 +3808,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3742
3808
  return (_this$_runAbortContro3 = this._runAbortController) === null || _this$_runAbortContro3 === void 0 ? void 0 : _this$_runAbortContro3.signal;
3743
3809
  })(), discardOnAbort = false }) {
3744
3810
  let toolCallResult = "";
3811
+ let toolCallText = "";
3745
3812
  let errorMessage;
3746
3813
  let isArgumentError = false;
3747
3814
  let parsedArgs;
@@ -3780,9 +3847,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3780
3847
  agent,
3781
3848
  signal
3782
3849
  });
3783
- if (result === void 0 || result === null) toolCallResult = "";
3784
- else if (typeof result === "string") toolCallResult = result;
3785
- else toolCallResult = JSON.stringify(result);
3850
+ ({content: toolCallResult, text: toolCallText} = toToolResultContent(result));
3786
3851
  } catch (error) {
3787
3852
  const handlerError = error instanceof Error ? error : new Error(String(error));
3788
3853
  errorMessage = handlerError.message;
@@ -3799,7 +3864,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3799
3864
  }
3800
3865
  });
3801
3866
  }
3802
- if (errorMessage) toolCallResult = `Error: ${errorMessage}`;
3867
+ if (errorMessage) toolCallResult = toolCallText = `Error: ${errorMessage}`;
3803
3868
  await this._internal.notifySubscribers((subscriber) => {
3804
3869
  var _subscriber$onToolExe2;
3805
3870
  return (_subscriber$onToolExe2 = subscriber.onToolExecutionEnd) === null || _subscriber$onToolExe2 === void 0 ? void 0 : _subscriber$onToolExe2.call(subscriber, {
@@ -3807,12 +3872,13 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3807
3872
  toolCallId: toolCall.id,
3808
3873
  agentId,
3809
3874
  toolName: toolCall.function.name,
3810
- result: errorMessage ? "" : toolCallResult,
3875
+ result: errorMessage ? "" : toolCallText,
3811
3876
  error: errorMessage
3812
3877
  });
3813
3878
  }, "Subscriber onToolExecutionEnd error:");
3814
3879
  return {
3815
- result: toolCallResult,
3880
+ content: toolCallResult,
3881
+ result: toolCallText,
3816
3882
  error: errorMessage,
3817
3883
  isArgumentError
3818
3884
  };
@@ -3824,6 +3890,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3824
3890
  const threadId = agent.threadId;
3825
3891
  if ((tool === null || tool === void 0 ? void 0 : tool.agentId) && tool.agentId !== agent.agentId) return false;
3826
3892
  let handlerResult = {
3893
+ content: "",
3827
3894
  result: "",
3828
3895
  error: void 0,
3829
3896
  isArgumentError: false
@@ -3849,7 +3916,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3849
3916
  id: (0, _copilotkit_shared.randomUUID)(),
3850
3917
  role: "tool",
3851
3918
  toolCallId: toolCall.id,
3852
- content: handlerResult.result
3919
+ content: handlerResult.content
3853
3920
  };
3854
3921
  agent.messages.splice(insertAt, 0, toolMessage);
3855
3922
  if (!handlerResult.error && (tool === null || tool === void 0 ? void 0 : tool.followUp) !== false) return true;
@@ -3866,6 +3933,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3866
3933
  const threadId = agent.threadId;
3867
3934
  if ((wildcardTool === null || wildcardTool === void 0 ? void 0 : wildcardTool.agentId) && wildcardTool.agentId !== agent.agentId) return false;
3868
3935
  let toolCallResult = "";
3936
+ let toolCallText = "";
3869
3937
  let errorMessage;
3870
3938
  if (wildcardTool === null || wildcardTool === void 0 ? void 0 : wildcardTool.handler) {
3871
3939
  let parsedArgs;
@@ -3907,9 +3975,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3907
3975
  agent,
3908
3976
  signal
3909
3977
  });
3910
- if (result === void 0 || result === null) toolCallResult = "";
3911
- else if (typeof result === "string") toolCallResult = result;
3912
- else toolCallResult = JSON.stringify(result);
3978
+ ({content: toolCallResult, text: toolCallText} = toToolResultContent(result));
3913
3979
  } catch (error) {
3914
3980
  const handlerError = error instanceof Error ? error : new Error(String(error));
3915
3981
  errorMessage = handlerError.message;
@@ -3926,7 +3992,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3926
3992
  }
3927
3993
  });
3928
3994
  }
3929
- if (errorMessage) toolCallResult = `Error: ${errorMessage}`;
3995
+ if (errorMessage) toolCallResult = toolCallText = `Error: ${errorMessage}`;
3930
3996
  await this._internal.notifySubscribers((subscriber) => {
3931
3997
  var _subscriber$onToolExe4;
3932
3998
  return (_subscriber$onToolExe4 = subscriber.onToolExecutionEnd) === null || _subscriber$onToolExe4 === void 0 ? void 0 : _subscriber$onToolExe4.call(subscriber, {
@@ -3934,7 +4000,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3934
4000
  toolCallId: toolCall.id,
3935
4001
  agentId,
3936
4002
  toolName: toolCall.function.name,
3937
- result: errorMessage ? "" : toolCallResult,
4003
+ result: errorMessage ? "" : toolCallText,
3938
4004
  error: errorMessage
3939
4005
  });
3940
4006
  }, "Subscriber onToolExecutionEnd error:");
@@ -4007,6 +4073,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4007
4073
  };
4008
4074
  agent.messages.push(assistantMessage);
4009
4075
  let handlerResult = {
4076
+ content: "",
4010
4077
  result: "",
4011
4078
  error: void 0,
4012
4079
  isArgumentError: false
@@ -4023,7 +4090,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4023
4090
  id: (0, _copilotkit_shared.randomUUID)(),
4024
4091
  role: "tool",
4025
4092
  toolCallId,
4026
- content: handlerResult.result
4093
+ content: handlerResult.content
4027
4094
  };
4028
4095
  const assistantIndex = agent.messages.findIndex((m) => m.id === assistantMessage.id);
4029
4096
  if (assistantIndex !== -1) agent.messages.splice(assistantIndex + 1, 0, toolResultMessage);
@@ -4676,6 +4743,745 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4676
4743
  }
4677
4744
  };
4678
4745
 
4746
+ //#endregion
4747
+ //#region src/core/trajectory-connection.ts
4748
+ const TIMEOUT_MS = 1e4;
4749
+ const BATCH_INTERVAL_MS = 2e3;
4750
+ const MAX_BATCH_EVENTS = 50;
4751
+ const MAX_BATCH_BYTES = 64 * 1024;
4752
+ const MAX_EVENT_BYTES = 16 * 1024;
4753
+ const byteLength = (value) => new TextEncoder().encode(JSON.stringify(value)).byteLength;
4754
+ const reconnectDelay = (0, _copilotkit_shared.phoenixExponentialBackoff)(1e3, 1e4);
4755
+ function isObject(value) {
4756
+ return typeof value === "object" && value !== null;
4757
+ }
4758
+ function isNonNegativeInteger(value) {
4759
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
4760
+ }
4761
+ function isBatchAcknowledgement(value, eventCount) {
4762
+ return isObject(value) && isNonNegativeInteger(value.accepted) && isNonNegativeInteger(value.rejected) && value.accepted + value.rejected === eventCount && (value.highestSeq === null || isNonNegativeInteger(value.highestSeq)) && (value.accepted === 0 || value.highestSeq !== null);
4763
+ }
4764
+ function isGrant(value) {
4765
+ return isObject(value) && typeof value.joinToken === "string" && value.joinToken.length > 0 && isObject(value.realtime) && typeof value.realtime.clientUrl === "string" && value.realtime.clientUrl.length > 0 && typeof value.realtime.topic === "string" && value.realtime.topic.length > 0;
4766
+ }
4767
+ function errorCode(value, fallback) {
4768
+ return isObject(value) && typeof value.code === "string" && /^[A-Z][A-Z0-9_]{0,63}$/.test(value.code) ? value.code : fallback;
4769
+ }
4770
+ /** Owns bounded, connected-only capture batches. Failed batches are never resent. */
4771
+ var TrajectoryConnection = class {
4772
+ constructor(core, onChange) {
4773
+ this.core = core;
4774
+ this.onChange = onChange;
4775
+ _defineProperty(this, "session", void 0);
4776
+ _defineProperty(this, "nextSeq", Math.floor(Date.now()) * 1e3);
4777
+ }
4778
+ get trajectoryId() {
4779
+ var _this$session;
4780
+ return ((_this$session = this.session) === null || _this$session === void 0 ? void 0 : _this$session.ready) ? this.session.trajectoryId : null;
4781
+ }
4782
+ start(trajectoryId, config) {
4783
+ if (this.session && (trajectoryId === void 0 || trajectoryId === this.session.trajectoryId)) return this.session.promise;
4784
+ this.stop();
4785
+ const id = trajectoryId !== null && trajectoryId !== void 0 ? trajectoryId : crypto.randomUUID();
4786
+ let resolveStart;
4787
+ const promise = new Promise((resolve) => {
4788
+ resolveStart = resolve;
4789
+ });
4790
+ const session = {
4791
+ trajectoryId: id,
4792
+ config,
4793
+ promise,
4794
+ resolve: resolveStart,
4795
+ retries: 0,
4796
+ queue: [],
4797
+ dropped: 0,
4798
+ ready: false,
4799
+ started: false,
4800
+ offline: typeof navigator !== "undefined" && navigator.onLine === false,
4801
+ onOffline: () => {
4802
+ if (this.session !== session) return;
4803
+ session.offline = true;
4804
+ if (session.connection) this.fail(session, session.connection, "CONNECTION_LOST");
4805
+ clearTimeout(session.retry);
4806
+ session.retry = void 0;
4807
+ },
4808
+ onOnline: () => {
4809
+ if (this.session !== session) return;
4810
+ session.offline = false;
4811
+ if (!session.connection) {
4812
+ clearTimeout(session.retry);
4813
+ session.retry = void 0;
4814
+ this.connect(session);
4815
+ }
4816
+ }
4817
+ };
4818
+ this.session = session;
4819
+ if (typeof window !== "undefined" && typeof window.addEventListener === "function") {
4820
+ window.addEventListener("offline", session.onOffline);
4821
+ window.addEventListener("online", session.onOnline);
4822
+ }
4823
+ if (session.offline) {
4824
+ this.report(session, "CONNECTION_LOST");
4825
+ this.end(session, {
4826
+ status: "error",
4827
+ code: "CONNECTION_LOST"
4828
+ });
4829
+ } else this.connect(session);
4830
+ return promise;
4831
+ }
4832
+ stop() {
4833
+ const session = this.session;
4834
+ if (!session) return;
4835
+ if (session.ready && session.connection) this.flush(session, session.connection);
4836
+ this.end(session, {
4837
+ status: "error",
4838
+ code: "CANCELLED"
4839
+ });
4840
+ }
4841
+ emit(name, value) {
4842
+ var _session$collector;
4843
+ const session = this.session;
4844
+ if (session === null || session === void 0 ? void 0 : session.ready) (_session$collector = session.collector) === null || _session$collector === void 0 || _session$collector.emit(name, value);
4845
+ else if (session === null || session === void 0 ? void 0 : session.started) this.addDropped(session, 1, false);
4846
+ }
4847
+ report(session, code) {
4848
+ try {
4849
+ var _session$config$onErr, _session$config;
4850
+ (_session$config$onErr = (_session$config = session.config).onError) === null || _session$config$onErr === void 0 || _session$config$onErr.call(_session$config, {
4851
+ code,
4852
+ message: `Trajectory capture: ${code}.`
4853
+ });
4854
+ } catch (_unused) {}
4855
+ }
4856
+ current(session, connection) {
4857
+ return this.session === session && session.connection === connection;
4858
+ }
4859
+ end(session, result) {
4860
+ var _session$collector2;
4861
+ if (this.session !== session) return;
4862
+ this.session = void 0;
4863
+ clearTimeout(session.retry);
4864
+ (_session$collector2 = session.collector) === null || _session$collector2 === void 0 || _session$collector2.stop();
4865
+ session.ready = false;
4866
+ if (session.queue.length > 0) this.report(session, "EVENTS_DROPPED");
4867
+ this.discardQueue(session);
4868
+ if (session.connection) {
4869
+ for (const pending of session.connection.pending) {
4870
+ pending.finish("PERSISTENCE_UNKNOWN");
4871
+ this.report(session, "PERSISTENCE_UNKNOWN");
4872
+ }
4873
+ this.cleanup(session, session.connection);
4874
+ }
4875
+ if (typeof window !== "undefined" && typeof window.removeEventListener === "function") {
4876
+ window.removeEventListener("offline", session.onOffline);
4877
+ window.removeEventListener("online", session.onOnline);
4878
+ }
4879
+ session.resolve(result);
4880
+ this.onChange();
4881
+ }
4882
+ cleanup(session, connection) {
4883
+ session.connection = void 0;
4884
+ clearTimeout(connection.timer);
4885
+ connection.abort.abort();
4886
+ for (const pending of connection.pending) clearTimeout(pending.timer);
4887
+ connection.pending.clear();
4888
+ const { socket, channel } = connection;
4889
+ try {
4890
+ if (channel) {
4891
+ for (const [event, ref] of connection.channelRefs) channel.off(event, ref);
4892
+ channel.leave();
4893
+ }
4894
+ } finally {
4895
+ if (socket) {
4896
+ socket.off(connection.socketRefs);
4897
+ socket.disconnect();
4898
+ }
4899
+ }
4900
+ }
4901
+ fail(session, connection, code, retryable = true) {
4902
+ var _session$collector3;
4903
+ if (!this.current(session, connection)) return;
4904
+ (_session$collector3 = session.collector) === null || _session$collector3 === void 0 || _session$collector3.stop();
4905
+ session.collector = void 0;
4906
+ if (session.ready && session.started) session.promise = new Promise((resolve) => {
4907
+ session.resolve = resolve;
4908
+ });
4909
+ session.ready = false;
4910
+ this.discardQueue(session);
4911
+ for (const pending of connection.pending) pending.finish("PERSISTENCE_UNKNOWN");
4912
+ if (!this.current(session, connection)) return;
4913
+ this.cleanup(session, connection);
4914
+ this.onChange();
4915
+ this.report(session, code);
4916
+ if (this.session !== session) return;
4917
+ if (!session.started || !retryable) {
4918
+ this.end(session, {
4919
+ status: "error",
4920
+ code
4921
+ });
4922
+ return;
4923
+ }
4924
+ if (session.offline || this.session !== session) return;
4925
+ session.retry = setTimeout(() => {
4926
+ session.retry = void 0;
4927
+ if (this.session === session && !session.offline) this.connect(session);
4928
+ }, reconnectDelay(++session.retries));
4929
+ }
4930
+ async connect(session) {
4931
+ if (this.session !== session || session.offline || session.connection) return;
4932
+ const connection = {
4933
+ abort: new AbortController(),
4934
+ socketRefs: [],
4935
+ channelRefs: [],
4936
+ pending: /* @__PURE__ */ new Set()
4937
+ };
4938
+ session.connection = connection;
4939
+ connection.timer = setTimeout(() => this.fail(session, connection, "CONNECTION_TIMEOUT"), TIMEOUT_MS);
4940
+ try {
4941
+ var _this$core$ɵruntimeE;
4942
+ const runtimeUrl = this.core.runtimeUrl;
4943
+ if (!runtimeUrl) {
4944
+ this.fail(session, connection, "RUNTIME_REQUIRED", false);
4945
+ return;
4946
+ }
4947
+ let transport = this.core.runtimeTransport;
4948
+ if (transport === "auto") {
4949
+ transport = await this.detectedTransport(connection.abort.signal);
4950
+ if (!this.current(session, connection)) return;
4951
+ }
4952
+ const rest = transport === "rest";
4953
+ const response = await fetch(rest ? `${runtimeUrl}/trajectory/${encodeURIComponent(session.trajectoryId)}/connect` : (_this$core$ɵruntimeE = this.core.ɵruntimeEndpointUrl) !== null && _this$core$ɵruntimeE !== void 0 ? _this$core$ɵruntimeE : runtimeUrl, {
4954
+ method: "POST",
4955
+ redirect: "error",
4956
+ signal: connection.abort.signal,
4957
+ headers: {
4958
+ ...this.core.headers,
4959
+ "Content-Type": "application/json"
4960
+ },
4961
+ credentials: this.core.credentials,
4962
+ body: JSON.stringify(rest ? {} : {
4963
+ method: "trajectory/connect",
4964
+ params: { trajectoryId: session.trajectoryId },
4965
+ body: {}
4966
+ })
4967
+ });
4968
+ if (!this.current(session, connection)) return;
4969
+ const payload = await response.json().catch(() => void 0);
4970
+ if (!this.current(session, connection)) return;
4971
+ if (!response.ok) {
4972
+ this.fail(session, connection, errorCode(payload, "CONNECTION_FAILED"), response.status >= 500 || response.status === 408 || response.status === 429);
4973
+ return;
4974
+ }
4975
+ if (!isGrant(payload)) {
4976
+ this.fail(session, connection, "INVALID_GRANT", false);
4977
+ return;
4978
+ }
4979
+ const socket = new phoenix.Socket(payload.realtime.clientUrl, {
4980
+ params: { join_token: payload.joinToken },
4981
+ timeout: TIMEOUT_MS
4982
+ });
4983
+ connection.socket = socket;
4984
+ const lost = () => this.fail(session, connection, "CONNECTION_LOST");
4985
+ connection.socketRefs.push(socket.onError(lost), socket.onClose(lost));
4986
+ const channel = socket.channel(payload.realtime.topic, {});
4987
+ connection.channel = channel;
4988
+ connection.channelRefs.push(["phx_error", channel.onError(lost)], ["phx_close", channel.onClose(lost)]);
4989
+ socket.connect();
4990
+ if (!this.current(session, connection)) return;
4991
+ channel.join(TIMEOUT_MS).receive("ok", () => {
4992
+ if (!this.current(session, connection)) return;
4993
+ try {
4994
+ var _session$config$ignor;
4995
+ clearTimeout(connection.timer);
4996
+ session.ready = true;
4997
+ session.retries = 0;
4998
+ session.collector = (0, _copilotkit_learning.createTrajectoryCollector)({
4999
+ ...session.config,
5000
+ ignoreUrls: [
5001
+ ...(_session$config$ignor = session.config.ignoreUrls) !== null && _session$config$ignor !== void 0 ? _session$config$ignor : [],
5002
+ ...this.core.runtimeUrl ? [this.core.runtimeUrl] : [],
5003
+ ...this.core.ɵruntimeEndpointUrl ? [this.core.ɵruntimeEndpointUrl] : [],
5004
+ "https://telemetry.copilotkit.ai/",
5005
+ "https://cdn.copilotkit.ai/"
5006
+ ],
5007
+ onError: (error) => {
5008
+ if (error.code === "CAPTURE_FAILED") this.fail(session, connection, error.code, false);
5009
+ else {
5010
+ var _session$config$onErr2, _session$config2;
5011
+ if (error.code === "INVALID_EVENT" || error.code === "EVENT_TOO_LARGE") this.addDropped(session, 1);
5012
+ (_session$config$onErr2 = (_session$config2 = session.config).onError) === null || _session$config$onErr2 === void 0 || _session$config$onErr2.call(_session$config2, error);
5013
+ }
5014
+ },
5015
+ send: (event) => this.send(session, connection, event)
5016
+ });
5017
+ session.collector.start();
5018
+ if (!this.current(session, connection)) return;
5019
+ if (session.dropped > 0) this.scheduleFlush(session, connection);
5020
+ session.started = true;
5021
+ session.resolve({
5022
+ status: "started",
5023
+ trajectoryId: session.trajectoryId
5024
+ });
5025
+ this.onChange();
5026
+ } catch (_unused2) {
5027
+ this.fail(session, connection, "CAPTURE_FAILED", false);
5028
+ }
5029
+ }).receive("error", (joinError) => this.fail(session, connection, errorCode(joinError, "JOIN_FAILED"))).receive("timeout", () => this.fail(session, connection, "CONNECTION_TIMEOUT"));
5030
+ } catch (_unused3) {
5031
+ this.fail(session, connection, "CONNECTION_FAILED");
5032
+ }
5033
+ }
5034
+ /** Resolves once auto-detection picks a transport, or with "auto" when the attempt is aborted. */
5035
+ detectedTransport(signal) {
5036
+ return new Promise((resolve) => {
5037
+ const finish = () => {
5038
+ subscription.unsubscribe();
5039
+ signal.removeEventListener("abort", finish);
5040
+ resolve(this.core.runtimeTransport);
5041
+ };
5042
+ const subscription = this.core.subscribe({ onRuntimeConnectionStatusChanged: () => {
5043
+ if (this.core.runtimeTransport !== "auto") finish();
5044
+ } });
5045
+ signal.addEventListener("abort", finish, { once: true });
5046
+ });
5047
+ }
5048
+ addDropped(session, count, schedule = true) {
5049
+ session.dropped = Math.min(Number.MAX_SAFE_INTEGER, session.dropped + count);
5050
+ if (schedule && count > 0 && session.ready && session.connection) this.scheduleFlush(session, session.connection);
5051
+ }
5052
+ scheduleFlush(session, connection) {
5053
+ if (session.flushTimer !== void 0 || !this.current(session, connection)) return;
5054
+ session.flushTimer = setTimeout(() => {
5055
+ session.flushTimer = void 0;
5056
+ this.flush(session, connection);
5057
+ }, BATCH_INTERVAL_MS);
5058
+ }
5059
+ discardQueue(session) {
5060
+ clearTimeout(session.flushTimer);
5061
+ session.flushTimer = void 0;
5062
+ this.addDropped(session, session.queue.length, false);
5063
+ session.queue = [];
5064
+ }
5065
+ connected(connection) {
5066
+ var _connection$socket, _connection$channel;
5067
+ return ((_connection$socket = connection.socket) === null || _connection$socket === void 0 ? void 0 : _connection$socket.isConnected()) === true && ((_connection$channel = connection.channel) === null || _connection$channel === void 0 ? void 0 : _connection$channel.state) === "joined";
5068
+ }
5069
+ send(session, connection, event) {
5070
+ if (!this.current(session, connection) || !session.ready) return;
5071
+ if (!this.connected(connection)) {
5072
+ this.addDropped(session, 1);
5073
+ this.fail(session, connection, "CONNECTION_LOST");
5074
+ return;
5075
+ }
5076
+ if (!Number.isSafeInteger(this.nextSeq)) {
5077
+ this.addDropped(session, 1);
5078
+ this.report(session, "SEQUENCE_EXHAUSTED");
5079
+ return;
5080
+ }
5081
+ const original = event.value;
5082
+ const fields = isObject(original) && !Array.isArray(original) && !Object.hasOwn(original, "seq") ? original : { data: original };
5083
+ const wire = {
5084
+ ...event,
5085
+ value: {
5086
+ ...fields,
5087
+ seq: this.nextSeq++
5088
+ }
5089
+ };
5090
+ if (byteLength(wire) > MAX_EVENT_BYTES) {
5091
+ this.addDropped(session, 1);
5092
+ this.report(session, "EVENT_TOO_LARGE");
5093
+ return;
5094
+ }
5095
+ const fits = () => session.queue.length < MAX_BATCH_EVENTS && byteLength({
5096
+ events: [...session.queue, wire],
5097
+ dropped: Number.MAX_SAFE_INTEGER
5098
+ }) <= MAX_BATCH_BYTES;
5099
+ if (!fits()) this.flush(session, connection);
5100
+ if (!this.current(session, connection) || !session.ready) return;
5101
+ if (!fits()) {
5102
+ this.addDropped(session, 1);
5103
+ this.report(session, "EVENTS_DROPPED");
5104
+ return;
5105
+ }
5106
+ session.queue.push(wire);
5107
+ if (session.queue.length === MAX_BATCH_EVENTS) this.flush(session, connection);
5108
+ else this.scheduleFlush(session, connection);
5109
+ }
5110
+ flush(session, connection) {
5111
+ if (!this.current(session, connection) || !session.ready || session.queue.length === 0 && session.dropped === 0) return;
5112
+ if (!this.connected(connection)) {
5113
+ this.fail(session, connection, "CONNECTION_LOST");
5114
+ return;
5115
+ }
5116
+ if (connection.pending.size > 0) return;
5117
+ clearTimeout(session.flushTimer);
5118
+ session.flushTimer = void 0;
5119
+ const batch = {
5120
+ events: session.queue,
5121
+ dropped: session.dropped
5122
+ };
5123
+ session.queue = [];
5124
+ session.dropped = 0;
5125
+ let finished = false;
5126
+ const pending = {
5127
+ timer: setTimeout(() => pending.finish("PERSISTENCE_UNKNOWN"), TIMEOUT_MS),
5128
+ finish: (code, knownRollback = false, flushNext = true) => {
5129
+ if (finished) return;
5130
+ finished = true;
5131
+ clearTimeout(pending.timer);
5132
+ connection.pending.delete(pending);
5133
+ if (knownRollback) this.addDropped(session, batch.events.length + batch.dropped, false);
5134
+ if (code && this.current(session, connection)) this.report(session, code);
5135
+ if (flushNext && this.current(session, connection) && session.ready && (session.queue.length > 0 || !knownRollback && session.dropped > 0)) this.flush(session, connection);
5136
+ }
5137
+ };
5138
+ connection.pending.add(pending);
5139
+ try {
5140
+ connection.channel.push("events", batch, TIMEOUT_MS).receive("ok", (payload) => {
5141
+ pending.finish(!isBatchAcknowledgement(payload, batch.events.length) ? "PERSISTENCE_UNKNOWN" : payload.rejected > 0 ? "EVENTS_REJECTED" : void 0);
5142
+ }).receive("error", (payload) => {
5143
+ if (!this.current(session, connection)) return;
5144
+ const reason = isObject(payload) ? payload.reason : void 0;
5145
+ if (reason === "unauthorized" || reason === "trajectory_mismatch") {
5146
+ pending.finish(void 0, true, false);
5147
+ this.fail(session, connection, reason.toUpperCase(), false);
5148
+ return;
5149
+ }
5150
+ const rollback = typeof reason === "string" && [
5151
+ "invalid_batch",
5152
+ "batch_too_large",
5153
+ "batch_too_many_events",
5154
+ "trajectory_over_share",
5155
+ "trajectory_outbox_full",
5156
+ "unsupported_event"
5157
+ ].includes(reason);
5158
+ pending.finish(rollback ? reason.toUpperCase() : "PERSISTENCE_UNKNOWN", rollback);
5159
+ }).receive("timeout", () => pending.finish("PERSISTENCE_UNKNOWN"));
5160
+ } catch (_unused4) {
5161
+ pending.finish("PERSISTENCE_UNKNOWN");
5162
+ }
5163
+ }
5164
+ };
5165
+
5166
+ //#endregion
5167
+ //#region src/core/learning-bridge.ts
5168
+ const COPILOTKIT_OWN_URLS = ["https://telemetry.copilotkit.ai/", "https://cdn.copilotkit.ai/"];
5169
+ /**
5170
+ * Wires `@copilotkit/learning` into Core. Default capture uses Runtime and Phoenix;
5171
+ * explicit legacy sinks also use agent events and open-Thread attribution.
5172
+ */
5173
+ var LearningBridge = class {
5174
+ constructor(core, config, onChange = () => {}) {
5175
+ this.core = core;
5176
+ this.config = config;
5177
+ _defineProperty(this, "collector", null);
5178
+ _defineProperty(this, "agents", /* @__PURE__ */ new Map());
5179
+ _defineProperty(this, "openThreads", /* @__PURE__ */ new Set());
5180
+ _defineProperty(this, "toolCalls", /* @__PURE__ */ new Map());
5181
+ _defineProperty(this, "executingTools", /* @__PURE__ */ new Map());
5182
+ _defineProperty(this, "lastRunIds", /* @__PURE__ */ new WeakMap());
5183
+ _defineProperty(this, "lastLinkedThreadId", null);
5184
+ _defineProperty(this, "coreSubscription", null);
5185
+ _defineProperty(this, "seq", 0);
5186
+ _defineProperty(this, "activeConfig", void 0);
5187
+ _defineProperty(this, "connection", void 0);
5188
+ this.connection = new TrajectoryConnection(core, onChange);
5189
+ this.setConfig(config);
5190
+ }
5191
+ setConfig(config) {
5192
+ this.config = config;
5193
+ if (config === void 0) this.stop();
5194
+ }
5195
+ get isConfigured() {
5196
+ return this.config !== void 0;
5197
+ }
5198
+ get isLegacyCaptureActive() {
5199
+ return this.collector !== null && this.collector.trajectoryId !== null;
5200
+ }
5201
+ startTracking() {
5202
+ if (this.coreSubscription !== null || !this.isLegacyCaptureActive) return;
5203
+ this.coreSubscription = this.core.subscribe({
5204
+ onAgentsChanged: ({ agents }) => {
5205
+ for (const agent of Object.values(agents)) this.track(agent);
5206
+ },
5207
+ onAgentRunStarted: ({ agent }) => this.track(agent),
5208
+ onToolExecutionStart: ({ toolCallId, agentId, toolName }) => {
5209
+ if (!this.isLegacyCaptureActive) return;
5210
+ this.executingTools.set(toolCallId, Date.now());
5211
+ this.emitToolCall("executing", toolCallId, agentId, toolName, {});
5212
+ },
5213
+ onToolExecutionEnd: ({ toolCallId, agentId, toolName, error }) => {
5214
+ if (!this.isLegacyCaptureActive) return;
5215
+ const startedAt = this.executingTools.get(toolCallId);
5216
+ this.executingTools.delete(toolCallId);
5217
+ this.emitToolCall("completed", toolCallId, agentId, toolName, {
5218
+ durationMs: startedAt === void 0 ? void 0 : Date.now() - startedAt,
5219
+ outcome: error === void 0 ? "ok" : "error"
5220
+ });
5221
+ this.toolCalls.delete(toolCallId);
5222
+ }
5223
+ });
5224
+ for (const agent of Object.values(this.core.agents)) this.track(agent);
5225
+ }
5226
+ get trajectoryId() {
5227
+ var _ref, _this$connection$traj, _this$collector;
5228
+ return (_ref = (_this$connection$traj = this.connection.trajectoryId) !== null && _this$connection$traj !== void 0 ? _this$connection$traj : (_this$collector = this.collector) === null || _this$collector === void 0 ? void 0 : _this$collector.trajectoryId) !== null && _ref !== void 0 ? _ref : null;
5229
+ }
5230
+ start(options = {}) {
5231
+ var _ref2, _options$trajectoryId, _this$collector2;
5232
+ const config = this.config;
5233
+ if (config === void 0) {
5234
+ console.warn("[CopilotKit] startTrajectory() needs the `learning` option on CopilotKitCore (or the CopilotKitProvider `learning` prop).");
5235
+ return Promise.resolve({
5236
+ status: "error",
5237
+ code: "LEARNING_DISABLED"
5238
+ });
5239
+ }
5240
+ if (config.sink === void 0) {
5241
+ if (options.learningContainerIds !== void 0) console.warn("[CopilotKit] learningContainerIds is supported only with a custom sink. Authenticated Trajectory capture does not assign Learning Containers; remove learningContainerIds from the capture options.");
5242
+ this.stopLegacy();
5243
+ return this.connection.start(options.trajectoryId, config);
5244
+ }
5245
+ this.connection.stop();
5246
+ const trajectoryId = (_ref2 = (_options$trajectoryId = options.trajectoryId) !== null && _options$trajectoryId !== void 0 ? _options$trajectoryId : (_this$collector2 = this.collector) === null || _this$collector2 === void 0 ? void 0 : _this$collector2.trajectoryId) !== null && _ref2 !== void 0 ? _ref2 : crypto.randomUUID();
5247
+ if (this.collector === null) {
5248
+ var _config$ignoreUrls;
5249
+ this.activeConfig = config;
5250
+ const runtimeUrl = this.core.runtimeUrl;
5251
+ this.collector = (0, _copilotkit_learning.createCollector)({
5252
+ ...config,
5253
+ beforeSend: (event) => {
5254
+ const sequenced = {
5255
+ ...event,
5256
+ value: {
5257
+ ...event.value,
5258
+ seq: ++this.seq
5259
+ }
5260
+ };
5261
+ return config.beforeSend === void 0 ? sequenced : config.beforeSend(sequenced);
5262
+ },
5263
+ ignoreUrls: [
5264
+ ...(_config$ignoreUrls = config.ignoreUrls) !== null && _config$ignoreUrls !== void 0 ? _config$ignoreUrls : [],
5265
+ ...COPILOTKIT_OWN_URLS,
5266
+ ...runtimeUrl === void 0 ? [] : [runtimeUrl]
5267
+ ],
5268
+ enrich: (target) => this.enrich(target)
5269
+ });
5270
+ }
5271
+ const wasActive = this.collector.trajectoryId !== null;
5272
+ this.collector.start({
5273
+ ...options,
5274
+ trajectoryId
5275
+ });
5276
+ if (wasActive) return Promise.resolve(this.collector.trajectoryId === trajectoryId ? {
5277
+ status: "started",
5278
+ trajectoryId
5279
+ } : {
5280
+ status: "error",
5281
+ code: "TRAJECTORY_ACTIVE"
5282
+ });
5283
+ this.startTracking();
5284
+ this.lastLinkedThreadId = null;
5285
+ for (const threadId of this.distinctOpenThreadIds()) this.emitThreadLinked(threadId, "start");
5286
+ return Promise.resolve({
5287
+ status: "started",
5288
+ trajectoryId
5289
+ });
5290
+ }
5291
+ stop() {
5292
+ this.connection.stop();
5293
+ this.stopLegacy();
5294
+ }
5295
+ stopLegacy() {
5296
+ var _this$collector3, _this$coreSubscriptio;
5297
+ (_this$collector3 = this.collector) === null || _this$collector3 === void 0 || _this$collector3.stop();
5298
+ this.collector = null;
5299
+ this.activeConfig = void 0;
5300
+ (_this$coreSubscriptio = this.coreSubscription) === null || _this$coreSubscriptio === void 0 || _this$coreSubscriptio.unsubscribe();
5301
+ this.coreSubscription = null;
5302
+ for (const subscription of this.agents.values()) subscription.unsubscribe();
5303
+ this.agents.clear();
5304
+ this.toolCalls.clear();
5305
+ this.executingTools.clear();
5306
+ }
5307
+ /** A developer event. Only an explicit legacy sink adds open-Thread context. */
5308
+ emit(name, value) {
5309
+ this.connection.emit(name, value);
5310
+ if (value !== null && typeof value === "object" && !Array.isArray(value)) {
5311
+ var _this$collector4;
5312
+ (_this$collector4 = this.collector) === null || _this$collector4 === void 0 || _this$collector4.emit(name, {
5313
+ ...this.openThreadContext(),
5314
+ ...value
5315
+ });
5316
+ }
5317
+ }
5318
+ registerOpenThread(params) {
5319
+ const entry = { ...params };
5320
+ const isNew = !this.distinctOpenThreadIds().includes(entry.threadId);
5321
+ this.openThreads.add(entry);
5322
+ if (isNew) this.emitThreadLinked(entry.threadId, "open");
5323
+ return {
5324
+ update: (threadId) => {
5325
+ if (threadId === entry.threadId) return;
5326
+ entry.threadId = threadId;
5327
+ if (![...this.openThreads].filter((other) => other !== entry).some((other) => other.threadId === threadId)) this.emitThreadLinked(threadId, "switch");
5328
+ },
5329
+ unregister: () => {
5330
+ this.openThreads.delete(entry);
5331
+ }
5332
+ };
5333
+ }
5334
+ distinctOpenThreadIds() {
5335
+ return [...new Set([...this.openThreads].map((open) => open.threadId))];
5336
+ }
5337
+ emitThreadLinked(threadId, reason) {
5338
+ var _this$collector5, _ref3, _owner$agentId, _agent$messages$lengt;
5339
+ if (!(this.collector !== null && this.collector.trajectoryId !== null) || threadId === this.lastLinkedThreadId) return;
5340
+ this.lastLinkedThreadId = threadId;
5341
+ const owner = [...this.openThreads].find((open) => open.threadId === threadId);
5342
+ const agent = this.findAgentForThread(threadId);
5343
+ (_this$collector5 = this.collector) === null || _this$collector5 === void 0 || _this$collector5.ɵemit("thread.linked", {
5344
+ threadId,
5345
+ agentId: (_ref3 = (_owner$agentId = owner === null || owner === void 0 ? void 0 : owner.agentId) !== null && _owner$agentId !== void 0 ? _owner$agentId : agent === null || agent === void 0 ? void 0 : agent.agentId) !== null && _ref3 !== void 0 ? _ref3 : null,
5346
+ hasMessages: ((_agent$messages$lengt = agent === null || agent === void 0 ? void 0 : agent.messages.length) !== null && _agent$messages$lengt !== void 0 ? _agent$messages$lengt : 0) > 0,
5347
+ reason
5348
+ });
5349
+ }
5350
+ findAgentForThread(threadId) {
5351
+ return [...this.agents.keys()].find((agent) => agent.threadId === threadId);
5352
+ }
5353
+ track(agent) {
5354
+ const agentId = agent.agentId;
5355
+ if (!this.isLegacyCaptureActive || this.agents.has(agent) || agentId === void 0) return;
5356
+ this.agents.set(agent, agent.subscribe(this.agentSubscriber(agent, agentId)));
5357
+ }
5358
+ agentSubscriber(agent, agentId) {
5359
+ const runIdFor = () => this.lastRunIds.get(agent);
5360
+ return {
5361
+ onRunStartedEvent: ({ event }) => {
5362
+ this.lastRunIds.set(agent, event.runId);
5363
+ this.emitRun("started", agent, event.threadId, event.runId);
5364
+ },
5365
+ onRunFinishedEvent: ({ event }) => {
5366
+ this.emitRun("finished", agent, event.threadId, event.runId);
5367
+ },
5368
+ onRunErrorEvent: () => {
5369
+ var _runIdFor;
5370
+ this.emitRun("error", agent, agent.threadId, (_runIdFor = runIdFor()) !== null && _runIdFor !== void 0 ? _runIdFor : null);
5371
+ },
5372
+ onToolCallStartEvent: ({ event }) => {
5373
+ if (!this.isLegacyCaptureActive) return;
5374
+ const origin = {
5375
+ agentId,
5376
+ threadId: agent.threadId,
5377
+ messageId: event.parentMessageId,
5378
+ runId: runIdFor()
5379
+ };
5380
+ this.toolCalls.set(event.toolCallId, origin);
5381
+ this.emitToolCall("started", event.toolCallId, origin.agentId, event.toolCallName, {});
5382
+ },
5383
+ onToolCallResultEvent: ({ event }) => {
5384
+ if (!this.executingTools.has(event.toolCallId)) this.toolCalls.delete(event.toolCallId);
5385
+ },
5386
+ onNewMessage: ({ message }) => this.emitMessage(agent, message)
5387
+ };
5388
+ }
5389
+ emitRun(phase, agent, threadId, runId) {
5390
+ var _this$collector6;
5391
+ (_this$collector6 = this.collector) === null || _this$collector6 === void 0 || _this$collector6.ɵemit("agent.run", {
5392
+ phase,
5393
+ runId,
5394
+ threadId,
5395
+ agentId: agent.agentId
5396
+ });
5397
+ }
5398
+ emitMessage(agent, message) {
5399
+ var _this$activeConfig, _this$collector7;
5400
+ const content = typeof message.content === "string" ? message.content : "";
5401
+ const includeText = ((_this$activeConfig = this.activeConfig) === null || _this$activeConfig === void 0 || (_this$activeConfig = _this$activeConfig.capture) === null || _this$activeConfig === void 0 ? void 0 : _this$activeConfig.agentText) !== false && typeof message.content === "string";
5402
+ (_this$collector7 = this.collector) === null || _this$collector7 === void 0 || _this$collector7.ɵemit("agent.message", {
5403
+ messageId: message.id,
5404
+ runId: this.runIdForMessage(agent, message.id),
5405
+ threadId: agent.threadId,
5406
+ agentId: agent.agentId,
5407
+ role: message.role,
5408
+ textLength: content.length,
5409
+ ...includeText ? { text: content } : {}
5410
+ });
5411
+ }
5412
+ emitToolCall(phase, toolCallId, agentId, toolName, extra) {
5413
+ var _this$collector8, _origin$threadId;
5414
+ const origin = this.toolCalls.get(toolCallId);
5415
+ (_this$collector8 = this.collector) === null || _this$collector8 === void 0 || _this$collector8.ɵemit("tool.call", {
5416
+ phase,
5417
+ toolCallId,
5418
+ toolName,
5419
+ agentId,
5420
+ threadId: (_origin$threadId = origin === null || origin === void 0 ? void 0 : origin.threadId) !== null && _origin$threadId !== void 0 ? _origin$threadId : null,
5421
+ messageId: origin === null || origin === void 0 ? void 0 : origin.messageId,
5422
+ runId: origin === null || origin === void 0 ? void 0 : origin.runId,
5423
+ ...extra
5424
+ });
5425
+ }
5426
+ runIdForMessage(agent, messageId) {
5427
+ var _ref4, _this$core$getRunIdFo;
5428
+ const agentId = agent.agentId;
5429
+ if (agentId === void 0) return null;
5430
+ return (_ref4 = (_this$core$getRunIdFo = this.core.getRunIdForMessage(agentId, agent.threadId, messageId)) !== null && _this$core$getRunIdFo !== void 0 ? _this$core$getRunIdFo : this.lastRunIds.get(agent)) !== null && _ref4 !== void 0 ? _ref4 : null;
5431
+ }
5432
+ findMessage(messageId) {
5433
+ for (const agent of this.agents.keys()) {
5434
+ const message = agent.messages.find((candidate) => candidate.id === messageId);
5435
+ if (message !== void 0) return {
5436
+ agent,
5437
+ message
5438
+ };
5439
+ }
5440
+ return null;
5441
+ }
5442
+ toolStatus(agent, toolCallId) {
5443
+ if (this.executingTools.has(toolCallId)) return "executing";
5444
+ return agent.messages.some((message) => message.role === "tool" && message.toolCallId === toolCallId) ? "complete" : "inProgress";
5445
+ }
5446
+ /** Adds agent context to a click: exact message first, then the single open Thread. */
5447
+ enrich(target) {
5448
+ var _target$closest$getAt, _target$closest, _target$closest$getAt2, _target$closest2;
5449
+ const messageId = (_target$closest$getAt = (_target$closest = target.closest("[data-message-id]")) === null || _target$closest === void 0 ? void 0 : _target$closest.getAttribute("data-message-id")) !== null && _target$closest$getAt !== void 0 ? _target$closest$getAt : null;
5450
+ const toolCallId = (_target$closest$getAt2 = (_target$closest2 = target.closest("[data-tool-call-id]")) === null || _target$closest2 === void 0 ? void 0 : _target$closest2.getAttribute("data-tool-call-id")) !== null && _target$closest$getAt2 !== void 0 ? _target$closest$getAt2 : null;
5451
+ const found = messageId === null ? null : this.findMessage(messageId);
5452
+ if (found !== null) {
5453
+ var _message$toolCalls;
5454
+ const { agent, message } = found;
5455
+ const toolCall = toolCallId !== null && message.role === "assistant" ? (_message$toolCalls = message.toolCalls) === null || _message$toolCalls === void 0 ? void 0 : _message$toolCalls.find((call) => call.id === toolCallId) : void 0;
5456
+ return {
5457
+ threadId: agent.threadId,
5458
+ agentId: agent.agentId,
5459
+ messageId: message.id,
5460
+ runId: this.runIdForMessage(agent, message.id),
5461
+ ...toolCall === void 0 ? {} : {
5462
+ toolCallId: toolCall.id,
5463
+ toolName: toolCall.function.name,
5464
+ toolStatus: this.toolStatus(agent, toolCall.id)
5465
+ }
5466
+ };
5467
+ }
5468
+ return this.openThreadContext();
5469
+ }
5470
+ /** The single open Thread, or `null` with the candidates when several are open. */
5471
+ openThreadContext() {
5472
+ var _openIds$;
5473
+ const openIds = this.distinctOpenThreadIds();
5474
+ if (openIds.length > 1) return {
5475
+ threadId: null,
5476
+ threadAmbiguity: {
5477
+ reason: "multiple-open",
5478
+ candidates: openIds
5479
+ }
5480
+ };
5481
+ return { threadId: (_openIds$ = openIds[0]) !== null && _openIds$ !== void 0 ? _openIds$ : null };
5482
+ }
5483
+ };
5484
+
4679
5485
  //#endregion
4680
5486
  //#region src/utils/micro-redux.ts
4681
5487
  const INTERNAL_ACTION_TYPES = {
@@ -5820,7 +6626,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
5820
6626
  return Object.fromEntries(Object.entries(headers).filter((entry) => entry[1] != null));
5821
6627
  }
5822
6628
  var CopilotKitCore = class {
5823
- constructor({ runtimeUrl, runtimeTransport = "auto", deferInitialConnection = false, headers = {}, credentials, messageFilter, properties = {}, agents__unsafe_dev_only = {}, tools = [], suggestionsConfig = [], debug }) {
6629
+ constructor({ runtimeUrl, runtimeTransport = "auto", deferInitialConnection = false, headers = {}, credentials, messageFilter, properties = {}, agents__unsafe_dev_only = {}, tools = [], suggestionsConfig = [], debug, learning }) {
5824
6630
  _defineProperty(this, "_headers", void 0);
5825
6631
  _defineProperty(this, "_credentials", void 0);
5826
6632
  _defineProperty(this, "_messageFilter", void 0);
@@ -5834,6 +6640,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
5834
6640
  _defineProperty(this, "runHandler", void 0);
5835
6641
  _defineProperty(this, "stateManager", void 0);
5836
6642
  _defineProperty(this, "threadStoreRegistry", void 0);
6643
+ _defineProperty(this, "learningBridge", void 0);
6644
+ _defineProperty(this, "notifiedTrajectoryId", null);
6645
+ _defineProperty(this, "learningConfiguredListeners", /* @__PURE__ */ new Set());
5837
6646
  _defineProperty(this, "_memoryStore", void 0);
5838
6647
  _defineProperty(this, "previousAgentIds", /* @__PURE__ */ new Set());
5839
6648
  this._headers = normalizeHeaders(headers);
@@ -5851,6 +6660,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
5851
6660
  this.runHandler.initialize(tools);
5852
6661
  this.suggestionEngine.initialize(suggestionsConfig);
5853
6662
  this.stateManager.initialize();
6663
+ this.learningBridge = new LearningBridge(this, learning, () => this.notifyTrajectoryChanged());
5854
6664
  this.agentRegistry.setRuntimeTransport(runtimeTransport);
5855
6665
  this.agentRegistry.setRuntimeUrl(runtimeUrl, { deferConnection: deferInitialConnection });
5856
6666
  this.previousAgentIds = new Set(Object.keys(agents__unsafe_dev_only));
@@ -6005,6 +6815,10 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
6005
6815
  get runtimeConnectionStatus() {
6006
6816
  return this.agentRegistry.runtimeConnectionStatus;
6007
6817
  }
6818
+ /** @internal The verbatim single-endpoint URL, including any trailing slash. */
6819
+ get ɵruntimeEndpointUrl() {
6820
+ return this.agentRegistry.runtimeEndpointUrl;
6821
+ }
6008
6822
  get ɵruntimeFetch() {
6009
6823
  return this.agentRegistry.createRuntimeFetch();
6010
6824
  }
@@ -6170,6 +6984,86 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
6170
6984
  getAgent(id) {
6171
6985
  return this.agentRegistry.getAgent(id);
6172
6986
  }
6987
+ /** Updates settings for the next capture. Removing the config stops capture. */
6988
+ setLearningConfig(config) {
6989
+ const wasConfigured = this.ɵlearningConfigured;
6990
+ this.learningBridge.setConfig(config);
6991
+ this.notifyTrajectoryChanged();
6992
+ if (this.ɵlearningConfigured === wasConfigured) return;
6993
+ for (const listener of this.learningConfiguredListeners) try {
6994
+ listener();
6995
+ } catch (error) {
6996
+ console.error("Learning configured listener error:", error);
6997
+ }
6998
+ }
6999
+ /**
7000
+ * @internal Whether a `learning` config is set. Unlike {@link trajectoryId},
7001
+ * it does not change with capture start, connection failures or reconnects.
7002
+ */
7003
+ get ɵlearningConfigured() {
7004
+ return this.learningBridge.isConfigured;
7005
+ }
7006
+ /** @internal Calls `listener` when {@link ɵlearningConfigured} changes. */
7007
+ ɵsubscribeToLearningConfigured(listener) {
7008
+ this.learningConfiguredListeners.add(listener);
7009
+ return () => {
7010
+ this.learningConfiguredListeners.delete(listener);
7011
+ };
7012
+ }
7013
+ /** The active capture's Trajectory ID, or null while capture is stopped. */
7014
+ get trajectoryId() {
7015
+ return this.learningBridge.trajectoryId;
7016
+ }
7017
+ notifyTrajectoryChanged() {
7018
+ const trajectoryId = this.trajectoryId;
7019
+ if (trajectoryId === this.notifiedTrajectoryId) return;
7020
+ this.notifiedTrajectoryId = trajectoryId;
7021
+ this.notifySubscribers((subscriber) => {
7022
+ var _subscriber$onTraject;
7023
+ return (_subscriber$onTraject = subscriber.onTrajectoryChanged) === null || _subscriber$onTraject === void 0 ? void 0 : _subscriber$onTraject.call(subscriber, {
7024
+ copilotkit: this,
7025
+ trajectoryId
7026
+ });
7027
+ }, "Subscriber onTrajectoryChanged error:");
7028
+ }
7029
+ /**
7030
+ * Starts one Trajectory after Runtime authorization and the Gateway join.
7031
+ * Omit the ID to create one. Repeated starts await the active connection;
7032
+ * a different ID stops the previous capture. Explicit sinks retain the
7033
+ * prototype's synchronous capture and require a stop before changing IDs.
7034
+ *
7035
+ * @example copilotkit.startTrajectory({ trajectoryId: crypto.randomUUID() })
7036
+ */
7037
+ startTrajectory(options = {}) {
7038
+ const result = this.learningBridge.start(options);
7039
+ this.notifyTrajectoryChanged();
7040
+ return result;
7041
+ }
7042
+ /** Cancels pending work and stops capture, attempting one final batch without waiting for its ACK. */
7043
+ stopTrajectory() {
7044
+ this.learningBridge.stop();
7045
+ this.notifyTrajectoryChanged();
7046
+ }
7047
+ /**
7048
+ * Records an outcome that clicks cannot show, such as a saved report or an
7049
+ * approved deal. The wire adds `value.seq`; arrays, primitives, and objects
7050
+ * already containing `seq` are preserved under `value.data`. Explicit legacy
7051
+ * sinks retain object-only events with open-Thread enrichment.
7052
+ * No-op while no Trajectory runs. Events emitted during connection recovery
7053
+ * count as dropped. Built-in names such as `click` are rejected.
7054
+ *
7055
+ * @example copilotkit.emitTrajectoryEvent("deal.approved", { dealId: "deal-1" })
7056
+ */
7057
+ emitTrajectoryEvent(name, value = {}) {
7058
+ this.learningBridge.emit(name, value);
7059
+ }
7060
+ /**
7061
+ * Tells Core that a view shows this Thread, so captured interactions can link to it.
7062
+ * Framework bindings call this; call it yourself only without a CopilotKit provider.
7063
+ */
7064
+ registerOpenThread(params) {
7065
+ return this.learningBridge.registerOpenThread(params);
7066
+ }
6173
7067
  /**
6174
7068
  * Re-apply the current headers to a single agent (delegated to
6175
7069
  * AgentRegistry). Core headers are merged on top of the agent's own