@copilotkit/core 1.62.2 → 1.63.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.cjs +1560 -664
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +483 -3
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +483 -3
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1547 -668
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +1559 -667
- package/dist/index.umd.js.map +1 -1
- package/package.json +2 -2
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('rxjs/fetch')) :
|
|
3
|
+
typeof define === 'function' && define.amd ? define(['exports', '@tanstack/pacer', '@ag-ui/client', '@copilotkit/shared', 'rxjs', 'rxjs/operators', 'phoenix', 'zod-to-json-schema', 'rxjs/fetch'], 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.rxjs_fetch));
|
|
5
|
+
})(this, function(exports, _tanstack_pacer, _ag_ui_client, _copilotkit_shared, rxjs, rxjs_operators, phoenix, zod_to_json_schema, rxjs_fetch) {
|
|
6
6
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
7
7
|
|
|
8
8
|
//#region src/utils/phoenix-observable.ts
|
|
@@ -646,12 +646,12 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
646
646
|
function isZodError(error) {
|
|
647
647
|
return error !== null && typeof error === "object" && "name" in error && error.name === "ZodError";
|
|
648
648
|
}
|
|
649
|
-
function isAbortError(error) {
|
|
649
|
+
function isAbortError$1(error) {
|
|
650
650
|
return (error instanceof DOMException || error instanceof Error) && error.name === "AbortError";
|
|
651
651
|
}
|
|
652
652
|
function withAbortErrorHandling(observable) {
|
|
653
653
|
return observable.pipe((0, rxjs_operators.catchError)((error) => {
|
|
654
|
-
if (isZodError(error) || isAbortError(error)) return rxjs.EMPTY;
|
|
654
|
+
if (isZodError(error) || isAbortError$1(error)) return rxjs.EMPTY;
|
|
655
655
|
throw error;
|
|
656
656
|
}));
|
|
657
657
|
}
|
|
@@ -1005,6 +1005,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1005
1005
|
_defineProperty(this, "localAgents", {});
|
|
1006
1006
|
_defineProperty(this, "remoteAgents", {});
|
|
1007
1007
|
_defineProperty(this, "_runtimeUrl", void 0);
|
|
1008
|
+
_defineProperty(this, "_connectionInFlight", void 0);
|
|
1008
1009
|
_defineProperty(this, "_runtimeVersion", void 0);
|
|
1009
1010
|
_defineProperty(this, "_runtimeConnectionStatus", CopilotKitCoreRuntimeConnectionStatus.Disconnected);
|
|
1010
1011
|
_defineProperty(this, "_runtimeTransport", "auto");
|
|
@@ -1013,6 +1014,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1013
1014
|
_defineProperty(this, "_runtimeMode", _copilotkit_shared.RUNTIME_MODE_SSE);
|
|
1014
1015
|
_defineProperty(this, "_intelligence", void 0);
|
|
1015
1016
|
_defineProperty(this, "_threadEndpoints", void 0);
|
|
1017
|
+
_defineProperty(this, "_suggestions", void 0);
|
|
1016
1018
|
_defineProperty(this, "_a2uiEnabled", false);
|
|
1017
1019
|
_defineProperty(this, "_a2uiAgents", void 0);
|
|
1018
1020
|
_defineProperty(this, "_openGenerativeUIEnabled", false);
|
|
@@ -1050,6 +1052,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1050
1052
|
get threadEndpoints() {
|
|
1051
1053
|
return this._threadEndpoints;
|
|
1052
1054
|
}
|
|
1055
|
+
get suggestions() {
|
|
1056
|
+
return this._suggestions;
|
|
1057
|
+
}
|
|
1053
1058
|
get a2uiEnabled() {
|
|
1054
1059
|
return this._a2uiEnabled;
|
|
1055
1060
|
}
|
|
@@ -1081,10 +1086,28 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1081
1086
|
/**
|
|
1082
1087
|
* Set the runtime URL and update connection
|
|
1083
1088
|
*/
|
|
1084
|
-
setRuntimeUrl(runtimeUrl) {
|
|
1089
|
+
setRuntimeUrl(runtimeUrl, options) {
|
|
1085
1090
|
const normalizedRuntimeUrl = runtimeUrl ? runtimeUrl.replace(/\/$/, "") : void 0;
|
|
1086
1091
|
if (this._runtimeUrl === normalizedRuntimeUrl) return;
|
|
1087
1092
|
this._runtimeUrl = normalizedRuntimeUrl;
|
|
1093
|
+
if (options === null || options === void 0 ? void 0 : options.deferConnection) return;
|
|
1094
|
+
this.updateRuntimeConnection();
|
|
1095
|
+
}
|
|
1096
|
+
/**
|
|
1097
|
+
* Start the initial runtime connection if it has not been started yet.
|
|
1098
|
+
*
|
|
1099
|
+
* Backs {@link CopilotKitCore.connect}. Idempotent: it only kicks off a fetch
|
|
1100
|
+
* when a `runtimeUrl` is set and the connection is still `Disconnected` (its
|
|
1101
|
+
* state before any connect attempt). `updateRuntimeConnection` flips the
|
|
1102
|
+
* status to `Connecting` synchronously, so a second call — e.g. React
|
|
1103
|
+
* StrictMode double-invoking the mount effect — bails here. A genuine config
|
|
1104
|
+
* change still reconnects through `setRuntimeUrl`/`setRuntimeTransport`. See
|
|
1105
|
+
* #5801.
|
|
1106
|
+
*/
|
|
1107
|
+
connectRuntime() {
|
|
1108
|
+
if (typeof window === "undefined") return;
|
|
1109
|
+
if (!this._runtimeUrl) return;
|
|
1110
|
+
if (this._runtimeConnectionStatus !== CopilotKitCoreRuntimeConnectionStatus.Disconnected) return;
|
|
1088
1111
|
this.updateRuntimeConnection();
|
|
1089
1112
|
}
|
|
1090
1113
|
setRuntimeTransport(runtimeTransport) {
|
|
@@ -1229,7 +1252,23 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1229
1252
|
* Update runtime connection and fetch remote agents
|
|
1230
1253
|
*/
|
|
1231
1254
|
async updateRuntimeConnection() {
|
|
1255
|
+
var _this$_runtimeUrl;
|
|
1232
1256
|
if (typeof window === "undefined") return;
|
|
1257
|
+
const key = `${(_this$_runtimeUrl = this._runtimeUrl) !== null && _this$_runtimeUrl !== void 0 ? _this$_runtimeUrl : ""}::${this._requestedTransport}`;
|
|
1258
|
+
const inFlight = this._connectionInFlight;
|
|
1259
|
+
if (inFlight && inFlight.key === key) return inFlight.promise;
|
|
1260
|
+
const promise = this.performRuntimeConnection();
|
|
1261
|
+
this._connectionInFlight = {
|
|
1262
|
+
key,
|
|
1263
|
+
promise
|
|
1264
|
+
};
|
|
1265
|
+
promise.finally(() => {
|
|
1266
|
+
var _this$_connectionInFl;
|
|
1267
|
+
if (((_this$_connectionInFl = this._connectionInFlight) === null || _this$_connectionInFl === void 0 ? void 0 : _this$_connectionInFl.promise) === promise) this._connectionInFlight = void 0;
|
|
1268
|
+
});
|
|
1269
|
+
return promise;
|
|
1270
|
+
}
|
|
1271
|
+
async performRuntimeConnection() {
|
|
1233
1272
|
if (!this.runtimeUrl) {
|
|
1234
1273
|
this._runtimeConnectionStatus = CopilotKitCoreRuntimeConnectionStatus.Disconnected;
|
|
1235
1274
|
this._runtimeVersion = void 0;
|
|
@@ -1237,6 +1276,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1237
1276
|
this._runtimeMode = _copilotkit_shared.RUNTIME_MODE_SSE;
|
|
1238
1277
|
this._intelligence = void 0;
|
|
1239
1278
|
this._threadEndpoints = void 0;
|
|
1279
|
+
this._suggestions = void 0;
|
|
1240
1280
|
this._a2uiEnabled = false;
|
|
1241
1281
|
this._a2uiAgents = void 0;
|
|
1242
1282
|
this._openGenerativeUIEnabled = false;
|
|
@@ -1286,6 +1326,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1286
1326
|
this._runtimeMode = (_runtimeInfoResponse$3 = runtimeInfoResponse.mode) !== null && _runtimeInfoResponse$3 !== void 0 ? _runtimeInfoResponse$3 : _copilotkit_shared.RUNTIME_MODE_SSE;
|
|
1287
1327
|
this._intelligence = runtimeInfoResponse.intelligence;
|
|
1288
1328
|
this._threadEndpoints = runtimeInfoResponse.threadEndpoints;
|
|
1329
|
+
this._suggestions = runtimeInfoResponse.suggestions;
|
|
1289
1330
|
const a2uiInfo = runtimeInfoResponse.a2ui;
|
|
1290
1331
|
this._a2uiEnabled = (_ref = (_a2uiInfo$enabled = a2uiInfo === null || a2uiInfo === void 0 ? void 0 : a2uiInfo.enabled) !== null && _a2uiInfo$enabled !== void 0 ? _a2uiInfo$enabled : runtimeInfoResponse.a2uiEnabled) !== null && _ref !== void 0 ? _ref : false;
|
|
1291
1332
|
this._a2uiAgents = (a2uiInfo === null || a2uiInfo === void 0 ? void 0 : a2uiInfo.enabled) ? a2uiInfo.agents : void 0;
|
|
@@ -1301,6 +1342,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1301
1342
|
this._runtimeMode = _copilotkit_shared.RUNTIME_MODE_SSE;
|
|
1302
1343
|
this._intelligence = void 0;
|
|
1303
1344
|
this._threadEndpoints = void 0;
|
|
1345
|
+
this._suggestions = void 0;
|
|
1304
1346
|
this._a2uiEnabled = false;
|
|
1305
1347
|
this._a2uiAgents = void 0;
|
|
1306
1348
|
this._openGenerativeUIEnabled = false;
|
|
@@ -1551,39 +1593,82 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1551
1593
|
};
|
|
1552
1594
|
}
|
|
1553
1595
|
/**
|
|
1554
|
-
* Generate suggestions
|
|
1596
|
+
* Generate suggestions by running a provider agent and extracting the
|
|
1597
|
+
* `copilotkitSuggest` tool call from its streamed messages.
|
|
1598
|
+
*
|
|
1599
|
+
* Two transports, one set of mechanics: both seed an agent with the
|
|
1600
|
+
* consumer's messages + state and the instruction, then `runAgent` with
|
|
1601
|
+
* forced `copilotkitSuggest` tool choice, parsing suggestions as messages
|
|
1602
|
+
* stream in via `onMessagesChanged`.
|
|
1603
|
+
*
|
|
1604
|
+
* - **Stateless** (runtime advertises `suggestions` and transport isn't
|
|
1605
|
+
* `single`): a stock `HttpAgent` pointed at `/agent/:id/suggest`. That
|
|
1606
|
+
* endpoint runs the provider directly and streams AG-UI SSE **without**
|
|
1607
|
+
* persisting a thread, and a plain `HttpAgent` only ever speaks REST SSE —
|
|
1608
|
+
* it never routes through the Intelligence websocket delegate (which would
|
|
1609
|
+
* persist a thread). This is the path that removes the thread flood.
|
|
1610
|
+
* - **Fallback** (capability absent → old runtime, or `single` transport):
|
|
1611
|
+
* clone the provider agent and run it client-side, as before.
|
|
1612
|
+
*
|
|
1613
|
+
* Gated to non-`single` transports because this client only builds the
|
|
1614
|
+
* multi-route `/agent/:id/suggest` URL; single-route deployments (not the
|
|
1615
|
+
* persisting-thread/Intelligence case) fall through to the clone fallback.
|
|
1555
1616
|
*/
|
|
1556
1617
|
async generateSuggestions(suggestionId, config, consumerAgentId) {
|
|
1557
|
-
let
|
|
1618
|
+
let runHandle = void 0;
|
|
1619
|
+
let aborted = false;
|
|
1558
1620
|
try {
|
|
1559
|
-
var _config$providerAgent,
|
|
1560
|
-
const
|
|
1561
|
-
|
|
1562
|
-
const
|
|
1621
|
+
var _config$providerAgent, _config$minSuggestion, _config$maxSuggestion, _suggestionsConsumerA, _this$_runningSuggest3;
|
|
1622
|
+
const friends = this.core;
|
|
1623
|
+
const resolvedProviderAgentId = (_config$providerAgent = config.providerAgentId) !== null && _config$providerAgent !== void 0 ? _config$providerAgent : "default";
|
|
1624
|
+
const suggestionsProviderAgent = friends.getAgent(resolvedProviderAgentId);
|
|
1625
|
+
if (!suggestionsProviderAgent) throw new Error(`Suggestions provider agent not found: ${resolvedProviderAgentId}`);
|
|
1626
|
+
const suggestionsConsumerAgent = friends.getAgent(consumerAgentId);
|
|
1563
1627
|
if (!suggestionsConsumerAgent) throw new Error(`Suggestions consumer agent not found: ${consumerAgentId}`);
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1628
|
+
const instructionContent = [
|
|
1629
|
+
`Suggest what the user could say next. Provide clear, highly relevant suggestions by calling the \`copilotkitSuggest\` tool.`,
|
|
1630
|
+
`Provide at least ${(_config$minSuggestion = config.minSuggestions) !== null && _config$minSuggestion !== void 0 ? _config$minSuggestion : 1} and at most ${(_config$maxSuggestion = config.maxSuggestions) !== null && _config$maxSuggestion !== void 0 ? _config$maxSuggestion : 3} suggestions.`,
|
|
1631
|
+
`The user has the following tools available: ${JSON.stringify(friends.buildFrontendTools(consumerAgentId))}.`,
|
|
1632
|
+
` ${config.instructions}`
|
|
1633
|
+
].join("\n");
|
|
1568
1634
|
this._suggestions[consumerAgentId] = {
|
|
1569
1635
|
...this._suggestions[consumerAgentId],
|
|
1570
1636
|
[suggestionId]: []
|
|
1571
1637
|
};
|
|
1572
|
-
|
|
1573
|
-
|
|
1638
|
+
const seededMessages = JSON.parse(JSON.stringify(suggestionsConsumerAgent.messages));
|
|
1639
|
+
const seededState = JSON.parse(JSON.stringify((_suggestionsConsumerA = suggestionsConsumerAgent.state) !== null && _suggestionsConsumerA !== void 0 ? _suggestionsConsumerA : {}));
|
|
1640
|
+
const useStateless = this.core.suggestions === true && this.core.runtimeTransport !== "single";
|
|
1641
|
+
let suggestionAgent;
|
|
1642
|
+
if (useStateless) {
|
|
1643
|
+
const suggestUrl = `${this.core.runtimeUrl}/agent/${encodeURIComponent(resolvedProviderAgentId)}/suggest`;
|
|
1644
|
+
const credentials = this.core.credentials;
|
|
1645
|
+
suggestionAgent = new _ag_ui_client.HttpAgent({
|
|
1646
|
+
agentId: resolvedProviderAgentId,
|
|
1647
|
+
url: suggestUrl,
|
|
1648
|
+
headers: { ...this.core.headers },
|
|
1649
|
+
...credentials ? { fetch: (url, requestInit) => fetch(url, {
|
|
1650
|
+
...requestInit,
|
|
1651
|
+
credentials
|
|
1652
|
+
}) } : {}
|
|
1653
|
+
});
|
|
1654
|
+
} else suggestionAgent = suggestionsProviderAgent.clone();
|
|
1655
|
+
suggestionAgent.threadId = suggestionId;
|
|
1656
|
+
suggestionAgent.setMessages(seededMessages);
|
|
1657
|
+
suggestionAgent.setState(seededState);
|
|
1658
|
+
runHandle = { abortRun: () => {
|
|
1659
|
+
aborted = true;
|
|
1660
|
+
suggestionAgent.abortRun();
|
|
1661
|
+
} };
|
|
1662
|
+
this._runningSuggestions[consumerAgentId] = [...(_this$_runningSuggest3 = this._runningSuggestions[consumerAgentId]) !== null && _this$_runningSuggest3 !== void 0 ? _this$_runningSuggest3 : [], runHandle];
|
|
1663
|
+
suggestionAgent.addMessage({
|
|
1574
1664
|
id: suggestionId,
|
|
1575
1665
|
role: "user",
|
|
1576
|
-
content:
|
|
1577
|
-
`Suggest what the user could say next. Provide clear, highly relevant suggestions by calling the \`copilotkitSuggest\` tool.`,
|
|
1578
|
-
`Provide at least ${(_config$minSuggestion = config.minSuggestions) !== null && _config$minSuggestion !== void 0 ? _config$minSuggestion : 1} and at most ${(_config$maxSuggestion = config.maxSuggestions) !== null && _config$maxSuggestion !== void 0 ? _config$maxSuggestion : 3} suggestions.`,
|
|
1579
|
-
`The user has the following tools available: ${JSON.stringify(this.core.buildFrontendTools(consumerAgentId))}.`,
|
|
1580
|
-
` ${config.instructions}`
|
|
1581
|
-
].join("\n")
|
|
1666
|
+
content: instructionContent
|
|
1582
1667
|
});
|
|
1583
|
-
await
|
|
1584
|
-
context:
|
|
1668
|
+
await suggestionAgent.runAgent({
|
|
1669
|
+
context: friends.getContextForAgent(consumerAgentId),
|
|
1585
1670
|
forwardedProps: {
|
|
1586
|
-
...
|
|
1671
|
+
...friends.properties,
|
|
1587
1672
|
toolChoice: {
|
|
1588
1673
|
type: "function",
|
|
1589
1674
|
function: { name: "copilotkitSuggest" }
|
|
@@ -1594,18 +1679,15 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1594
1679
|
this.extractSuggestions(messages, suggestionId, consumerAgentId, true);
|
|
1595
1680
|
} });
|
|
1596
1681
|
} catch (error) {
|
|
1597
|
-
console.warn("Error generating suggestions:", error);
|
|
1682
|
+
if (!isAbortError(error) && !aborted) console.warn("Error generating suggestions:", error);
|
|
1598
1683
|
} finally {
|
|
1599
1684
|
this.finalizeSuggestions(suggestionId, consumerAgentId);
|
|
1600
1685
|
const runningAgents = this._runningSuggestions[consumerAgentId];
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
this._runningSuggestions[consumerAgentId]
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
await this.notifySuggestionsFinishedLoading(consumerAgentId);
|
|
1607
|
-
}
|
|
1608
|
-
}
|
|
1686
|
+
const remaining = runHandle ? (runningAgents !== null && runningAgents !== void 0 ? runningAgents : []).filter((a) => a !== runHandle) : runningAgents !== null && runningAgents !== void 0 ? runningAgents : [];
|
|
1687
|
+
if (remaining.length === 0) {
|
|
1688
|
+
delete this._runningSuggestions[consumerAgentId];
|
|
1689
|
+
await this.notifySuggestionsFinishedLoading(consumerAgentId);
|
|
1690
|
+
} else this._runningSuggestions[consumerAgentId] = remaining;
|
|
1609
1691
|
}
|
|
1610
1692
|
}
|
|
1611
1693
|
/**
|
|
@@ -1743,6 +1825,13 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1743
1825
|
}
|
|
1744
1826
|
};
|
|
1745
1827
|
/**
|
|
1828
|
+
* Detects an `AbortController`-driven cancellation so the stateless path can
|
|
1829
|
+
* treat it as an expected (non-error) outcome on clear/reload.
|
|
1830
|
+
*/
|
|
1831
|
+
function isAbortError(error) {
|
|
1832
|
+
return typeof error === "object" && error !== null && "name" in error && error.name === "AbortError";
|
|
1833
|
+
}
|
|
1834
|
+
/**
|
|
1746
1835
|
* Type guard for dynamic suggestions config
|
|
1747
1836
|
*/
|
|
1748
1837
|
function isDynamicSuggestionsConfig(config) {
|
|
@@ -2716,152 +2805,1130 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
2716
2805
|
};
|
|
2717
2806
|
|
|
2718
2807
|
//#endregion
|
|
2719
|
-
//#region src/
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
CopilotKitCoreErrorCode["TOOL_ARGUMENT_PARSE_FAILED"] = "tool_argument_parse_failed";
|
|
2727
|
-
CopilotKitCoreErrorCode["TOOL_HANDLER_FAILED"] = "tool_handler_failed";
|
|
2728
|
-
CopilotKitCoreErrorCode["TOOL_NOT_FOUND"] = "tool_not_found";
|
|
2729
|
-
CopilotKitCoreErrorCode["AGENT_NOT_FOUND"] = "agent_not_found";
|
|
2730
|
-
/**
|
|
2731
|
-
* Emitted when an agent run fails because the thread is already locked
|
|
2732
|
-
* by another active run.
|
|
2733
|
-
*
|
|
2734
|
-
* @example
|
|
2735
|
-
* ```tsx
|
|
2736
|
-
* <CopilotKitProvider
|
|
2737
|
-
* onError={({ code, error, context }) => {
|
|
2738
|
-
* if (code === "agent_thread_locked") {
|
|
2739
|
-
* // Show "Agent is busy, retry?" UI
|
|
2740
|
-
* }
|
|
2741
|
-
* }}
|
|
2742
|
-
* />
|
|
2743
|
-
* ```
|
|
2744
|
-
*/
|
|
2745
|
-
CopilotKitCoreErrorCode["AGENT_THREAD_LOCKED"] = "agent_thread_locked";
|
|
2746
|
-
CopilotKitCoreErrorCode["TRANSCRIPTION_FAILED"] = "transcription_failed";
|
|
2747
|
-
CopilotKitCoreErrorCode["TRANSCRIPTION_SERVICE_NOT_CONFIGURED"] = "transcription_service_not_configured";
|
|
2748
|
-
CopilotKitCoreErrorCode["TRANSCRIPTION_INVALID_AUDIO"] = "transcription_invalid_audio";
|
|
2749
|
-
CopilotKitCoreErrorCode["TRANSCRIPTION_RATE_LIMITED"] = "transcription_rate_limited";
|
|
2750
|
-
CopilotKitCoreErrorCode["TRANSCRIPTION_AUTH_FAILED"] = "transcription_auth_failed";
|
|
2751
|
-
CopilotKitCoreErrorCode["TRANSCRIPTION_NETWORK_ERROR"] = "transcription_network_error";
|
|
2752
|
-
CopilotKitCoreErrorCode["SUBSCRIBER_CALLBACK_FAILED"] = "subscriber_callback_failed";
|
|
2753
|
-
return CopilotKitCoreErrorCode;
|
|
2754
|
-
}({});
|
|
2808
|
+
//#region src/utils/micro-redux.ts
|
|
2809
|
+
const INTERNAL_ACTION_TYPES = {
|
|
2810
|
+
boot: "@@micro-redux/boot",
|
|
2811
|
+
init: "@@micro-redux/init",
|
|
2812
|
+
stop: "@@micro-redux/stop"
|
|
2813
|
+
};
|
|
2814
|
+
const INTERNAL_BOOT_ACTION = { type: INTERNAL_ACTION_TYPES.boot };
|
|
2755
2815
|
/**
|
|
2756
|
-
*
|
|
2757
|
-
* to module scope so the Set is allocated once, not per-subscription.
|
|
2816
|
+
* Builds a typed action creator from a type string and payload factory.
|
|
2758
2817
|
*/
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
CopilotKitCoreRuntimeConnectionStatus["Disconnected"] = "disconnected";
|
|
2769
|
-
CopilotKitCoreRuntimeConnectionStatus["Connected"] = "connected";
|
|
2770
|
-
CopilotKitCoreRuntimeConnectionStatus["Connecting"] = "connecting";
|
|
2771
|
-
CopilotKitCoreRuntimeConnectionStatus["Error"] = "error";
|
|
2772
|
-
return CopilotKitCoreRuntimeConnectionStatus;
|
|
2773
|
-
}({});
|
|
2818
|
+
function createTypedActionCreator(type, factory) {
|
|
2819
|
+
const creator = ((...args) => ({
|
|
2820
|
+
...factory(...args),
|
|
2821
|
+
type
|
|
2822
|
+
}));
|
|
2823
|
+
creator.type = type;
|
|
2824
|
+
creator.match = (action) => action.type === type;
|
|
2825
|
+
return creator;
|
|
2826
|
+
}
|
|
2774
2827
|
/**
|
|
2775
|
-
*
|
|
2776
|
-
*
|
|
2777
|
-
*
|
|
2778
|
-
*
|
|
2828
|
+
* Declares a payload-based action config for `createActionGroup`.
|
|
2829
|
+
*
|
|
2830
|
+
* @example
|
|
2831
|
+
* ```ts
|
|
2832
|
+
* const actions = createActionGroup("User", {
|
|
2833
|
+
* loaded: props<{ id: string }>(),
|
|
2834
|
+
* });
|
|
2835
|
+
* ```
|
|
2779
2836
|
*/
|
|
2780
|
-
function
|
|
2781
|
-
return
|
|
2837
|
+
function props() {
|
|
2838
|
+
return { kind: "props" };
|
|
2782
2839
|
}
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
this.agentRegistry.setRuntimeTransport(runtimeTransport);
|
|
2813
|
-
this.agentRegistry.setRuntimeUrl(runtimeUrl);
|
|
2814
|
-
this.previousAgentIds = new Set(Object.keys(agents__unsafe_dev_only));
|
|
2815
|
-
this.subscribe({ onAgentsChanged: ({ agents }) => {
|
|
2816
|
-
Object.values(agents).forEach((agent) => {
|
|
2817
|
-
if (agent.agentId) this.stateManager.subscribeToAgent(agent);
|
|
2818
|
-
});
|
|
2819
|
-
const currentAgentIds = new Set(Object.keys(agents));
|
|
2820
|
-
for (const agentId of Object.keys(this.threadStoreRegistry.getAll())) if (this.previousAgentIds.has(agentId) && !currentAgentIds.has(agentId)) try {
|
|
2821
|
-
this.threadStoreRegistry.unregister(agentId);
|
|
2822
|
-
} catch (err) {
|
|
2823
|
-
console.error(`CopilotKitCore.onAgentsChanged: threadStoreRegistry.unregister failed for "${agentId}":`, err);
|
|
2824
|
-
}
|
|
2825
|
-
for (const agentId of this.previousAgentIds) if (!currentAgentIds.has(agentId)) try {
|
|
2826
|
-
this.stateManager.unsubscribeFromAgent(agentId);
|
|
2827
|
-
} catch (err) {
|
|
2828
|
-
console.error(`CopilotKitCore.onAgentsChanged: stateManager.unsubscribeFromAgent failed for "${agentId}":`, err);
|
|
2829
|
-
}
|
|
2830
|
-
this.previousAgentIds = currentAgentIds;
|
|
2831
|
-
} });
|
|
2840
|
+
/**
|
|
2841
|
+
* Declares a no-payload action config for `createActionGroup`.
|
|
2842
|
+
*
|
|
2843
|
+
* @example
|
|
2844
|
+
* ```ts
|
|
2845
|
+
* const actions = createActionGroup("User", {
|
|
2846
|
+
* reset: empty(),
|
|
2847
|
+
* });
|
|
2848
|
+
* ```
|
|
2849
|
+
*/
|
|
2850
|
+
function empty() {
|
|
2851
|
+
return { kind: "empty" };
|
|
2852
|
+
}
|
|
2853
|
+
/**
|
|
2854
|
+
* Creates a namespaced group of typed action creators.
|
|
2855
|
+
*
|
|
2856
|
+
* Action types are formatted as: `[Source] actionName`.
|
|
2857
|
+
*/
|
|
2858
|
+
function createActionGroup(source, config) {
|
|
2859
|
+
const group = {};
|
|
2860
|
+
for (const eventName of Object.keys(config)) {
|
|
2861
|
+
const eventConfig = config[eventName];
|
|
2862
|
+
if (!eventConfig) continue;
|
|
2863
|
+
const actionType = `[${source}] ${eventName}`;
|
|
2864
|
+
if (eventConfig.kind === "props") {
|
|
2865
|
+
group[eventName] = createTypedActionCreator(actionType, (payload) => ({ ...payload }));
|
|
2866
|
+
continue;
|
|
2867
|
+
}
|
|
2868
|
+
group[eventName] = createTypedActionCreator(actionType, () => ({}));
|
|
2832
2869
|
}
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2870
|
+
return group;
|
|
2871
|
+
}
|
|
2872
|
+
/**
|
|
2873
|
+
* Registers one reducer handler for one or more action creators.
|
|
2874
|
+
*
|
|
2875
|
+
* @throws Error when called without at least one action creator and reducer.
|
|
2876
|
+
*/
|
|
2877
|
+
function on(...args) {
|
|
2878
|
+
if (args.length < 2) throw new Error("on requires at least one action creator and one reducer");
|
|
2879
|
+
const reducer = args[args.length - 1];
|
|
2880
|
+
return {
|
|
2881
|
+
creators: args.slice(0, -1),
|
|
2882
|
+
reducer
|
|
2883
|
+
};
|
|
2884
|
+
}
|
|
2885
|
+
/**
|
|
2886
|
+
* Creates a reducer from an initial state and `on(...)` handler entries.
|
|
2887
|
+
*
|
|
2888
|
+
* Unknown action types return the current state unchanged.
|
|
2889
|
+
*/
|
|
2890
|
+
function createReducer(initialState, ...entries) {
|
|
2891
|
+
const reducerMap = /* @__PURE__ */ new Map();
|
|
2892
|
+
for (const entry of entries) for (const creator of entry.creators) {
|
|
2893
|
+
var _reducerMap$get;
|
|
2894
|
+
const handlers = (_reducerMap$get = reducerMap.get(creator.type)) !== null && _reducerMap$get !== void 0 ? _reducerMap$get : [];
|
|
2895
|
+
handlers.push(entry.reducer);
|
|
2896
|
+
reducerMap.set(creator.type, handlers);
|
|
2844
2897
|
}
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2898
|
+
return (state, action) => {
|
|
2899
|
+
const currentState = state !== null && state !== void 0 ? state : initialState;
|
|
2900
|
+
const handlers = reducerMap.get(action.type);
|
|
2901
|
+
if (!handlers || handlers.length === 0) return currentState;
|
|
2902
|
+
let nextState = currentState;
|
|
2903
|
+
for (const handler of handlers) nextState = handler(nextState, action);
|
|
2904
|
+
return nextState;
|
|
2905
|
+
};
|
|
2906
|
+
}
|
|
2907
|
+
/**
|
|
2908
|
+
* Creates a selector that caches and reuses the last computed result
|
|
2909
|
+
* when all input references are unchanged.
|
|
2910
|
+
*/
|
|
2911
|
+
function createSelector(...args) {
|
|
2912
|
+
if (args.length === 1) {
|
|
2913
|
+
const projector = args[0];
|
|
2914
|
+
let hasCached = false;
|
|
2915
|
+
let lastState;
|
|
2916
|
+
let lastResult;
|
|
2917
|
+
return (state) => {
|
|
2918
|
+
if (hasCached && state === lastState) return lastResult;
|
|
2919
|
+
lastState = state;
|
|
2920
|
+
lastResult = projector(state);
|
|
2921
|
+
hasCached = true;
|
|
2922
|
+
return lastResult;
|
|
2923
|
+
};
|
|
2858
2924
|
}
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2925
|
+
const projector = args[args.length - 1];
|
|
2926
|
+
const selectors = args.slice(0, -1);
|
|
2927
|
+
let hasCached = false;
|
|
2928
|
+
let lastInputs = [];
|
|
2929
|
+
let lastResult;
|
|
2930
|
+
return (state) => {
|
|
2931
|
+
const inputs = selectors.map((selector) => selector(state));
|
|
2932
|
+
if (hasCached && inputs.length === lastInputs.length && inputs.every((value, index) => value === lastInputs[index])) return lastResult;
|
|
2933
|
+
lastInputs = inputs;
|
|
2934
|
+
lastResult = projector(...inputs);
|
|
2935
|
+
hasCached = true;
|
|
2936
|
+
return lastResult;
|
|
2937
|
+
};
|
|
2938
|
+
}
|
|
2939
|
+
/**
|
|
2940
|
+
* RxJS operator that maps state emissions through a selector and suppresses
|
|
2941
|
+
* unchanged projected values via reference equality.
|
|
2942
|
+
*/
|
|
2943
|
+
function select(selector) {
|
|
2944
|
+
return (source$) => source$.pipe((0, rxjs_operators.map)(selector), (0, rxjs_operators.distinctUntilChanged)());
|
|
2945
|
+
}
|
|
2946
|
+
/**
|
|
2947
|
+
* RxJS operator that filters an action stream by action creators and narrows
|
|
2948
|
+
* the output action type to the matched creator union.
|
|
2949
|
+
*
|
|
2950
|
+
* @throws Error when called without at least one action creator.
|
|
2951
|
+
*/
|
|
2952
|
+
function ofType(...creators) {
|
|
2953
|
+
if (creators.length === 0) throw new Error("ofType requires at least one action creator");
|
|
2954
|
+
const actionTypes = new Set(creators.map((creator) => creator.type));
|
|
2955
|
+
return (source$) => {
|
|
2956
|
+
return source$.pipe((0, rxjs_operators.filter)((action) => {
|
|
2957
|
+
return actionTypes.has(action.type);
|
|
2958
|
+
}));
|
|
2959
|
+
};
|
|
2960
|
+
}
|
|
2961
|
+
/**
|
|
2962
|
+
* Creates an effect descriptor consumed by `createStore`.
|
|
2963
|
+
*/
|
|
2964
|
+
function createEffect(factory, options = {}) {
|
|
2965
|
+
if (options.dispatch === false) return {
|
|
2966
|
+
run: factory,
|
|
2967
|
+
dispatch: false
|
|
2968
|
+
};
|
|
2969
|
+
return {
|
|
2970
|
+
run: factory,
|
|
2971
|
+
dispatch: true
|
|
2972
|
+
};
|
|
2973
|
+
}
|
|
2974
|
+
/**
|
|
2975
|
+
* Creates a small observable store with reducer + effects.
|
|
2976
|
+
*
|
|
2977
|
+
* Behavior:
|
|
2978
|
+
* - `init()` starts effects and dispatches `@@micro-redux/init`.
|
|
2979
|
+
* - `stop()` dispatches `@@micro-redux/stop` and unsubscribes all effects.
|
|
2980
|
+
* - Effect action observation is scheduled on `asapScheduler` to avoid
|
|
2981
|
+
* synchronous re-entrancy in the effect loop.
|
|
2982
|
+
* - Any effect error triggers fail-fast teardown and errors both `actions$`
|
|
2983
|
+
* and `state$`.
|
|
2984
|
+
*/
|
|
2985
|
+
function createStore(options) {
|
|
2986
|
+
var _options$effects;
|
|
2987
|
+
const reducer = options.reducer;
|
|
2988
|
+
const effects = (_options$effects = options.effects) !== null && _options$effects !== void 0 ? _options$effects : [];
|
|
2989
|
+
let hasFatalError = false;
|
|
2990
|
+
let isRunning = false;
|
|
2991
|
+
let effectSubscriptions = new rxjs.Subscription();
|
|
2992
|
+
let currentState = reducer(void 0, INTERNAL_BOOT_ACTION);
|
|
2993
|
+
const stateSubject = new rxjs.BehaviorSubject(currentState);
|
|
2994
|
+
const actionsSubject = new rxjs.Subject();
|
|
2995
|
+
const dispatchInternal = (action) => {
|
|
2996
|
+
if (hasFatalError) throw new Error("Store is in a failed state due to an effect error");
|
|
2997
|
+
currentState = reducer(currentState, action);
|
|
2998
|
+
stateSubject.next(currentState);
|
|
2999
|
+
actionsSubject.next(action);
|
|
3000
|
+
};
|
|
3001
|
+
const failFast = (error) => {
|
|
3002
|
+
if (hasFatalError) return;
|
|
3003
|
+
hasFatalError = true;
|
|
3004
|
+
isRunning = false;
|
|
3005
|
+
effectSubscriptions.unsubscribe();
|
|
3006
|
+
effectSubscriptions = new rxjs.Subscription();
|
|
3007
|
+
actionsSubject.error(error);
|
|
3008
|
+
stateSubject.error(error);
|
|
3009
|
+
};
|
|
3010
|
+
const startEffects = () => {
|
|
3011
|
+
for (const effect of effects) {
|
|
3012
|
+
const scheduledActions$ = actionsSubject.asObservable().pipe((0, rxjs_operators.observeOn)(rxjs.asapScheduler));
|
|
3013
|
+
const state$ = stateSubject.asObservable();
|
|
3014
|
+
if (effect.dispatch) {
|
|
3015
|
+
const subscription = effect.run(scheduledActions$, state$).subscribe({
|
|
3016
|
+
next: (effectAction) => {
|
|
3017
|
+
if (hasFatalError) return;
|
|
3018
|
+
dispatchInternal(effectAction);
|
|
3019
|
+
},
|
|
3020
|
+
error: (error) => {
|
|
3021
|
+
failFast(error);
|
|
3022
|
+
}
|
|
3023
|
+
});
|
|
3024
|
+
effectSubscriptions.add(subscription);
|
|
3025
|
+
continue;
|
|
3026
|
+
}
|
|
3027
|
+
const subscription = effect.run(scheduledActions$, state$).subscribe({ error: (error) => {
|
|
3028
|
+
failFast(error);
|
|
3029
|
+
} });
|
|
3030
|
+
effectSubscriptions.add(subscription);
|
|
3031
|
+
}
|
|
3032
|
+
};
|
|
3033
|
+
return {
|
|
3034
|
+
dispatch(action) {
|
|
3035
|
+
dispatchInternal(action);
|
|
3036
|
+
},
|
|
3037
|
+
getState() {
|
|
3038
|
+
return currentState;
|
|
3039
|
+
},
|
|
3040
|
+
get state$() {
|
|
3041
|
+
return stateSubject.asObservable();
|
|
3042
|
+
},
|
|
3043
|
+
get actions$() {
|
|
3044
|
+
return actionsSubject.asObservable();
|
|
3045
|
+
},
|
|
3046
|
+
select(selector) {
|
|
3047
|
+
return stateSubject.asObservable().pipe(select(selector));
|
|
3048
|
+
},
|
|
3049
|
+
init() {
|
|
3050
|
+
if (hasFatalError || isRunning) return;
|
|
3051
|
+
isRunning = true;
|
|
3052
|
+
startEffects();
|
|
3053
|
+
if (hasFatalError) return;
|
|
3054
|
+
dispatchInternal({ type: INTERNAL_ACTION_TYPES.init });
|
|
3055
|
+
},
|
|
3056
|
+
stop() {
|
|
3057
|
+
if (hasFatalError || !isRunning) return;
|
|
3058
|
+
dispatchInternal({ type: INTERNAL_ACTION_TYPES.stop });
|
|
3059
|
+
effectSubscriptions.unsubscribe();
|
|
3060
|
+
effectSubscriptions = new rxjs.Subscription();
|
|
3061
|
+
isRunning = false;
|
|
3062
|
+
}
|
|
3063
|
+
};
|
|
3064
|
+
}
|
|
3065
|
+
|
|
3066
|
+
//#endregion
|
|
3067
|
+
//#region src/memory-errors.ts
|
|
3068
|
+
/**
|
|
3069
|
+
* The memory error registry: the single source of truth for memory error
|
|
3070
|
+
* metadata. Keyed by `code` so a code maps to exactly one category/retryable
|
|
3071
|
+
* default.
|
|
3072
|
+
*
|
|
3073
|
+
* Categories/retryable rationale:
|
|
3074
|
+
* - List/credentials/mutation failures are `dependency` (the runtime/platform
|
|
3075
|
+
* the store calls failed). A 5xx is transient (`retryable: true`); a 4xx is
|
|
3076
|
+
* caller-caused, so the helpers below downgrade those to non-retryable.
|
|
3077
|
+
* - Timeouts are `dependency` and `retryable: true` (the request may simply be
|
|
3078
|
+
* slow).
|
|
3079
|
+
*/
|
|
3080
|
+
const MEMORY_ERROR_REGISTRY = Object.freeze({
|
|
3081
|
+
MEMORY_LIST_FAILED: {
|
|
3082
|
+
code: "MEMORY_LIST_FAILED",
|
|
3083
|
+
category: "dependency",
|
|
3084
|
+
retryable: true,
|
|
3085
|
+
message: "Failed to fetch memories",
|
|
3086
|
+
docsPath: "docs/errors/memory.md#memory_list_failed"
|
|
3087
|
+
},
|
|
3088
|
+
MEMORY_CREDENTIALS_FAILED: {
|
|
3089
|
+
code: "MEMORY_CREDENTIALS_FAILED",
|
|
3090
|
+
category: "dependency",
|
|
3091
|
+
retryable: true,
|
|
3092
|
+
message: "Failed to fetch memory subscribe credentials",
|
|
3093
|
+
docsPath: "docs/errors/memory.md#memory_credentials_failed"
|
|
3094
|
+
},
|
|
3095
|
+
MEMORY_MUTATION_FAILED: {
|
|
3096
|
+
code: "MEMORY_MUTATION_FAILED",
|
|
3097
|
+
category: "dependency",
|
|
3098
|
+
retryable: true,
|
|
3099
|
+
message: "Memory mutation request failed",
|
|
3100
|
+
docsPath: "docs/errors/memory.md#memory_mutation_failed"
|
|
3101
|
+
},
|
|
3102
|
+
MEMORY_REQUEST_TIMEOUT: {
|
|
3103
|
+
code: "MEMORY_REQUEST_TIMEOUT",
|
|
3104
|
+
category: "dependency",
|
|
3105
|
+
retryable: true,
|
|
3106
|
+
message: "Request timed out",
|
|
3107
|
+
docsPath: "docs/errors/memory.md#memory_request_timeout"
|
|
3108
|
+
}
|
|
3109
|
+
});
|
|
3110
|
+
/**
|
|
3111
|
+
* An `Error` carrying a stable memory error `code`, `category`, and `retryable`
|
|
3112
|
+
* flag so consumers and observability can branch on it without string-matching
|
|
3113
|
+
* the message.
|
|
3114
|
+
*
|
|
3115
|
+
* It is a real `Error` subclass: `instanceof Error` is true, so the public
|
|
3116
|
+
* `MemoryState.error: Error | null` contract (and the `error: Error | null`
|
|
3117
|
+
* surfaced by `useMemories` / `injectMemories`) holds unchanged. Existing
|
|
3118
|
+
* consumers that only read `.message` keep working; the richer fields are
|
|
3119
|
+
* additive.
|
|
3120
|
+
*/
|
|
3121
|
+
var MemoryError = class MemoryError extends Error {
|
|
3122
|
+
/**
|
|
3123
|
+
* @param code - Registry code identifying this error.
|
|
3124
|
+
* @param options - Optional overrides:
|
|
3125
|
+
* - `message`: human-readable message (defaults to the registry message;
|
|
3126
|
+
* callers pass a status-bearing string to preserve prior wording).
|
|
3127
|
+
* - `retryable`: overrides the registry default (e.g. a 4xx list failure is
|
|
3128
|
+
* not retryable even though the code's default is).
|
|
3129
|
+
* - `cause`: the underlying error, preserved for debugging.
|
|
3130
|
+
*/
|
|
3131
|
+
constructor(code, options) {
|
|
3132
|
+
var _options$message, _options$retryable;
|
|
3133
|
+
const entry = MEMORY_ERROR_REGISTRY[code];
|
|
3134
|
+
super((_options$message = options === null || options === void 0 ? void 0 : options.message) !== null && _options$message !== void 0 ? _options$message : entry.message, { cause: options === null || options === void 0 ? void 0 : options.cause });
|
|
3135
|
+
_defineProperty(this, "code", void 0);
|
|
3136
|
+
_defineProperty(this, "category", void 0);
|
|
3137
|
+
_defineProperty(this, "retryable", void 0);
|
|
3138
|
+
this.name = "MemoryError";
|
|
3139
|
+
this.code = code;
|
|
3140
|
+
this.category = entry.category;
|
|
3141
|
+
this.retryable = (_options$retryable = options === null || options === void 0 ? void 0 : options.retryable) !== null && _options$retryable !== void 0 ? _options$retryable : entry.retryable;
|
|
3142
|
+
Object.setPrototypeOf(this, MemoryError.prototype);
|
|
3143
|
+
}
|
|
3144
|
+
};
|
|
3145
|
+
/**
|
|
3146
|
+
* Narrows an HTTP status to whether the failure is worth retrying: a 5xx (or a
|
|
3147
|
+
* missing/0 status) is a transient dependency failure and retryable; a 4xx is
|
|
3148
|
+
* caller-caused and not. Used so a `MEMORY_LIST_FAILED`/`MEMORY_MUTATION_FAILED`
|
|
3149
|
+
* carries an accurate `retryable` flag derived from the response status.
|
|
3150
|
+
*/
|
|
3151
|
+
function isRetryableStatus(status) {
|
|
3152
|
+
return !(Number.isInteger(status) && status >= 400 && status <= 499);
|
|
3153
|
+
}
|
|
3154
|
+
|
|
3155
|
+
//#endregion
|
|
3156
|
+
//#region src/memory.ts
|
|
3157
|
+
const MEMORIES_PATH = "/memories";
|
|
3158
|
+
const MEMORIES_SUBSCRIBE_PATH = "/memories/subscribe";
|
|
3159
|
+
const REQUEST_TIMEOUT_MS$1 = 15e3;
|
|
3160
|
+
/** Consecutive socket errors tolerated before the realtime stream gives up. */
|
|
3161
|
+
const MAX_SOCKET_RETRIES$1 = 5;
|
|
3162
|
+
/**
|
|
3163
|
+
* HTTP status codes that indicate memory routes are not configured (non-fatal).
|
|
3164
|
+
* 404/501 mean the route is absent/unimplemented; 422 is the runtime's
|
|
3165
|
+
* MISSING_INTELLIGENCE signal (intelligence not configured on the deployment —
|
|
3166
|
+
* see packages/runtime/.../handlers/intelligence/memories.ts). All three map to
|
|
3167
|
+
* the graceful "not available" locked-teaser path, not a hard error.
|
|
3168
|
+
*/
|
|
3169
|
+
const ROUTE_UNAVAILABLE_STATUSES = new Set([
|
|
3170
|
+
404,
|
|
3171
|
+
422,
|
|
3172
|
+
501
|
|
3173
|
+
]);
|
|
3174
|
+
/**
|
|
3175
|
+
* Thrown when a memory route returns a 404/422/501 — treated as "not
|
|
3176
|
+
* configured" (422 is the runtime's MISSING_INTELLIGENCE signal).
|
|
3177
|
+
*/
|
|
3178
|
+
var MemoryRouteUnavailableError = class extends Error {};
|
|
3179
|
+
const initialMemoryState = Object.freeze({
|
|
3180
|
+
memories: Object.freeze([]),
|
|
3181
|
+
isLoading: false,
|
|
3182
|
+
inFlightMutationCount: 0,
|
|
3183
|
+
error: null,
|
|
3184
|
+
context: null,
|
|
3185
|
+
sessionId: 0,
|
|
3186
|
+
available: true,
|
|
3187
|
+
realtimeStatus: "connecting"
|
|
3188
|
+
});
|
|
3189
|
+
const memoryAdapterEvents = createActionGroup("Memory Adapter", {
|
|
3190
|
+
started: empty(),
|
|
3191
|
+
stopped: empty(),
|
|
3192
|
+
contextChanged: props(),
|
|
3193
|
+
addRequested: props(),
|
|
3194
|
+
updateRequested: props(),
|
|
3195
|
+
removeRequested: props()
|
|
3196
|
+
});
|
|
3197
|
+
const memoryRestEvents = createActionGroup("Memory REST", {
|
|
3198
|
+
listRequested: props(),
|
|
3199
|
+
listSucceeded: props(),
|
|
3200
|
+
listFailed: props(),
|
|
3201
|
+
listUnavailable: props(),
|
|
3202
|
+
mutationFinished: props(),
|
|
3203
|
+
credentialsRequested: props(),
|
|
3204
|
+
credentialsSucceeded: props(),
|
|
3205
|
+
credentialsFailed: props(),
|
|
3206
|
+
credentialsUnavailable: props()
|
|
3207
|
+
});
|
|
3208
|
+
const memoryDomainEvents = createActionGroup("Memory Domain", {
|
|
3209
|
+
memoryUpserted: props(),
|
|
3210
|
+
memoryInvalidated: props(),
|
|
3211
|
+
realtimeConnecting: props(),
|
|
3212
|
+
realtimeConnected: props(),
|
|
3213
|
+
realtimeUnavailable: props()
|
|
3214
|
+
});
|
|
3215
|
+
/** Projects a wire memory to the public {@link Memory} shape (drops tenant ids). */
|
|
3216
|
+
function toMemory(memory) {
|
|
3217
|
+
return {
|
|
3218
|
+
id: memory.id,
|
|
3219
|
+
kind: memory.kind,
|
|
3220
|
+
scope: memory.scope,
|
|
3221
|
+
content: memory.content,
|
|
3222
|
+
sourceThreadIds: memory.sourceThreadIds,
|
|
3223
|
+
invalidatedAt: memory.invalidatedAt
|
|
3224
|
+
};
|
|
3225
|
+
}
|
|
3226
|
+
/**
|
|
3227
|
+
* Maps a realtime `memory_metadata` event to the domain action that applies it:
|
|
3228
|
+
* `created`/`updated` upsert the projected memory, `invalidated` removes it by
|
|
3229
|
+
* id. Carries the current `sessionId` so the reducer's session guard can drop
|
|
3230
|
+
* deltas left over from a previous context.
|
|
3231
|
+
*/
|
|
3232
|
+
function mapMemoryMetadataEvent(event, sessionId) {
|
|
3233
|
+
if (event.operation === "invalidated") return memoryDomainEvents.memoryInvalidated({
|
|
3234
|
+
sessionId,
|
|
3235
|
+
memoryId: event.invalidated.id
|
|
3236
|
+
});
|
|
3237
|
+
return memoryDomainEvents.memoryUpserted({
|
|
3238
|
+
sessionId,
|
|
3239
|
+
memory: toMemory(event.memory)
|
|
3240
|
+
});
|
|
3241
|
+
}
|
|
3242
|
+
/**
|
|
3243
|
+
* Inserts or replaces a memory by id. A new memory is prepended (newest first,
|
|
3244
|
+
* matching the REST list's `created_at DESC` ordering without needing a date
|
|
3245
|
+
* field on the public projection); an existing memory is replaced in place.
|
|
3246
|
+
*/
|
|
3247
|
+
function upsertMemory(memories, memory) {
|
|
3248
|
+
const existingIndex = memories.findIndex((item) => item.id === memory.id);
|
|
3249
|
+
if (existingIndex === -1) return [memory, ...memories];
|
|
3250
|
+
const next = [...memories];
|
|
3251
|
+
next[existingIndex] = memory;
|
|
3252
|
+
return next;
|
|
3253
|
+
}
|
|
3254
|
+
const memoryReducer = createReducer(initialMemoryState, on(memoryAdapterEvents.contextChanged, (state, { context }) => ({
|
|
3255
|
+
...state,
|
|
3256
|
+
context,
|
|
3257
|
+
sessionId: state.sessionId + 1,
|
|
3258
|
+
memories: [],
|
|
3259
|
+
isLoading: Boolean(context),
|
|
3260
|
+
inFlightMutationCount: 0,
|
|
3261
|
+
error: null,
|
|
3262
|
+
available: true,
|
|
3263
|
+
realtimeStatus: "connecting"
|
|
3264
|
+
})), on(memoryAdapterEvents.stopped, (state) => ({
|
|
3265
|
+
...state,
|
|
3266
|
+
memories: [],
|
|
3267
|
+
isLoading: false,
|
|
3268
|
+
inFlightMutationCount: 0,
|
|
3269
|
+
error: null,
|
|
3270
|
+
available: true,
|
|
3271
|
+
realtimeStatus: "connecting"
|
|
3272
|
+
})), on(memoryRestEvents.listRequested, (state, { sessionId }) => {
|
|
3273
|
+
if (sessionId !== state.sessionId || !state.context) return state;
|
|
3274
|
+
return {
|
|
3275
|
+
...state,
|
|
3276
|
+
isLoading: true,
|
|
3277
|
+
error: null,
|
|
3278
|
+
available: true
|
|
3279
|
+
};
|
|
3280
|
+
}), on(memoryRestEvents.listFailed, (state, { sessionId, error }) => {
|
|
3281
|
+
if (sessionId !== state.sessionId) return state;
|
|
3282
|
+
return {
|
|
3283
|
+
...state,
|
|
3284
|
+
isLoading: false,
|
|
3285
|
+
error
|
|
3286
|
+
};
|
|
3287
|
+
}), on(memoryRestEvents.listUnavailable, (state, { sessionId }) => {
|
|
3288
|
+
if (sessionId !== state.sessionId) return state;
|
|
3289
|
+
return {
|
|
3290
|
+
...state,
|
|
3291
|
+
memories: [],
|
|
3292
|
+
isLoading: false,
|
|
3293
|
+
error: null,
|
|
3294
|
+
available: false
|
|
3295
|
+
};
|
|
3296
|
+
}), on(memoryAdapterEvents.addRequested, memoryAdapterEvents.updateRequested, memoryAdapterEvents.removeRequested, (state) => ({
|
|
3297
|
+
...state,
|
|
3298
|
+
inFlightMutationCount: state.inFlightMutationCount + 1
|
|
3299
|
+
})), on(memoryRestEvents.mutationFinished, (state, { outcome }) => {
|
|
3300
|
+
if (outcome.sessionId !== state.sessionId) return state;
|
|
3301
|
+
return {
|
|
3302
|
+
...state,
|
|
3303
|
+
inFlightMutationCount: Math.max(0, state.inFlightMutationCount - 1),
|
|
3304
|
+
error: outcome.ok ? null : outcome.error
|
|
3305
|
+
};
|
|
3306
|
+
}), on(memoryRestEvents.listSucceeded, (state, { sessionId, memories }) => {
|
|
3307
|
+
if (sessionId !== state.sessionId) return state;
|
|
3308
|
+
return {
|
|
3309
|
+
...state,
|
|
3310
|
+
memories,
|
|
3311
|
+
isLoading: false,
|
|
3312
|
+
error: null,
|
|
3313
|
+
available: true
|
|
3314
|
+
};
|
|
3315
|
+
}), on(memoryDomainEvents.memoryUpserted, (state, { sessionId, memory }) => {
|
|
3316
|
+
if (sessionId !== state.sessionId) return state;
|
|
3317
|
+
return {
|
|
3318
|
+
...state,
|
|
3319
|
+
memories: upsertMemory(state.memories, memory)
|
|
3320
|
+
};
|
|
3321
|
+
}), on(memoryDomainEvents.memoryInvalidated, (state, { sessionId, memoryId }) => {
|
|
3322
|
+
if (sessionId !== state.sessionId) return state;
|
|
3323
|
+
return {
|
|
3324
|
+
...state,
|
|
3325
|
+
memories: state.memories.filter((memory) => memory.id !== memoryId)
|
|
3326
|
+
};
|
|
3327
|
+
}), on(memoryDomainEvents.realtimeConnecting, (state, { sessionId }) => {
|
|
3328
|
+
if (sessionId !== state.sessionId) return state;
|
|
3329
|
+
return {
|
|
3330
|
+
...state,
|
|
3331
|
+
realtimeStatus: "connecting"
|
|
3332
|
+
};
|
|
3333
|
+
}), on(memoryDomainEvents.realtimeConnected, (state, { sessionId }) => {
|
|
3334
|
+
if (sessionId !== state.sessionId) return state;
|
|
3335
|
+
return {
|
|
3336
|
+
...state,
|
|
3337
|
+
realtimeStatus: "connected"
|
|
3338
|
+
};
|
|
3339
|
+
}), on(memoryDomainEvents.realtimeUnavailable, (state, { sessionId }) => {
|
|
3340
|
+
if (sessionId !== state.sessionId) return state;
|
|
3341
|
+
return {
|
|
3342
|
+
...state,
|
|
3343
|
+
realtimeStatus: "unavailable"
|
|
3344
|
+
};
|
|
3345
|
+
}));
|
|
3346
|
+
const selectMemories = createSelector((state) => state.memories);
|
|
3347
|
+
const selectMemoriesIsLoading = createSelector((state) => state.isLoading);
|
|
3348
|
+
const selectMemoriesError = createSelector((state) => state.error);
|
|
3349
|
+
/**
|
|
3350
|
+
* Reports whether at least one mutation is in flight. Derived from
|
|
3351
|
+
* `inFlightMutationCount` so concurrent mutations stay correct: the boolean
|
|
3352
|
+
* only clears once every in-flight mutation has settled.
|
|
3353
|
+
*/
|
|
3354
|
+
const selectMemoriesIsMutating = createSelector((state) => state.inFlightMutationCount > 0);
|
|
3355
|
+
/**
|
|
3356
|
+
* Reports whether the memory routes are available. Becomes `false` after a
|
|
3357
|
+
* 404, 422 (the runtime's MISSING_INTELLIGENCE signal), or 501 response during
|
|
3358
|
+
* an auto-activation read; defaults to `true`.
|
|
3359
|
+
*/
|
|
3360
|
+
const selectMemoriesAvailable = createSelector((state) => state.available);
|
|
3361
|
+
/**
|
|
3362
|
+
* Reports the realtime-connection health (see {@link MemoryRealtimeStatus}).
|
|
3363
|
+
* Distinct from `available`/`error`: it reflects ONLY the live socket/channel,
|
|
3364
|
+
* so the UI can suppress a "live" indicator once realtime permanently dies even
|
|
3365
|
+
* while the REST list route stays healthy. Defaults to `"connecting"`.
|
|
3366
|
+
*/
|
|
3367
|
+
const selectMemoriesRealtimeStatus = createSelector((state) => state.realtimeStatus);
|
|
3368
|
+
const MEMORY_METADATA_EVENT = "memory_metadata";
|
|
3369
|
+
function memoryFromFetch(input, init) {
|
|
3370
|
+
return (0, rxjs_fetch.fromFetch)(input, init);
|
|
3371
|
+
}
|
|
3372
|
+
/**
|
|
3373
|
+
* Fetches the memory snapshot and maps it to a success/failure action. Keeps
|
|
3374
|
+
* only user-scoped memories (v1 surfaces user scope only; the realtime stream
|
|
3375
|
+
* is user-scoped too), so project-scoped rows visible to the caller are
|
|
3376
|
+
* dropped from the store.
|
|
3377
|
+
*/
|
|
3378
|
+
function createMemoryFetchObservable(environment, context, sessionId) {
|
|
3379
|
+
return (0, rxjs.defer)(() => {
|
|
3380
|
+
const qs = context.includeInvalidated ? "?includeInvalidated=true" : "";
|
|
3381
|
+
return memoryFromFetch(`${context.runtimeUrl}${MEMORIES_PATH}${qs}`, {
|
|
3382
|
+
selector: (response) => {
|
|
3383
|
+
if (!response.ok) {
|
|
3384
|
+
if (ROUTE_UNAVAILABLE_STATUSES.has(response.status)) throw new MemoryRouteUnavailableError(String(response.status));
|
|
3385
|
+
throw new MemoryError("MEMORY_LIST_FAILED", {
|
|
3386
|
+
message: `Failed to fetch memories: ${response.status}`,
|
|
3387
|
+
retryable: isRetryableStatus(response.status)
|
|
3388
|
+
});
|
|
3389
|
+
}
|
|
3390
|
+
return response.json();
|
|
3391
|
+
},
|
|
3392
|
+
fetch: environment.fetch,
|
|
3393
|
+
method: "GET",
|
|
3394
|
+
headers: { ...context.headers }
|
|
3395
|
+
}).pipe((0, rxjs_operators.timeout)({
|
|
3396
|
+
first: REQUEST_TIMEOUT_MS$1,
|
|
3397
|
+
with: () => {
|
|
3398
|
+
throw new MemoryError("MEMORY_REQUEST_TIMEOUT");
|
|
3399
|
+
}
|
|
3400
|
+
}), (0, rxjs_operators.map)((data) => memoryRestEvents.listSucceeded({
|
|
3401
|
+
sessionId,
|
|
3402
|
+
memories: data.memories.filter((memory) => memory.scope === "user")
|
|
3403
|
+
})), (0, rxjs_operators.catchError)((error) => {
|
|
3404
|
+
if (error instanceof MemoryRouteUnavailableError) return (0, rxjs.of)(memoryRestEvents.listUnavailable({ sessionId }));
|
|
3405
|
+
return (0, rxjs.of)(memoryRestEvents.listFailed({
|
|
3406
|
+
sessionId,
|
|
3407
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
3408
|
+
}));
|
|
3409
|
+
}));
|
|
3410
|
+
});
|
|
3411
|
+
}
|
|
3412
|
+
/**
|
|
3413
|
+
* Fetches join credentials from the `/memories/subscribe` endpoint and maps
|
|
3414
|
+
* the response to a success/failure action. Requires both `joinToken` and
|
|
3415
|
+
* `joinCode` to be non-empty strings; throws otherwise so the `catchError`
|
|
3416
|
+
* path emits `credentialsFailed`.
|
|
3417
|
+
*/
|
|
3418
|
+
function createMemoryCredentialsFetchObservable(environment, context, sessionId) {
|
|
3419
|
+
return (0, rxjs.defer)(() => memoryFromFetch(`${context.runtimeUrl}${MEMORIES_SUBSCRIBE_PATH}`, {
|
|
3420
|
+
selector: async (response) => {
|
|
3421
|
+
if (!response.ok) {
|
|
3422
|
+
if (ROUTE_UNAVAILABLE_STATUSES.has(response.status)) throw new MemoryRouteUnavailableError(String(response.status));
|
|
3423
|
+
throw new MemoryError("MEMORY_CREDENTIALS_FAILED", {
|
|
3424
|
+
message: `Failed to fetch memory subscribe credentials: ${response.status}`,
|
|
3425
|
+
retryable: isRetryableStatus(response.status)
|
|
3426
|
+
});
|
|
3427
|
+
}
|
|
3428
|
+
return response.json();
|
|
3429
|
+
},
|
|
3430
|
+
fetch: environment.fetch,
|
|
3431
|
+
method: "POST",
|
|
3432
|
+
headers: {
|
|
3433
|
+
...context.headers,
|
|
3434
|
+
"Content-Type": "application/json"
|
|
3435
|
+
},
|
|
3436
|
+
body: JSON.stringify({})
|
|
3437
|
+
}).pipe((0, rxjs_operators.timeout)({
|
|
3438
|
+
first: REQUEST_TIMEOUT_MS$1,
|
|
3439
|
+
with: () => {
|
|
3440
|
+
throw new MemoryError("MEMORY_REQUEST_TIMEOUT");
|
|
3441
|
+
}
|
|
3442
|
+
}), (0, rxjs_operators.map)((data) => {
|
|
3443
|
+
if (typeof data.joinToken !== "string" || data.joinToken.length === 0) throw new Error("missing joinToken");
|
|
3444
|
+
if (typeof data.joinCode !== "string" || data.joinCode.length === 0) throw new Error("missing joinCode");
|
|
3445
|
+
return memoryRestEvents.credentialsSucceeded({
|
|
3446
|
+
sessionId,
|
|
3447
|
+
joinToken: data.joinToken,
|
|
3448
|
+
joinCode: data.joinCode
|
|
3449
|
+
});
|
|
3450
|
+
}), (0, rxjs_operators.catchError)((error) => {
|
|
3451
|
+
if (error instanceof MemoryRouteUnavailableError) return (0, rxjs.of)(memoryRestEvents.credentialsUnavailable({ sessionId }));
|
|
3452
|
+
return (0, rxjs.of)(memoryRestEvents.credentialsFailed({
|
|
3453
|
+
sessionId,
|
|
3454
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
3455
|
+
}));
|
|
3456
|
+
})));
|
|
3457
|
+
}
|
|
3458
|
+
/** Projects a REST mutation response to the public {@link Memory} shape. */
|
|
3459
|
+
function responseToMemory(data) {
|
|
3460
|
+
return {
|
|
3461
|
+
id: data.id,
|
|
3462
|
+
kind: data.kind,
|
|
3463
|
+
scope: data.scope,
|
|
3464
|
+
content: data.content,
|
|
3465
|
+
sourceThreadIds: data.sourceThreadIds,
|
|
3466
|
+
invalidatedAt: data.invalidatedAt
|
|
3467
|
+
};
|
|
3468
|
+
}
|
|
3469
|
+
const MEMORY_KINDS = new Set([
|
|
3470
|
+
"topical",
|
|
3471
|
+
"episodic",
|
|
3472
|
+
"operational"
|
|
3473
|
+
]);
|
|
3474
|
+
const MEMORY_SCOPES = new Set(["user", "project"]);
|
|
3475
|
+
/**
|
|
3476
|
+
* Validates the required fields of a create/supersede REST response before it is
|
|
3477
|
+
* projected to a {@link Memory}. Returns an `Error` describing the first
|
|
3478
|
+
* missing/invalid field, or `null` when the body is well-formed. Without this a
|
|
3479
|
+
* malformed 200 body yields a Memory with undefined fields that gets upserted.
|
|
3480
|
+
*/
|
|
3481
|
+
function validateMutationResponse(data) {
|
|
3482
|
+
if (!data || typeof data !== "object") return /* @__PURE__ */ new Error("memory mutation response missing/invalid body");
|
|
3483
|
+
if (typeof data.id !== "string" || data.id.length === 0) return /* @__PURE__ */ new Error("memory mutation response missing/invalid id");
|
|
3484
|
+
if (typeof data.kind !== "string" || !MEMORY_KINDS.has(data.kind)) return /* @__PURE__ */ new Error("memory mutation response missing/invalid kind");
|
|
3485
|
+
if (typeof data.scope !== "string" || !MEMORY_SCOPES.has(data.scope)) return /* @__PURE__ */ new Error("memory mutation response missing/invalid scope");
|
|
3486
|
+
if (typeof data.content !== "string") return /* @__PURE__ */ new Error("memory mutation response missing/invalid content");
|
|
3487
|
+
if (!Array.isArray(data.sourceThreadIds) || !data.sourceThreadIds.every((id) => typeof id === "string")) return /* @__PURE__ */ new Error("memory mutation response missing/invalid sourceThreadIds");
|
|
3488
|
+
if (data.invalidatedAt !== null && typeof data.invalidatedAt !== "string") return /* @__PURE__ */ new Error("memory mutation response missing/invalid invalidatedAt");
|
|
3489
|
+
return null;
|
|
3490
|
+
}
|
|
3491
|
+
/**
|
|
3492
|
+
* Request body for create/supersede. `scope` is forwarded only when the caller
|
|
3493
|
+
* supplies it: the platform owns the default (`scope` defaults to `"user"` in
|
|
3494
|
+
* the `/api/memories` schema), so the store does not second-guess it here —
|
|
3495
|
+
* one default, at the contract owner. `sourceThreadIds` defaults to `[]`.
|
|
3496
|
+
*/
|
|
3497
|
+
function toMutationBody(input) {
|
|
3498
|
+
var _input$sourceThreadId;
|
|
3499
|
+
return {
|
|
3500
|
+
content: input.content,
|
|
3501
|
+
kind: input.kind,
|
|
3502
|
+
...input.scope !== void 0 ? { scope: input.scope } : {},
|
|
3503
|
+
sourceThreadIds: (_input$sourceThreadId = input.sourceThreadIds) !== null && _input$sourceThreadId !== void 0 ? _input$sourceThreadId : []
|
|
3504
|
+
};
|
|
3505
|
+
}
|
|
3506
|
+
/**
|
|
3507
|
+
* Builds the actions a successful mutation dispatches (server-authoritative):
|
|
3508
|
+
* the REST response is applied to local state immediately, and the realtime
|
|
3509
|
+
* event reconciles idempotently (upsert-by-id). `mutationFinished` resolves the
|
|
3510
|
+
* caller's promise.
|
|
3511
|
+
*/
|
|
3512
|
+
function buildMutationSuccessActions(request, data) {
|
|
3513
|
+
const { requestId, sessionId } = request;
|
|
3514
|
+
if (request.kind === "remove") return [memoryDomainEvents.memoryInvalidated({
|
|
3515
|
+
sessionId,
|
|
3516
|
+
memoryId: request.id
|
|
3517
|
+
}), memoryRestEvents.mutationFinished({ outcome: {
|
|
3518
|
+
requestId,
|
|
3519
|
+
sessionId,
|
|
3520
|
+
ok: true,
|
|
3521
|
+
memory: null
|
|
3522
|
+
} })];
|
|
3523
|
+
const validationError = validateMutationResponse(data);
|
|
3524
|
+
if (validationError) return [memoryRestEvents.mutationFinished({ outcome: {
|
|
3525
|
+
requestId,
|
|
3526
|
+
sessionId,
|
|
3527
|
+
ok: false,
|
|
3528
|
+
error: validationError
|
|
3529
|
+
} })];
|
|
3530
|
+
const memory = responseToMemory(data);
|
|
3531
|
+
if (request.kind === "update") {
|
|
3532
|
+
const retiredId = data.retiredId;
|
|
3533
|
+
if (typeof retiredId !== "string" || retiredId.length === 0) return [memoryRestEvents.mutationFinished({ outcome: {
|
|
3534
|
+
requestId,
|
|
3535
|
+
sessionId,
|
|
3536
|
+
ok: false,
|
|
3537
|
+
error: /* @__PURE__ */ new Error("supersede response missing retiredId")
|
|
3538
|
+
} })];
|
|
3539
|
+
return [
|
|
3540
|
+
memoryDomainEvents.memoryInvalidated({
|
|
3541
|
+
sessionId,
|
|
3542
|
+
memoryId: retiredId
|
|
3543
|
+
}),
|
|
3544
|
+
memoryDomainEvents.memoryUpserted({
|
|
3545
|
+
sessionId,
|
|
3546
|
+
memory
|
|
3547
|
+
}),
|
|
3548
|
+
memoryRestEvents.mutationFinished({ outcome: {
|
|
3549
|
+
requestId,
|
|
3550
|
+
sessionId,
|
|
3551
|
+
ok: true,
|
|
3552
|
+
memory
|
|
3553
|
+
} })
|
|
3554
|
+
];
|
|
3555
|
+
}
|
|
3556
|
+
return [memoryDomainEvents.memoryUpserted({
|
|
3557
|
+
sessionId,
|
|
3558
|
+
memory
|
|
3559
|
+
}), memoryRestEvents.mutationFinished({ outcome: {
|
|
3560
|
+
requestId,
|
|
3561
|
+
sessionId,
|
|
3562
|
+
ok: true,
|
|
3563
|
+
memory
|
|
3564
|
+
} })];
|
|
3565
|
+
}
|
|
3566
|
+
/** Performs a create/supersede/retire HTTP call and emits its resulting actions. */
|
|
3567
|
+
function createMemoryMutationObservable(environment, context, request) {
|
|
3568
|
+
const method = request.kind === "add" ? "POST" : request.kind === "update" ? "PATCH" : "DELETE";
|
|
3569
|
+
const path = request.kind === "add" ? MEMORIES_PATH : `${MEMORIES_PATH}/${encodeURIComponent(request.id)}`;
|
|
3570
|
+
return (0, rxjs.defer)(() => memoryFromFetch(`${context.runtimeUrl}${path}`, {
|
|
3571
|
+
selector: async (response) => {
|
|
3572
|
+
if (!response.ok) throw new MemoryError("MEMORY_MUTATION_FAILED", {
|
|
3573
|
+
message: `Request failed: ${response.status}`,
|
|
3574
|
+
retryable: isRetryableStatus(response.status)
|
|
3575
|
+
});
|
|
3576
|
+
return request.kind === "remove" ? null : await response.json();
|
|
3577
|
+
},
|
|
3578
|
+
fetch: environment.fetch,
|
|
3579
|
+
method,
|
|
3580
|
+
headers: {
|
|
3581
|
+
...context.headers,
|
|
3582
|
+
"Content-Type": "application/json"
|
|
3583
|
+
},
|
|
3584
|
+
body: request.kind === "remove" ? void 0 : JSON.stringify(request.body)
|
|
3585
|
+
}).pipe((0, rxjs_operators.timeout)({
|
|
3586
|
+
first: REQUEST_TIMEOUT_MS$1,
|
|
3587
|
+
with: () => {
|
|
3588
|
+
throw new MemoryError("MEMORY_REQUEST_TIMEOUT");
|
|
3589
|
+
}
|
|
3590
|
+
}), (0, rxjs_operators.mergeMap)((data) => (0, rxjs.of)(...buildMutationSuccessActions(request, data))), (0, rxjs_operators.catchError)((error) => (0, rxjs.of)(memoryRestEvents.mutationFinished({ outcome: {
|
|
3591
|
+
requestId: request.requestId,
|
|
3592
|
+
sessionId: request.sessionId,
|
|
3593
|
+
ok: false,
|
|
3594
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
3595
|
+
} })))));
|
|
3596
|
+
}
|
|
3597
|
+
/**
|
|
3598
|
+
* Creates the framework-agnostic memory store: a REST snapshot on `setContext`,
|
|
3599
|
+
* server-authoritative add/update/remove mutations, and realtime
|
|
3600
|
+
* `memory_metadata` deltas off the injected `user_meta` event source — all
|
|
3601
|
+
* reduced into observable state.
|
|
3602
|
+
*/
|
|
3603
|
+
function createMemoryStore(environment) {
|
|
3604
|
+
let memoryRequestId = 0;
|
|
3605
|
+
const createMemoryRequestId = () => {
|
|
3606
|
+
memoryRequestId += 1;
|
|
3607
|
+
return `memory-request-${memoryRequestId}`;
|
|
3608
|
+
};
|
|
3609
|
+
const bootstrapEffect = createEffect((actions$, state$) => actions$.pipe(ofType(memoryAdapterEvents.contextChanged), (0, rxjs_operators.withLatestFrom)(state$), (0, rxjs_operators.filter)(([, state]) => Boolean(state.context)), (0, rxjs_operators.map)(([, state]) => memoryRestEvents.listRequested({ sessionId: state.sessionId }))));
|
|
3610
|
+
const credentialsBootstrapEffect = createEffect((actions$, state$) => actions$.pipe(ofType(memoryAdapterEvents.contextChanged), (0, rxjs_operators.withLatestFrom)(state$), (0, rxjs_operators.filter)(([, state]) => Boolean(state.context)), (0, rxjs_operators.map)(([, state]) => memoryRestEvents.credentialsRequested({ sessionId: state.sessionId }))));
|
|
3611
|
+
const credentialsFetchEffect = createEffect((actions$, state$) => actions$.pipe(ofType(memoryRestEvents.credentialsRequested), (0, rxjs_operators.switchMap)((action) => state$.pipe((0, rxjs_operators.map)((state) => state.context), (0, rxjs_operators.filter)((context) => Boolean(context)), (0, rxjs_operators.take)(1), (0, rxjs_operators.map)((context) => ({
|
|
3612
|
+
action,
|
|
3613
|
+
context
|
|
3614
|
+
})), (0, rxjs_operators.takeUntil)(actions$.pipe(ofType(memoryAdapterEvents.contextChanged, memoryAdapterEvents.stopped))), (0, rxjs_operators.switchMap)(({ action: currentAction, context }) => createMemoryCredentialsFetchObservable(environment, context, currentAction.sessionId))))));
|
|
3615
|
+
const store = createStore({
|
|
3616
|
+
reducer: memoryReducer,
|
|
3617
|
+
effects: [
|
|
3618
|
+
bootstrapEffect,
|
|
3619
|
+
credentialsBootstrapEffect,
|
|
3620
|
+
createEffect((actions$, state$) => actions$.pipe(ofType(memoryRestEvents.listRequested), (0, rxjs_operators.switchMap)((action) => state$.pipe((0, rxjs_operators.map)((state) => state.context), (0, rxjs_operators.filter)((context) => Boolean(context)), (0, rxjs_operators.take)(1), (0, rxjs_operators.map)((context) => ({
|
|
3621
|
+
action,
|
|
3622
|
+
context
|
|
3623
|
+
})), (0, rxjs_operators.takeUntil)(actions$.pipe(ofType(memoryAdapterEvents.contextChanged, memoryAdapterEvents.stopped))), (0, rxjs_operators.switchMap)(({ action: currentAction, context }) => createMemoryFetchObservable(environment, context, currentAction.sessionId)))))),
|
|
3624
|
+
credentialsFetchEffect,
|
|
3625
|
+
createEffect((actions$, state$) => actions$.pipe(ofType(memoryAdapterEvents.addRequested, memoryAdapterEvents.updateRequested, memoryAdapterEvents.removeRequested), (0, rxjs_operators.withLatestFrom)(state$), (0, rxjs_operators.mergeMap)(([action, state]) => {
|
|
3626
|
+
const context = state.context;
|
|
3627
|
+
const sessionId = state.sessionId;
|
|
3628
|
+
if (!(context === null || context === void 0 ? void 0 : context.runtimeUrl)) return (0, rxjs.of)(memoryRestEvents.mutationFinished({ outcome: {
|
|
3629
|
+
requestId: action.requestId,
|
|
3630
|
+
sessionId,
|
|
3631
|
+
ok: false,
|
|
3632
|
+
error: /* @__PURE__ */ new Error("Runtime URL is not configured")
|
|
3633
|
+
} }));
|
|
3634
|
+
if (memoryAdapterEvents.addRequested.match(action)) return createMemoryMutationObservable(environment, context, {
|
|
3635
|
+
requestId: action.requestId,
|
|
3636
|
+
sessionId,
|
|
3637
|
+
kind: "add",
|
|
3638
|
+
body: toMutationBody(action.input)
|
|
3639
|
+
});
|
|
3640
|
+
if (memoryAdapterEvents.updateRequested.match(action)) return createMemoryMutationObservable(environment, context, {
|
|
3641
|
+
requestId: action.requestId,
|
|
3642
|
+
sessionId,
|
|
3643
|
+
kind: "update",
|
|
3644
|
+
id: action.id,
|
|
3645
|
+
body: toMutationBody(action.changes)
|
|
3646
|
+
});
|
|
3647
|
+
return createMemoryMutationObservable(environment, context, {
|
|
3648
|
+
requestId: action.requestId,
|
|
3649
|
+
sessionId,
|
|
3650
|
+
kind: "remove",
|
|
3651
|
+
id: action.id
|
|
3652
|
+
});
|
|
3653
|
+
}))),
|
|
3654
|
+
createEffect((actions$, state$) => actions$.pipe(ofType(memoryRestEvents.credentialsSucceeded), (0, rxjs_operators.withLatestFrom)(state$), (0, rxjs_operators.filter)(([action, state]) => {
|
|
3655
|
+
var _state$context;
|
|
3656
|
+
return action.sessionId === state.sessionId && Boolean((_state$context = state.context) === null || _state$context === void 0 ? void 0 : _state$context.wsUrl);
|
|
3657
|
+
}), (0, rxjs_operators.switchMap)(([action, state]) => {
|
|
3658
|
+
const context = state.context;
|
|
3659
|
+
const { joinToken, joinCode } = action;
|
|
3660
|
+
const sessionId = action.sessionId;
|
|
3661
|
+
const shutdown$ = actions$.pipe(ofType(memoryAdapterEvents.contextChanged, memoryAdapterEvents.stopped));
|
|
3662
|
+
return (0, rxjs.defer)(() => {
|
|
3663
|
+
const socket$ = ɵphoenixSocket$({
|
|
3664
|
+
url: context.wsUrl,
|
|
3665
|
+
options: {
|
|
3666
|
+
params: { join_token: joinToken },
|
|
3667
|
+
reconnectAfterMs: (0, _copilotkit_shared.phoenixExponentialBackoff)(100, 1e4),
|
|
3668
|
+
rejoinAfterMs: (0, _copilotkit_shared.phoenixExponentialBackoff)(1e3, 3e4)
|
|
3669
|
+
}
|
|
3670
|
+
}).pipe((0, rxjs_operators.shareReplay)({
|
|
3671
|
+
bufferSize: 1,
|
|
3672
|
+
refCount: true
|
|
3673
|
+
}));
|
|
3674
|
+
const channel$ = ɵphoenixChannel$({
|
|
3675
|
+
socket$,
|
|
3676
|
+
topic: `user_meta:memories:${joinCode}`
|
|
3677
|
+
}).pipe((0, rxjs_operators.shareReplay)({
|
|
3678
|
+
bufferSize: 1,
|
|
3679
|
+
refCount: true
|
|
3680
|
+
}));
|
|
3681
|
+
const fatalSocketShutdown$ = ɵobservePhoenixSocketHealth$(ɵobservePhoenixSocketSignals$(socket$).pipe((0, rxjs_operators.share)()), MAX_SOCKET_RETRIES$1).pipe((0, rxjs_operators.catchError)(() => {
|
|
3682
|
+
console.warn(`[memory] WebSocket failed after ${MAX_SOCKET_RETRIES$1} attempts, giving up`);
|
|
3683
|
+
return (0, rxjs.of)(void 0);
|
|
3684
|
+
}), (0, rxjs_operators.share)());
|
|
3685
|
+
const fatalStatus$ = fatalSocketShutdown$.pipe((0, rxjs_operators.map)(() => memoryDomainEvents.realtimeUnavailable({ sessionId })));
|
|
3686
|
+
const metadata$ = channel$.pipe((0, rxjs_operators.switchMap)(({ channel }) => ɵobservePhoenixEvent$(channel, MEMORY_METADATA_EVENT)), (0, rxjs_operators.map)((event) => mapMemoryMetadataEvent(event, action.sessionId)));
|
|
3687
|
+
const join$ = ɵjoinPhoenixChannel$(channel$).pipe((0, rxjs_operators.concatWith)((0, rxjs.of)(memoryDomainEvents.realtimeConnected({ sessionId }))), (0, rxjs_operators.catchError)((error) => {
|
|
3688
|
+
console.warn(`[memory] failed to join user_meta:memories:${joinCode}`, error);
|
|
3689
|
+
return (0, rxjs.of)(memoryDomainEvents.realtimeUnavailable({ sessionId }));
|
|
3690
|
+
}));
|
|
3691
|
+
return (0, rxjs.merge)((0, rxjs.of)(memoryDomainEvents.realtimeConnecting({ sessionId })), metadata$, join$, fatalStatus$).pipe((0, rxjs_operators.takeUntil)((0, rxjs.merge)(shutdown$, fatalSocketShutdown$.pipe((0, rxjs.observeOn)(rxjs.asapScheduler)))), (0, rxjs_operators.finalize)(() => {}));
|
|
3692
|
+
});
|
|
3693
|
+
})))
|
|
3694
|
+
]
|
|
3695
|
+
});
|
|
3696
|
+
function trackMutation(dispatchAction, extract) {
|
|
3697
|
+
const { requestId } = dispatchAction;
|
|
3698
|
+
const resultPromise = (0, rxjs.firstValueFrom)((0, rxjs.merge)(store.actions$.pipe(ofType(memoryRestEvents.mutationFinished), (0, rxjs_operators.filter)((action) => action.outcome.requestId === requestId), (0, rxjs_operators.map)((action) => action.outcome)), store.actions$.pipe(ofType(memoryAdapterEvents.stopped), (0, rxjs_operators.map)(() => ({
|
|
3699
|
+
requestId,
|
|
3700
|
+
sessionId: store.getState().sessionId,
|
|
3701
|
+
ok: false,
|
|
3702
|
+
error: /* @__PURE__ */ new Error("Memory store stopped before mutation completed")
|
|
3703
|
+
})))).pipe((0, rxjs_operators.take)(1))).then((outcome) => {
|
|
3704
|
+
if (!outcome.ok) throw outcome.error;
|
|
3705
|
+
return extract(outcome);
|
|
3706
|
+
});
|
|
3707
|
+
store.dispatch(dispatchAction);
|
|
3708
|
+
return resultPromise;
|
|
3709
|
+
}
|
|
3710
|
+
return {
|
|
3711
|
+
start() {
|
|
3712
|
+
store.init();
|
|
3713
|
+
store.dispatch(memoryAdapterEvents.started());
|
|
3714
|
+
},
|
|
3715
|
+
stop() {
|
|
3716
|
+
store.dispatch(memoryAdapterEvents.stopped());
|
|
3717
|
+
store.stop();
|
|
3718
|
+
},
|
|
3719
|
+
setContext(context) {
|
|
3720
|
+
store.dispatch(memoryAdapterEvents.contextChanged({ context }));
|
|
3721
|
+
},
|
|
3722
|
+
refresh() {
|
|
3723
|
+
const { sessionId, context } = store.getState();
|
|
3724
|
+
if (!context) return Promise.resolve();
|
|
3725
|
+
const done = (0, rxjs.firstValueFrom)((0, rxjs.merge)(store.actions$.pipe(ofType(memoryRestEvents.listSucceeded, memoryRestEvents.listFailed, memoryRestEvents.listUnavailable), (0, rxjs_operators.filter)((action) => action.sessionId === sessionId)), store.actions$.pipe(ofType(memoryAdapterEvents.stopped)), store.actions$.pipe(ofType(memoryAdapterEvents.contextChanged))).pipe((0, rxjs_operators.take)(1))).then((action) => {
|
|
3726
|
+
if (memoryRestEvents.listFailed.match(action)) throw action.error;
|
|
3727
|
+
if (memoryAdapterEvents.stopped.match(action)) throw new Error("Memory store stopped before refresh completed");
|
|
3728
|
+
if (memoryAdapterEvents.contextChanged.match(action)) return;
|
|
3729
|
+
});
|
|
3730
|
+
store.dispatch(memoryRestEvents.listRequested({ sessionId }));
|
|
3731
|
+
return done;
|
|
3732
|
+
},
|
|
3733
|
+
addMemory(input) {
|
|
3734
|
+
return trackMutation(memoryAdapterEvents.addRequested({
|
|
3735
|
+
requestId: createMemoryRequestId(),
|
|
3736
|
+
input
|
|
3737
|
+
}), (outcome) => {
|
|
3738
|
+
if (outcome.memory == null) throw new Error("add resolved without a memory");
|
|
3739
|
+
return outcome.memory;
|
|
3740
|
+
});
|
|
3741
|
+
},
|
|
3742
|
+
updateMemory(id, changes) {
|
|
3743
|
+
return trackMutation(memoryAdapterEvents.updateRequested({
|
|
3744
|
+
requestId: createMemoryRequestId(),
|
|
3745
|
+
id,
|
|
3746
|
+
changes
|
|
3747
|
+
}), (outcome) => {
|
|
3748
|
+
if (outcome.memory == null) throw new Error("update resolved without a memory");
|
|
3749
|
+
return outcome.memory;
|
|
3750
|
+
});
|
|
3751
|
+
},
|
|
3752
|
+
removeMemory(id) {
|
|
3753
|
+
return trackMutation(memoryAdapterEvents.removeRequested({
|
|
3754
|
+
requestId: createMemoryRequestId(),
|
|
3755
|
+
id
|
|
3756
|
+
}), () => void 0);
|
|
3757
|
+
},
|
|
3758
|
+
getState() {
|
|
3759
|
+
return store.getState();
|
|
3760
|
+
},
|
|
3761
|
+
getServerState() {
|
|
3762
|
+
return initialMemoryState;
|
|
3763
|
+
},
|
|
3764
|
+
select: store.select.bind(store)
|
|
3765
|
+
};
|
|
3766
|
+
}
|
|
3767
|
+
const ɵmemoryAdapterEvents = memoryAdapterEvents;
|
|
3768
|
+
const ɵmemoryRestEvents = memoryRestEvents;
|
|
3769
|
+
const ɵmemoryDomainEvents = memoryDomainEvents;
|
|
3770
|
+
const ɵmemoryReducer = memoryReducer;
|
|
3771
|
+
const ɵmapMemoryMetadataEvent = mapMemoryMetadataEvent;
|
|
3772
|
+
const ɵselectMemories = selectMemories;
|
|
3773
|
+
const ɵselectMemoriesIsLoading = selectMemoriesIsLoading;
|
|
3774
|
+
const ɵselectMemoriesError = selectMemoriesError;
|
|
3775
|
+
const ɵselectMemoriesIsMutating = selectMemoriesIsMutating;
|
|
3776
|
+
const ɵselectMemoriesAvailable = selectMemoriesAvailable;
|
|
3777
|
+
const ɵselectMemoriesRealtimeStatus = selectMemoriesRealtimeStatus;
|
|
3778
|
+
|
|
3779
|
+
//#endregion
|
|
3780
|
+
//#region src/core/core.ts
|
|
3781
|
+
let CopilotKitCoreErrorCode = /* @__PURE__ */ function(CopilotKitCoreErrorCode) {
|
|
3782
|
+
CopilotKitCoreErrorCode["RUNTIME_INFO_FETCH_FAILED"] = "runtime_info_fetch_failed";
|
|
3783
|
+
CopilotKitCoreErrorCode["AGENT_CONNECT_FAILED"] = "agent_connect_failed";
|
|
3784
|
+
CopilotKitCoreErrorCode["AGENT_RUN_FAILED"] = "agent_run_failed";
|
|
3785
|
+
CopilotKitCoreErrorCode["AGENT_RUN_FAILED_EVENT"] = "agent_run_failed_event";
|
|
3786
|
+
CopilotKitCoreErrorCode["AGENT_RUN_ERROR_EVENT"] = "agent_run_error_event";
|
|
3787
|
+
CopilotKitCoreErrorCode["TOOL_ARGUMENT_PARSE_FAILED"] = "tool_argument_parse_failed";
|
|
3788
|
+
CopilotKitCoreErrorCode["TOOL_HANDLER_FAILED"] = "tool_handler_failed";
|
|
3789
|
+
CopilotKitCoreErrorCode["TOOL_NOT_FOUND"] = "tool_not_found";
|
|
3790
|
+
CopilotKitCoreErrorCode["AGENT_NOT_FOUND"] = "agent_not_found";
|
|
3791
|
+
/**
|
|
3792
|
+
* Emitted when an agent run fails because the thread is already locked
|
|
3793
|
+
* by another active run.
|
|
3794
|
+
*
|
|
3795
|
+
* @example
|
|
3796
|
+
* ```tsx
|
|
3797
|
+
* <CopilotKitProvider
|
|
3798
|
+
* onError={({ code, error, context }) => {
|
|
3799
|
+
* if (code === "agent_thread_locked") {
|
|
3800
|
+
* // Show "Agent is busy, retry?" UI
|
|
3801
|
+
* }
|
|
3802
|
+
* }}
|
|
3803
|
+
* />
|
|
3804
|
+
* ```
|
|
3805
|
+
*/
|
|
3806
|
+
CopilotKitCoreErrorCode["AGENT_THREAD_LOCKED"] = "agent_thread_locked";
|
|
3807
|
+
CopilotKitCoreErrorCode["TRANSCRIPTION_FAILED"] = "transcription_failed";
|
|
3808
|
+
CopilotKitCoreErrorCode["TRANSCRIPTION_SERVICE_NOT_CONFIGURED"] = "transcription_service_not_configured";
|
|
3809
|
+
CopilotKitCoreErrorCode["TRANSCRIPTION_INVALID_AUDIO"] = "transcription_invalid_audio";
|
|
3810
|
+
CopilotKitCoreErrorCode["TRANSCRIPTION_RATE_LIMITED"] = "transcription_rate_limited";
|
|
3811
|
+
CopilotKitCoreErrorCode["TRANSCRIPTION_AUTH_FAILED"] = "transcription_auth_failed";
|
|
3812
|
+
CopilotKitCoreErrorCode["TRANSCRIPTION_NETWORK_ERROR"] = "transcription_network_error";
|
|
3813
|
+
CopilotKitCoreErrorCode["SUBSCRIBER_CALLBACK_FAILED"] = "subscriber_callback_failed";
|
|
3814
|
+
return CopilotKitCoreErrorCode;
|
|
3815
|
+
}({});
|
|
3816
|
+
/**
|
|
3817
|
+
* Runtime allowlist derived from {@link SUBSCRIBE_TO_AGENT_KEYS}. Hoisted
|
|
3818
|
+
* to module scope so the Set is allocated once, not per-subscription.
|
|
3819
|
+
*/
|
|
3820
|
+
const ALLOWED_KEYS = new Set([
|
|
3821
|
+
"onMessagesChanged",
|
|
3822
|
+
"onStateChanged",
|
|
3823
|
+
"onRunInitialized",
|
|
3824
|
+
"onRunFinalized",
|
|
3825
|
+
"onRunFailed",
|
|
3826
|
+
"onRunErrorEvent"
|
|
3827
|
+
]);
|
|
3828
|
+
let CopilotKitCoreRuntimeConnectionStatus = /* @__PURE__ */ function(CopilotKitCoreRuntimeConnectionStatus) {
|
|
3829
|
+
CopilotKitCoreRuntimeConnectionStatus["Disconnected"] = "disconnected";
|
|
3830
|
+
CopilotKitCoreRuntimeConnectionStatus["Connected"] = "connected";
|
|
3831
|
+
CopilotKitCoreRuntimeConnectionStatus["Connecting"] = "connecting";
|
|
3832
|
+
CopilotKitCoreRuntimeConnectionStatus["Error"] = "error";
|
|
3833
|
+
return CopilotKitCoreRuntimeConnectionStatus;
|
|
3834
|
+
}({});
|
|
3835
|
+
/**
|
|
3836
|
+
* Normalize a header map to the internal invariant: a `Record<string, string>`
|
|
3837
|
+
* with no `null`/`undefined` values. Entries whose value is `null`/`undefined`
|
|
3838
|
+
* are dropped (this is how a header is cleared). Shared by the constructor and
|
|
3839
|
+
* `setHeaders` so both write paths into `_headers` enforce the same invariant.
|
|
3840
|
+
*/
|
|
3841
|
+
function normalizeHeaders(headers) {
|
|
3842
|
+
return Object.fromEntries(Object.entries(headers).filter((entry) => entry[1] != null));
|
|
3843
|
+
}
|
|
3844
|
+
var CopilotKitCore = class {
|
|
3845
|
+
constructor({ runtimeUrl, runtimeTransport = "auto", deferInitialConnection = false, headers = {}, credentials, properties = {}, agents__unsafe_dev_only = {}, tools = [], suggestionsConfig = [], debug }) {
|
|
3846
|
+
_defineProperty(this, "_headers", void 0);
|
|
3847
|
+
_defineProperty(this, "_credentials", void 0);
|
|
3848
|
+
_defineProperty(this, "_properties", void 0);
|
|
3849
|
+
_defineProperty(this, "_defaultThrottleMs", void 0);
|
|
3850
|
+
_defineProperty(this, "_debug", void 0);
|
|
3851
|
+
_defineProperty(this, "subscribers", /* @__PURE__ */ new Set());
|
|
3852
|
+
_defineProperty(this, "agentRegistry", void 0);
|
|
3853
|
+
_defineProperty(this, "contextStore", void 0);
|
|
3854
|
+
_defineProperty(this, "suggestionEngine", void 0);
|
|
3855
|
+
_defineProperty(this, "runHandler", void 0);
|
|
3856
|
+
_defineProperty(this, "stateManager", void 0);
|
|
3857
|
+
_defineProperty(this, "threadStoreRegistry", void 0);
|
|
3858
|
+
_defineProperty(this, "_memoryStore", void 0);
|
|
3859
|
+
_defineProperty(this, "previousAgentIds", /* @__PURE__ */ new Set());
|
|
3860
|
+
this._headers = normalizeHeaders(headers);
|
|
3861
|
+
this._credentials = credentials;
|
|
3862
|
+
this._properties = properties;
|
|
3863
|
+
this._debug = debug;
|
|
3864
|
+
this.agentRegistry = new AgentRegistry(this);
|
|
3865
|
+
this.contextStore = new ContextStore(this);
|
|
3866
|
+
this.suggestionEngine = new SuggestionEngine(this);
|
|
3867
|
+
this.runHandler = new RunHandler(this);
|
|
3868
|
+
this.stateManager = new StateManager(this);
|
|
3869
|
+
this.threadStoreRegistry = new ThreadStoreRegistry(this);
|
|
3870
|
+
this.agentRegistry.initialize(agents__unsafe_dev_only);
|
|
3871
|
+
this.runHandler.initialize(tools);
|
|
3872
|
+
this.suggestionEngine.initialize(suggestionsConfig);
|
|
3873
|
+
this.stateManager.initialize();
|
|
3874
|
+
this.agentRegistry.setRuntimeTransport(runtimeTransport);
|
|
3875
|
+
this.agentRegistry.setRuntimeUrl(runtimeUrl, { deferConnection: deferInitialConnection });
|
|
3876
|
+
this.previousAgentIds = new Set(Object.keys(agents__unsafe_dev_only));
|
|
3877
|
+
this.subscribe({
|
|
3878
|
+
onRuntimeConnectionStatusChanged: () => {
|
|
3879
|
+
if (this._memoryStore) this.syncMemoryContext();
|
|
3880
|
+
},
|
|
3881
|
+
onAgentsChanged: ({ agents }) => {
|
|
3882
|
+
Object.values(agents).forEach((agent) => {
|
|
3883
|
+
if (agent.agentId) this.stateManager.subscribeToAgent(agent);
|
|
3884
|
+
});
|
|
3885
|
+
const currentAgentIds = new Set(Object.keys(agents));
|
|
3886
|
+
for (const agentId of Object.keys(this.threadStoreRegistry.getAll())) if (this.previousAgentIds.has(agentId) && !currentAgentIds.has(agentId)) try {
|
|
3887
|
+
this.threadStoreRegistry.unregister(agentId);
|
|
3888
|
+
} catch (err) {
|
|
3889
|
+
console.error(`CopilotKitCore.onAgentsChanged: threadStoreRegistry.unregister failed for "${agentId}":`, err);
|
|
3890
|
+
}
|
|
3891
|
+
for (const agentId of this.previousAgentIds) if (!currentAgentIds.has(agentId)) try {
|
|
3892
|
+
this.stateManager.unsubscribeFromAgent(agentId);
|
|
3893
|
+
} catch (err) {
|
|
3894
|
+
console.error(`CopilotKitCore.onAgentsChanged: stateManager.unsubscribeFromAgent failed for "${agentId}":`, err);
|
|
3895
|
+
}
|
|
3896
|
+
this.previousAgentIds = currentAgentIds;
|
|
3897
|
+
}
|
|
3898
|
+
});
|
|
3899
|
+
}
|
|
3900
|
+
/**
|
|
3901
|
+
* Internal method used by delegate classes and subclasses to notify subscribers
|
|
3902
|
+
*/
|
|
3903
|
+
async notifySubscribers(handler, errorMessage) {
|
|
3904
|
+
await Promise.all(Array.from(this.subscribers).map(async (subscriber) => {
|
|
3905
|
+
try {
|
|
3906
|
+
await handler(subscriber);
|
|
3907
|
+
} catch (error) {
|
|
3908
|
+
console.error(errorMessage, error);
|
|
3909
|
+
}
|
|
3910
|
+
}));
|
|
3911
|
+
}
|
|
3912
|
+
/**
|
|
3913
|
+
* Internal method used by delegate classes to emit errors
|
|
3914
|
+
*/
|
|
3915
|
+
async emitError({ error, code, context = {} }) {
|
|
3916
|
+
await this.notifySubscribers((subscriber) => {
|
|
3917
|
+
var _subscriber$onError;
|
|
3918
|
+
return (_subscriber$onError = subscriber.onError) === null || _subscriber$onError === void 0 ? void 0 : _subscriber$onError.call(subscriber, {
|
|
3919
|
+
copilotkit: this,
|
|
3920
|
+
error,
|
|
3921
|
+
code,
|
|
3922
|
+
context
|
|
3923
|
+
});
|
|
3924
|
+
}, "Subscriber onError error:");
|
|
3925
|
+
}
|
|
3926
|
+
/**
|
|
3927
|
+
* Log a message to the console and emit an error to subscribers.
|
|
3928
|
+
* Catches failures from `emitError` itself to prevent unhandled rejections.
|
|
3929
|
+
*/
|
|
3930
|
+
logAndEmitError(message, params, logLevel = "error") {
|
|
3931
|
+
console[logLevel](message, params.error);
|
|
2865
3932
|
this.emitError(params).catch((emitErr) => {
|
|
2866
3933
|
console.error(message + " — emitError itself failed:", emitErr);
|
|
2867
3934
|
});
|
|
@@ -2884,6 +3951,18 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
2884
3951
|
setRuntimeUrl(runtimeUrl) {
|
|
2885
3952
|
this.agentRegistry.setRuntimeUrl(runtimeUrl);
|
|
2886
3953
|
}
|
|
3954
|
+
/**
|
|
3955
|
+
* Start the runtime `/info` connection if it has not been started yet.
|
|
3956
|
+
*
|
|
3957
|
+
* Intended to be driven from a host's commit-phase effect when the core was
|
|
3958
|
+
* constructed with {@link CopilotKitCoreConfig.deferInitialConnection}. Safe
|
|
3959
|
+
* to call repeatedly — it is a no-op once a connection is in progress or
|
|
3960
|
+
* settled, so a double-invoked mount effect (React StrictMode) collapses to a
|
|
3961
|
+
* single request. See #5801.
|
|
3962
|
+
*/
|
|
3963
|
+
connect() {
|
|
3964
|
+
this.agentRegistry.connectRuntime();
|
|
3965
|
+
}
|
|
2887
3966
|
get runtimeTransport() {
|
|
2888
3967
|
return this.agentRegistry.runtimeTransport;
|
|
2889
3968
|
}
|
|
@@ -2952,6 +4031,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
2952
4031
|
get threadEndpoints() {
|
|
2953
4032
|
return this.agentRegistry.threadEndpoints;
|
|
2954
4033
|
}
|
|
4034
|
+
get suggestions() {
|
|
4035
|
+
return this.agentRegistry.suggestions;
|
|
4036
|
+
}
|
|
2955
4037
|
get a2uiEnabled() {
|
|
2956
4038
|
return this.agentRegistry.a2uiEnabled;
|
|
2957
4039
|
}
|
|
@@ -3005,6 +4087,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
3005
4087
|
*/
|
|
3006
4088
|
setHeaders(headers) {
|
|
3007
4089
|
this._headers = normalizeHeaders(headers);
|
|
4090
|
+
if (this._memoryStore) this.syncMemoryContext();
|
|
3008
4091
|
this.agentRegistry.applyHeadersToAgents(this.agentRegistry.agents);
|
|
3009
4092
|
this.notifySubscribers((subscriber) => {
|
|
3010
4093
|
var _subscriber$onHeaders;
|
|
@@ -3116,6 +4199,47 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
3116
4199
|
return this.threadStoreRegistry.getAll();
|
|
3117
4200
|
}
|
|
3118
4201
|
/**
|
|
4202
|
+
* Returns the single core-owned, user-scoped memory store, creating and
|
|
4203
|
+
* starting it on first access. Unlike thread stores, memory is not scoped per
|
|
4204
|
+
* agent: there is exactly one store whose runtime context the core wires
|
|
4205
|
+
* itself (see `syncMemoryContext`), so consumers (e.g. a `useMemories`
|
|
4206
|
+
* binding) just read this store rather than registering one.
|
|
4207
|
+
*/
|
|
4208
|
+
getMemoryStore() {
|
|
4209
|
+
return this.ensureMemoryStore();
|
|
4210
|
+
}
|
|
4211
|
+
/**
|
|
4212
|
+
* Lazily creates, starts, and context-syncs the core-owned memory store on
|
|
4213
|
+
* first access, then returns it. Subsequent calls return the existing store.
|
|
4214
|
+
* The store is constructed with a bound `globalThis.fetch` and immediately
|
|
4215
|
+
* has its runtime context synced from the current connection state.
|
|
4216
|
+
*/
|
|
4217
|
+
ensureMemoryStore() {
|
|
4218
|
+
if (!this._memoryStore) {
|
|
4219
|
+
this._memoryStore = createMemoryStore({ fetch: globalThis.fetch.bind(globalThis) });
|
|
4220
|
+
this._memoryStore.start();
|
|
4221
|
+
this.syncMemoryContext();
|
|
4222
|
+
}
|
|
4223
|
+
return this._memoryStore;
|
|
4224
|
+
}
|
|
4225
|
+
/**
|
|
4226
|
+
* Pushes the current runtime wiring into the memory store. When the runtime
|
|
4227
|
+
* is connected and both the intelligence WebSocket URL and runtime URL are
|
|
4228
|
+
* available, the store receives a context (runtime URL, WebSocket URL, and a
|
|
4229
|
+
* copy of the current headers); otherwise its context is cleared. No-op when
|
|
4230
|
+
* the store has not been created yet.
|
|
4231
|
+
*/
|
|
4232
|
+
syncMemoryContext() {
|
|
4233
|
+
var _this$intelligence;
|
|
4234
|
+
if (!this._memoryStore) return;
|
|
4235
|
+
if (this.runtimeConnectionStatus === CopilotKitCoreRuntimeConnectionStatus.Connected && ((_this$intelligence = this.intelligence) === null || _this$intelligence === void 0 ? void 0 : _this$intelligence.wsUrl) && this.runtimeUrl) this._memoryStore.setContext({
|
|
4236
|
+
runtimeUrl: this.runtimeUrl,
|
|
4237
|
+
wsUrl: this.intelligence.wsUrl,
|
|
4238
|
+
headers: { ...this.headers }
|
|
4239
|
+
});
|
|
4240
|
+
else this._memoryStore.setContext(null);
|
|
4241
|
+
}
|
|
4242
|
+
/**
|
|
3119
4243
|
* Suggestions management (delegated to SuggestionEngine)
|
|
3120
4244
|
*/
|
|
3121
4245
|
addSuggestionsConfig(config) {
|
|
@@ -3284,507 +4408,248 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
3284
4408
|
};
|
|
3285
4409
|
const subscription = agent.subscribe(wrappedSubscriber);
|
|
3286
4410
|
return { unsubscribe: () => {
|
|
3287
|
-
active = false;
|
|
3288
|
-
throttler.cancel();
|
|
3289
|
-
subscription.unsubscribe();
|
|
3290
|
-
} };
|
|
3291
|
-
}
|
|
3292
|
-
/**
|
|
3293
|
-
* Agent connectivity (delegated to RunHandler)
|
|
3294
|
-
*/
|
|
3295
|
-
async connectAgent(params) {
|
|
3296
|
-
return this.runHandler.connectAgent(params);
|
|
3297
|
-
}
|
|
3298
|
-
stopAgent(params) {
|
|
3299
|
-
this.runHandler.abortCurrentRun();
|
|
3300
|
-
params.agent.abortRun();
|
|
3301
|
-
}
|
|
3302
|
-
async runAgent(params) {
|
|
3303
|
-
return this.runHandler.runAgent(params);
|
|
3304
|
-
}
|
|
3305
|
-
/**
|
|
3306
|
-
* Programmatically execute a registered frontend tool without going through an LLM turn.
|
|
3307
|
-
* The handler runs, render components show up in the UI, and both the tool call and
|
|
3308
|
-
* result messages are added to `agent.messages`.
|
|
3309
|
-
*/
|
|
3310
|
-
async runTool(params) {
|
|
3311
|
-
return this.runHandler.runTool(params);
|
|
3312
|
-
}
|
|
3313
|
-
/**
|
|
3314
|
-
* State management (delegated to StateManager)
|
|
3315
|
-
*/
|
|
3316
|
-
getStateByRun(agentId, threadId, runId) {
|
|
3317
|
-
return this.stateManager.getStateByRun(agentId, threadId, runId);
|
|
3318
|
-
}
|
|
3319
|
-
getRunIdForMessage(agentId, threadId, messageId) {
|
|
3320
|
-
return this.stateManager.getRunIdForMessage(agentId, threadId, messageId);
|
|
3321
|
-
}
|
|
3322
|
-
getRunIdsForThread(agentId, threadId) {
|
|
3323
|
-
return this.stateManager.getRunIdsForThread(agentId, threadId);
|
|
3324
|
-
}
|
|
3325
|
-
/**
|
|
3326
|
-
* Internal method used by RunHandler to build frontend tools
|
|
3327
|
-
*/
|
|
3328
|
-
buildFrontendTools(agentId) {
|
|
3329
|
-
return this.runHandler.buildFrontendTools(agentId);
|
|
3330
|
-
}
|
|
3331
|
-
/**
|
|
3332
|
-
* Called before each follow-up agent run (after tool execution).
|
|
3333
|
-
*
|
|
3334
|
-
* When a frontend tool handler calls framework state setters (e.g. React's
|
|
3335
|
-
* setState), those updates are batched and deferred — they do not take effect
|
|
3336
|
-
* until the framework's scheduler runs (React uses MessageChannel).
|
|
3337
|
-
* useAgentContext registers context via useLayoutEffect, which runs
|
|
3338
|
-
* synchronously after React commits that deferred batch.
|
|
3339
|
-
*
|
|
3340
|
-
* Without yielding here, the follow-up runAgent reads the context store
|
|
3341
|
-
* synchronously while the deferred updates are still pending, producing stale
|
|
3342
|
-
* context for the next agent turn.
|
|
3343
|
-
*
|
|
3344
|
-
* Override in framework-specific subclasses to yield to the framework
|
|
3345
|
-
* scheduler before the follow-up run. The base implementation is a no-op
|
|
3346
|
-
* because non-React environments have no deferred state to flush.
|
|
3347
|
-
*/
|
|
3348
|
-
async waitForPendingFrameworkUpdates() {}
|
|
3349
|
-
};
|
|
3350
|
-
|
|
3351
|
-
//#endregion
|
|
3352
|
-
//#region src/types.ts
|
|
3353
|
-
/**
|
|
3354
|
-
* Status of a tool call execution
|
|
3355
|
-
*/
|
|
3356
|
-
let ToolCallStatus = /* @__PURE__ */ function(ToolCallStatus) {
|
|
3357
|
-
ToolCallStatus["InProgress"] = "inProgress";
|
|
3358
|
-
ToolCallStatus["Executing"] = "executing";
|
|
3359
|
-
ToolCallStatus["Complete"] = "complete";
|
|
3360
|
-
return ToolCallStatus;
|
|
3361
|
-
}({});
|
|
3362
|
-
|
|
3363
|
-
//#endregion
|
|
3364
|
-
//#region src/utils/markdown.ts
|
|
3365
|
-
function completePartialMarkdown(input) {
|
|
3366
|
-
let s = input;
|
|
3367
|
-
const fenceMatches = Array.from(s.matchAll(/^(\s*)(`{3,}|~{3,})/gm));
|
|
3368
|
-
if (fenceMatches.length % 2 === 1) {
|
|
3369
|
-
const [, indent, fence] = fenceMatches[0];
|
|
3370
|
-
s += `\n${indent}${fence}`;
|
|
3371
|
-
}
|
|
3372
|
-
if (s.match(/\[([^\]]*)\]\(([^)]*)$/)) s += ")";
|
|
3373
|
-
const openElements = [];
|
|
3374
|
-
const chars = Array.from(s);
|
|
3375
|
-
const codeBlockRanges = [];
|
|
3376
|
-
const inlineCodeRanges = [];
|
|
3377
|
-
let tempCodeFenceCount = 0;
|
|
3378
|
-
let currentCodeBlockStart = -1;
|
|
3379
|
-
for (let i = 0; i < chars.length; i++) if (i === 0 || chars[i - 1] === "\n") {
|
|
3380
|
-
const lineMatch = s.substring(i).match(/^(\s*)(`{3,}|~{3,})/);
|
|
3381
|
-
if (lineMatch) {
|
|
3382
|
-
tempCodeFenceCount++;
|
|
3383
|
-
if (tempCodeFenceCount % 2 === 1) currentCodeBlockStart = i;
|
|
3384
|
-
else if (currentCodeBlockStart !== -1) {
|
|
3385
|
-
codeBlockRanges.push({
|
|
3386
|
-
start: currentCodeBlockStart,
|
|
3387
|
-
end: i + lineMatch[0].length
|
|
3388
|
-
});
|
|
3389
|
-
currentCodeBlockStart = -1;
|
|
3390
|
-
}
|
|
3391
|
-
i += lineMatch[0].length - 1;
|
|
3392
|
-
}
|
|
3393
|
-
}
|
|
3394
|
-
for (let i = 0; i < chars.length; i++) if (chars[i] === "`") {
|
|
3395
|
-
let backslashCount = 0;
|
|
3396
|
-
for (let j = i - 1; j >= 0 && chars[j] === "\\"; j--) backslashCount++;
|
|
3397
|
-
if (backslashCount % 2 === 0) {
|
|
3398
|
-
for (let j = i + 1; j < chars.length; j++) if (chars[j] === "`") {
|
|
3399
|
-
let closingBackslashCount = 0;
|
|
3400
|
-
for (let k = j - 1; k >= 0 && chars[k] === "\\"; k--) closingBackslashCount++;
|
|
3401
|
-
if (closingBackslashCount % 2 === 0) {
|
|
3402
|
-
inlineCodeRanges.push({
|
|
3403
|
-
start: i,
|
|
3404
|
-
end: j + 1
|
|
3405
|
-
});
|
|
3406
|
-
i = j;
|
|
3407
|
-
break;
|
|
3408
|
-
}
|
|
3409
|
-
}
|
|
3410
|
-
}
|
|
3411
|
-
}
|
|
3412
|
-
const isInCode = (pos) => {
|
|
3413
|
-
return codeBlockRanges.some((range) => pos >= range.start && pos < range.end) || inlineCodeRanges.some((range) => pos >= range.start && pos < range.end);
|
|
3414
|
-
};
|
|
3415
|
-
for (let i = 0; i < chars.length; i++) {
|
|
3416
|
-
const char = chars[i];
|
|
3417
|
-
const nextChar = chars[i + 1];
|
|
3418
|
-
const prevChar = chars[i - 1];
|
|
3419
|
-
if (isInCode(i)) continue;
|
|
3420
|
-
if (char === "[") {
|
|
3421
|
-
let isCompleteLink = false;
|
|
3422
|
-
let bracketDepth = 1;
|
|
3423
|
-
let j = i + 1;
|
|
3424
|
-
while (j < chars.length && bracketDepth > 0) {
|
|
3425
|
-
if (chars[j] === "[" && !isInCode(j)) bracketDepth++;
|
|
3426
|
-
if (chars[j] === "]" && !isInCode(j)) bracketDepth--;
|
|
3427
|
-
j++;
|
|
3428
|
-
}
|
|
3429
|
-
if (bracketDepth === 0 && chars[j] === "(") {
|
|
3430
|
-
let parenDepth = 1;
|
|
3431
|
-
j++;
|
|
3432
|
-
while (j < chars.length && parenDepth > 0) {
|
|
3433
|
-
if (chars[j] === "(" && !isInCode(j)) parenDepth++;
|
|
3434
|
-
if (chars[j] === ")" && !isInCode(j)) parenDepth--;
|
|
3435
|
-
j++;
|
|
3436
|
-
}
|
|
3437
|
-
if (parenDepth === 0) {
|
|
3438
|
-
isCompleteLink = true;
|
|
3439
|
-
i = j - 1;
|
|
3440
|
-
continue;
|
|
3441
|
-
}
|
|
3442
|
-
}
|
|
3443
|
-
if (!isCompleteLink) {
|
|
3444
|
-
const existingIndex = openElements.findIndex((el) => el.type === "bracket");
|
|
3445
|
-
if (existingIndex !== -1) openElements.splice(existingIndex, 1);
|
|
3446
|
-
else openElements.push({
|
|
3447
|
-
type: "bracket",
|
|
3448
|
-
marker: "[",
|
|
3449
|
-
position: i
|
|
3450
|
-
});
|
|
3451
|
-
}
|
|
3452
|
-
} else if (char === "*" && nextChar === "*") {
|
|
3453
|
-
const existingIndex = openElements.findIndex((el) => el.type === "bold_star");
|
|
3454
|
-
if (existingIndex !== -1) openElements.splice(existingIndex, 1);
|
|
3455
|
-
else openElements.push({
|
|
3456
|
-
type: "bold_star",
|
|
3457
|
-
marker: "**",
|
|
3458
|
-
position: i
|
|
3459
|
-
});
|
|
3460
|
-
i++;
|
|
3461
|
-
} else if (char === "_" && nextChar === "_") {
|
|
3462
|
-
const existingIndex = openElements.findIndex((el) => el.type === "bold_underscore");
|
|
3463
|
-
if (existingIndex !== -1) openElements.splice(existingIndex, 1);
|
|
3464
|
-
else openElements.push({
|
|
3465
|
-
type: "bold_underscore",
|
|
3466
|
-
marker: "__",
|
|
3467
|
-
position: i
|
|
3468
|
-
});
|
|
3469
|
-
i++;
|
|
3470
|
-
} else if (char === "~" && nextChar === "~") {
|
|
3471
|
-
const existingIndex = openElements.findIndex((el) => el.type === "strike");
|
|
3472
|
-
if (existingIndex !== -1) openElements.splice(existingIndex, 1);
|
|
3473
|
-
else openElements.push({
|
|
3474
|
-
type: "strike",
|
|
3475
|
-
marker: "~~",
|
|
3476
|
-
position: i
|
|
3477
|
-
});
|
|
3478
|
-
i++;
|
|
3479
|
-
} else if (char === "*" && prevChar !== "*" && nextChar !== "*") {
|
|
3480
|
-
const existingIndex = openElements.findIndex((el) => el.type === "italic_star");
|
|
3481
|
-
if (existingIndex !== -1) openElements.splice(existingIndex, 1);
|
|
3482
|
-
else openElements.push({
|
|
3483
|
-
type: "italic_star",
|
|
3484
|
-
marker: "*",
|
|
3485
|
-
position: i
|
|
3486
|
-
});
|
|
3487
|
-
} else if (char === "_" && prevChar !== "_" && nextChar !== "_") {
|
|
3488
|
-
const existingIndex = openElements.findIndex((el) => el.type === "italic_underscore");
|
|
3489
|
-
if (existingIndex !== -1) openElements.splice(existingIndex, 1);
|
|
3490
|
-
else openElements.push({
|
|
3491
|
-
type: "italic_underscore",
|
|
3492
|
-
marker: "_",
|
|
3493
|
-
position: i
|
|
3494
|
-
});
|
|
3495
|
-
}
|
|
4411
|
+
active = false;
|
|
4412
|
+
throttler.cancel();
|
|
4413
|
+
subscription.unsubscribe();
|
|
4414
|
+
} };
|
|
3496
4415
|
}
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
switch (el.type) {
|
|
3503
|
-
case "bracket": return "]";
|
|
3504
|
-
case "bold_star": return "**";
|
|
3505
|
-
case "bold_underscore": return "__";
|
|
3506
|
-
case "strike": return "~~";
|
|
3507
|
-
case "italic_star": return "*";
|
|
3508
|
-
case "italic_underscore": return "_";
|
|
3509
|
-
default: return "";
|
|
3510
|
-
}
|
|
3511
|
-
});
|
|
3512
|
-
let result = s + closers.join("");
|
|
3513
|
-
const finalFenceMatches = Array.from(result.matchAll(/^(\s*)(`{3,}|~{3,})/gm));
|
|
3514
|
-
const hasUnclosedBacktick = (result.match(/`/g) || []).length % 2 === 1;
|
|
3515
|
-
const hasUnclosedCodeFence = finalFenceMatches.length % 2 === 1;
|
|
3516
|
-
let shouldCloseParens = !hasUnclosedBacktick && !hasUnclosedCodeFence;
|
|
3517
|
-
if (shouldCloseParens) {
|
|
3518
|
-
const lastOpenParen = result.lastIndexOf("(");
|
|
3519
|
-
if (lastOpenParen !== -1) {
|
|
3520
|
-
if ((result.substring(0, lastOpenParen).match(/`/g) || []).length % 2 === 1) shouldCloseParens = false;
|
|
3521
|
-
}
|
|
4416
|
+
/**
|
|
4417
|
+
* Agent connectivity (delegated to RunHandler)
|
|
4418
|
+
*/
|
|
4419
|
+
async connectAgent(params) {
|
|
4420
|
+
return this.runHandler.connectAgent(params);
|
|
3522
4421
|
}
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
if (openParens > closeParens) result += ")".repeat(openParens - closeParens);
|
|
4422
|
+
stopAgent(params) {
|
|
4423
|
+
this.runHandler.abortCurrentRun();
|
|
4424
|
+
params.agent.abortRun();
|
|
3527
4425
|
}
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
//#endregion
|
|
3532
|
-
//#region src/utils/micro-redux.ts
|
|
3533
|
-
const INTERNAL_ACTION_TYPES = {
|
|
3534
|
-
boot: "@@micro-redux/boot",
|
|
3535
|
-
init: "@@micro-redux/init",
|
|
3536
|
-
stop: "@@micro-redux/stop"
|
|
3537
|
-
};
|
|
3538
|
-
const INTERNAL_BOOT_ACTION = { type: INTERNAL_ACTION_TYPES.boot };
|
|
3539
|
-
/**
|
|
3540
|
-
* Builds a typed action creator from a type string and payload factory.
|
|
3541
|
-
*/
|
|
3542
|
-
function createTypedActionCreator(type, factory) {
|
|
3543
|
-
const creator = ((...args) => ({
|
|
3544
|
-
...factory(...args),
|
|
3545
|
-
type
|
|
3546
|
-
}));
|
|
3547
|
-
creator.type = type;
|
|
3548
|
-
creator.match = (action) => action.type === type;
|
|
3549
|
-
return creator;
|
|
3550
|
-
}
|
|
3551
|
-
/**
|
|
3552
|
-
* Declares a payload-based action config for `createActionGroup`.
|
|
3553
|
-
*
|
|
3554
|
-
* @example
|
|
3555
|
-
* ```ts
|
|
3556
|
-
* const actions = createActionGroup("User", {
|
|
3557
|
-
* loaded: props<{ id: string }>(),
|
|
3558
|
-
* });
|
|
3559
|
-
* ```
|
|
3560
|
-
*/
|
|
3561
|
-
function props() {
|
|
3562
|
-
return { kind: "props" };
|
|
3563
|
-
}
|
|
3564
|
-
/**
|
|
3565
|
-
* Declares a no-payload action config for `createActionGroup`.
|
|
3566
|
-
*
|
|
3567
|
-
* @example
|
|
3568
|
-
* ```ts
|
|
3569
|
-
* const actions = createActionGroup("User", {
|
|
3570
|
-
* reset: empty(),
|
|
3571
|
-
* });
|
|
3572
|
-
* ```
|
|
3573
|
-
*/
|
|
3574
|
-
function empty() {
|
|
3575
|
-
return { kind: "empty" };
|
|
3576
|
-
}
|
|
3577
|
-
/**
|
|
3578
|
-
* Creates a namespaced group of typed action creators.
|
|
3579
|
-
*
|
|
3580
|
-
* Action types are formatted as: `[Source] actionName`.
|
|
3581
|
-
*/
|
|
3582
|
-
function createActionGroup(source, config) {
|
|
3583
|
-
const group = {};
|
|
3584
|
-
for (const eventName of Object.keys(config)) {
|
|
3585
|
-
const eventConfig = config[eventName];
|
|
3586
|
-
if (!eventConfig) continue;
|
|
3587
|
-
const actionType = `[${source}] ${eventName}`;
|
|
3588
|
-
if (eventConfig.kind === "props") {
|
|
3589
|
-
group[eventName] = createTypedActionCreator(actionType, (payload) => ({ ...payload }));
|
|
3590
|
-
continue;
|
|
3591
|
-
}
|
|
3592
|
-
group[eventName] = createTypedActionCreator(actionType, () => ({}));
|
|
4426
|
+
async runAgent(params) {
|
|
4427
|
+
return this.runHandler.runAgent(params);
|
|
3593
4428
|
}
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
function on(...args) {
|
|
3602
|
-
if (args.length < 2) throw new Error("on requires at least one action creator and one reducer");
|
|
3603
|
-
const reducer = args[args.length - 1];
|
|
3604
|
-
return {
|
|
3605
|
-
creators: args.slice(0, -1),
|
|
3606
|
-
reducer
|
|
3607
|
-
};
|
|
3608
|
-
}
|
|
3609
|
-
/**
|
|
3610
|
-
* Creates a reducer from an initial state and `on(...)` handler entries.
|
|
3611
|
-
*
|
|
3612
|
-
* Unknown action types return the current state unchanged.
|
|
3613
|
-
*/
|
|
3614
|
-
function createReducer(initialState, ...entries) {
|
|
3615
|
-
const reducerMap = /* @__PURE__ */ new Map();
|
|
3616
|
-
for (const entry of entries) for (const creator of entry.creators) {
|
|
3617
|
-
var _reducerMap$get;
|
|
3618
|
-
const handlers = (_reducerMap$get = reducerMap.get(creator.type)) !== null && _reducerMap$get !== void 0 ? _reducerMap$get : [];
|
|
3619
|
-
handlers.push(entry.reducer);
|
|
3620
|
-
reducerMap.set(creator.type, handlers);
|
|
4429
|
+
/**
|
|
4430
|
+
* Programmatically execute a registered frontend tool without going through an LLM turn.
|
|
4431
|
+
* The handler runs, render components show up in the UI, and both the tool call and
|
|
4432
|
+
* result messages are added to `agent.messages`.
|
|
4433
|
+
*/
|
|
4434
|
+
async runTool(params) {
|
|
4435
|
+
return this.runHandler.runTool(params);
|
|
3621
4436
|
}
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
for (const handler of handlers) nextState = handler(nextState, action);
|
|
3628
|
-
return nextState;
|
|
3629
|
-
};
|
|
3630
|
-
}
|
|
3631
|
-
/**
|
|
3632
|
-
* Creates a selector that caches and reuses the last computed result
|
|
3633
|
-
* when all input references are unchanged.
|
|
3634
|
-
*/
|
|
3635
|
-
function createSelector(...args) {
|
|
3636
|
-
if (args.length === 1) {
|
|
3637
|
-
const projector = args[0];
|
|
3638
|
-
let hasCached = false;
|
|
3639
|
-
let lastState;
|
|
3640
|
-
let lastResult;
|
|
3641
|
-
return (state) => {
|
|
3642
|
-
if (hasCached && state === lastState) return lastResult;
|
|
3643
|
-
lastState = state;
|
|
3644
|
-
lastResult = projector(state);
|
|
3645
|
-
hasCached = true;
|
|
3646
|
-
return lastResult;
|
|
3647
|
-
};
|
|
4437
|
+
/**
|
|
4438
|
+
* State management (delegated to StateManager)
|
|
4439
|
+
*/
|
|
4440
|
+
getStateByRun(agentId, threadId, runId) {
|
|
4441
|
+
return this.stateManager.getStateByRun(agentId, threadId, runId);
|
|
3648
4442
|
}
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
/**
|
|
3686
|
-
* Creates an effect descriptor consumed by `createStore`.
|
|
3687
|
-
*/
|
|
3688
|
-
function createEffect(factory, options = {}) {
|
|
3689
|
-
if (options.dispatch === false) return {
|
|
3690
|
-
run: factory,
|
|
3691
|
-
dispatch: false
|
|
3692
|
-
};
|
|
3693
|
-
return {
|
|
3694
|
-
run: factory,
|
|
3695
|
-
dispatch: true
|
|
3696
|
-
};
|
|
3697
|
-
}
|
|
3698
|
-
/**
|
|
3699
|
-
* Creates a small observable store with reducer + effects.
|
|
3700
|
-
*
|
|
3701
|
-
* Behavior:
|
|
3702
|
-
* - `init()` starts effects and dispatches `@@micro-redux/init`.
|
|
3703
|
-
* - `stop()` dispatches `@@micro-redux/stop` and unsubscribes all effects.
|
|
3704
|
-
* - Effect action observation is scheduled on `asapScheduler` to avoid
|
|
3705
|
-
* synchronous re-entrancy in the effect loop.
|
|
3706
|
-
* - Any effect error triggers fail-fast teardown and errors both `actions$`
|
|
3707
|
-
* and `state$`.
|
|
4443
|
+
getRunIdForMessage(agentId, threadId, messageId) {
|
|
4444
|
+
return this.stateManager.getRunIdForMessage(agentId, threadId, messageId);
|
|
4445
|
+
}
|
|
4446
|
+
getRunIdsForThread(agentId, threadId) {
|
|
4447
|
+
return this.stateManager.getRunIdsForThread(agentId, threadId);
|
|
4448
|
+
}
|
|
4449
|
+
/**
|
|
4450
|
+
* Internal method used by RunHandler to build frontend tools
|
|
4451
|
+
*/
|
|
4452
|
+
buildFrontendTools(agentId) {
|
|
4453
|
+
return this.runHandler.buildFrontendTools(agentId);
|
|
4454
|
+
}
|
|
4455
|
+
/**
|
|
4456
|
+
* Called before each follow-up agent run (after tool execution).
|
|
4457
|
+
*
|
|
4458
|
+
* When a frontend tool handler calls framework state setters (e.g. React's
|
|
4459
|
+
* setState), those updates are batched and deferred — they do not take effect
|
|
4460
|
+
* until the framework's scheduler runs (React uses MessageChannel).
|
|
4461
|
+
* useAgentContext registers context via useLayoutEffect, which runs
|
|
4462
|
+
* synchronously after React commits that deferred batch.
|
|
4463
|
+
*
|
|
4464
|
+
* Without yielding here, the follow-up runAgent reads the context store
|
|
4465
|
+
* synchronously while the deferred updates are still pending, producing stale
|
|
4466
|
+
* context for the next agent turn.
|
|
4467
|
+
*
|
|
4468
|
+
* Override in framework-specific subclasses to yield to the framework
|
|
4469
|
+
* scheduler before the follow-up run. The base implementation is a no-op
|
|
4470
|
+
* because non-React environments have no deferred state to flush.
|
|
4471
|
+
*/
|
|
4472
|
+
async waitForPendingFrameworkUpdates() {}
|
|
4473
|
+
};
|
|
4474
|
+
|
|
4475
|
+
//#endregion
|
|
4476
|
+
//#region src/types.ts
|
|
4477
|
+
/**
|
|
4478
|
+
* Status of a tool call execution
|
|
3708
4479
|
*/
|
|
3709
|
-
function
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
}
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
if (hasFatalError) return;
|
|
3742
|
-
dispatchInternal(effectAction);
|
|
3743
|
-
},
|
|
3744
|
-
error: (error) => {
|
|
3745
|
-
failFast(error);
|
|
3746
|
-
}
|
|
4480
|
+
let ToolCallStatus = /* @__PURE__ */ function(ToolCallStatus) {
|
|
4481
|
+
ToolCallStatus["InProgress"] = "inProgress";
|
|
4482
|
+
ToolCallStatus["Executing"] = "executing";
|
|
4483
|
+
ToolCallStatus["Complete"] = "complete";
|
|
4484
|
+
return ToolCallStatus;
|
|
4485
|
+
}({});
|
|
4486
|
+
|
|
4487
|
+
//#endregion
|
|
4488
|
+
//#region src/utils/markdown.ts
|
|
4489
|
+
function completePartialMarkdown(input) {
|
|
4490
|
+
let s = input;
|
|
4491
|
+
const fenceMatches = Array.from(s.matchAll(/^(\s*)(`{3,}|~{3,})/gm));
|
|
4492
|
+
if (fenceMatches.length % 2 === 1) {
|
|
4493
|
+
const [, indent, fence] = fenceMatches[0];
|
|
4494
|
+
s += `\n${indent}${fence}`;
|
|
4495
|
+
}
|
|
4496
|
+
if (s.match(/\[([^\]]*)\]\(([^)]*)$/)) s += ")";
|
|
4497
|
+
const openElements = [];
|
|
4498
|
+
const chars = Array.from(s);
|
|
4499
|
+
const codeBlockRanges = [];
|
|
4500
|
+
const inlineCodeRanges = [];
|
|
4501
|
+
let tempCodeFenceCount = 0;
|
|
4502
|
+
let currentCodeBlockStart = -1;
|
|
4503
|
+
for (let i = 0; i < chars.length; i++) if (i === 0 || chars[i - 1] === "\n") {
|
|
4504
|
+
const lineMatch = s.substring(i).match(/^(\s*)(`{3,}|~{3,})/);
|
|
4505
|
+
if (lineMatch) {
|
|
4506
|
+
tempCodeFenceCount++;
|
|
4507
|
+
if (tempCodeFenceCount % 2 === 1) currentCodeBlockStart = i;
|
|
4508
|
+
else if (currentCodeBlockStart !== -1) {
|
|
4509
|
+
codeBlockRanges.push({
|
|
4510
|
+
start: currentCodeBlockStart,
|
|
4511
|
+
end: i + lineMatch[0].length
|
|
3747
4512
|
});
|
|
3748
|
-
|
|
3749
|
-
continue;
|
|
4513
|
+
currentCodeBlockStart = -1;
|
|
3750
4514
|
}
|
|
3751
|
-
|
|
3752
|
-
failFast(error);
|
|
3753
|
-
} });
|
|
3754
|
-
effectSubscriptions.add(subscription);
|
|
4515
|
+
i += lineMatch[0].length - 1;
|
|
3755
4516
|
}
|
|
3756
|
-
}
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
init() {
|
|
3774
|
-
if (hasFatalError || isRunning) return;
|
|
3775
|
-
isRunning = true;
|
|
3776
|
-
startEffects();
|
|
3777
|
-
if (hasFatalError) return;
|
|
3778
|
-
dispatchInternal({ type: INTERNAL_ACTION_TYPES.init });
|
|
3779
|
-
},
|
|
3780
|
-
stop() {
|
|
3781
|
-
if (hasFatalError || !isRunning) return;
|
|
3782
|
-
dispatchInternal({ type: INTERNAL_ACTION_TYPES.stop });
|
|
3783
|
-
effectSubscriptions.unsubscribe();
|
|
3784
|
-
effectSubscriptions = new rxjs.Subscription();
|
|
3785
|
-
isRunning = false;
|
|
4517
|
+
}
|
|
4518
|
+
for (let i = 0; i < chars.length; i++) if (chars[i] === "`") {
|
|
4519
|
+
let backslashCount = 0;
|
|
4520
|
+
for (let j = i - 1; j >= 0 && chars[j] === "\\"; j--) backslashCount++;
|
|
4521
|
+
if (backslashCount % 2 === 0) {
|
|
4522
|
+
for (let j = i + 1; j < chars.length; j++) if (chars[j] === "`") {
|
|
4523
|
+
let closingBackslashCount = 0;
|
|
4524
|
+
for (let k = j - 1; k >= 0 && chars[k] === "\\"; k--) closingBackslashCount++;
|
|
4525
|
+
if (closingBackslashCount % 2 === 0) {
|
|
4526
|
+
inlineCodeRanges.push({
|
|
4527
|
+
start: i,
|
|
4528
|
+
end: j + 1
|
|
4529
|
+
});
|
|
4530
|
+
i = j;
|
|
4531
|
+
break;
|
|
4532
|
+
}
|
|
4533
|
+
}
|
|
3786
4534
|
}
|
|
4535
|
+
}
|
|
4536
|
+
const isInCode = (pos) => {
|
|
4537
|
+
return codeBlockRanges.some((range) => pos >= range.start && pos < range.end) || inlineCodeRanges.some((range) => pos >= range.start && pos < range.end);
|
|
3787
4538
|
};
|
|
4539
|
+
for (let i = 0; i < chars.length; i++) {
|
|
4540
|
+
const char = chars[i];
|
|
4541
|
+
const nextChar = chars[i + 1];
|
|
4542
|
+
const prevChar = chars[i - 1];
|
|
4543
|
+
if (isInCode(i)) continue;
|
|
4544
|
+
if (char === "[") {
|
|
4545
|
+
let isCompleteLink = false;
|
|
4546
|
+
let bracketDepth = 1;
|
|
4547
|
+
let j = i + 1;
|
|
4548
|
+
while (j < chars.length && bracketDepth > 0) {
|
|
4549
|
+
if (chars[j] === "[" && !isInCode(j)) bracketDepth++;
|
|
4550
|
+
if (chars[j] === "]" && !isInCode(j)) bracketDepth--;
|
|
4551
|
+
j++;
|
|
4552
|
+
}
|
|
4553
|
+
if (bracketDepth === 0 && chars[j] === "(") {
|
|
4554
|
+
let parenDepth = 1;
|
|
4555
|
+
j++;
|
|
4556
|
+
while (j < chars.length && parenDepth > 0) {
|
|
4557
|
+
if (chars[j] === "(" && !isInCode(j)) parenDepth++;
|
|
4558
|
+
if (chars[j] === ")" && !isInCode(j)) parenDepth--;
|
|
4559
|
+
j++;
|
|
4560
|
+
}
|
|
4561
|
+
if (parenDepth === 0) {
|
|
4562
|
+
isCompleteLink = true;
|
|
4563
|
+
i = j - 1;
|
|
4564
|
+
continue;
|
|
4565
|
+
}
|
|
4566
|
+
}
|
|
4567
|
+
if (!isCompleteLink) {
|
|
4568
|
+
const existingIndex = openElements.findIndex((el) => el.type === "bracket");
|
|
4569
|
+
if (existingIndex !== -1) openElements.splice(existingIndex, 1);
|
|
4570
|
+
else openElements.push({
|
|
4571
|
+
type: "bracket",
|
|
4572
|
+
marker: "[",
|
|
4573
|
+
position: i
|
|
4574
|
+
});
|
|
4575
|
+
}
|
|
4576
|
+
} else if (char === "*" && nextChar === "*") {
|
|
4577
|
+
const existingIndex = openElements.findIndex((el) => el.type === "bold_star");
|
|
4578
|
+
if (existingIndex !== -1) openElements.splice(existingIndex, 1);
|
|
4579
|
+
else openElements.push({
|
|
4580
|
+
type: "bold_star",
|
|
4581
|
+
marker: "**",
|
|
4582
|
+
position: i
|
|
4583
|
+
});
|
|
4584
|
+
i++;
|
|
4585
|
+
} else if (char === "_" && nextChar === "_") {
|
|
4586
|
+
const existingIndex = openElements.findIndex((el) => el.type === "bold_underscore");
|
|
4587
|
+
if (existingIndex !== -1) openElements.splice(existingIndex, 1);
|
|
4588
|
+
else openElements.push({
|
|
4589
|
+
type: "bold_underscore",
|
|
4590
|
+
marker: "__",
|
|
4591
|
+
position: i
|
|
4592
|
+
});
|
|
4593
|
+
i++;
|
|
4594
|
+
} else if (char === "~" && nextChar === "~") {
|
|
4595
|
+
const existingIndex = openElements.findIndex((el) => el.type === "strike");
|
|
4596
|
+
if (existingIndex !== -1) openElements.splice(existingIndex, 1);
|
|
4597
|
+
else openElements.push({
|
|
4598
|
+
type: "strike",
|
|
4599
|
+
marker: "~~",
|
|
4600
|
+
position: i
|
|
4601
|
+
});
|
|
4602
|
+
i++;
|
|
4603
|
+
} else if (char === "*" && prevChar !== "*" && nextChar !== "*") {
|
|
4604
|
+
const existingIndex = openElements.findIndex((el) => el.type === "italic_star");
|
|
4605
|
+
if (existingIndex !== -1) openElements.splice(existingIndex, 1);
|
|
4606
|
+
else openElements.push({
|
|
4607
|
+
type: "italic_star",
|
|
4608
|
+
marker: "*",
|
|
4609
|
+
position: i
|
|
4610
|
+
});
|
|
4611
|
+
} else if (char === "_" && prevChar !== "_" && nextChar !== "_") {
|
|
4612
|
+
const existingIndex = openElements.findIndex((el) => el.type === "italic_underscore");
|
|
4613
|
+
if (existingIndex !== -1) openElements.splice(existingIndex, 1);
|
|
4614
|
+
else openElements.push({
|
|
4615
|
+
type: "italic_underscore",
|
|
4616
|
+
marker: "_",
|
|
4617
|
+
position: i
|
|
4618
|
+
});
|
|
4619
|
+
}
|
|
4620
|
+
}
|
|
4621
|
+
let backtickCount = 0;
|
|
4622
|
+
for (let i = 0; i < chars.length; i++) if (chars[i] === "`" && !isInCode(i)) backtickCount++;
|
|
4623
|
+
if (backtickCount % 2 === 1) s += "`";
|
|
4624
|
+
openElements.sort((a, b) => b.position - a.position);
|
|
4625
|
+
const closers = openElements.map((el) => {
|
|
4626
|
+
switch (el.type) {
|
|
4627
|
+
case "bracket": return "]";
|
|
4628
|
+
case "bold_star": return "**";
|
|
4629
|
+
case "bold_underscore": return "__";
|
|
4630
|
+
case "strike": return "~~";
|
|
4631
|
+
case "italic_star": return "*";
|
|
4632
|
+
case "italic_underscore": return "_";
|
|
4633
|
+
default: return "";
|
|
4634
|
+
}
|
|
4635
|
+
});
|
|
4636
|
+
let result = s + closers.join("");
|
|
4637
|
+
const finalFenceMatches = Array.from(result.matchAll(/^(\s*)(`{3,}|~{3,})/gm));
|
|
4638
|
+
const hasUnclosedBacktick = (result.match(/`/g) || []).length % 2 === 1;
|
|
4639
|
+
const hasUnclosedCodeFence = finalFenceMatches.length % 2 === 1;
|
|
4640
|
+
let shouldCloseParens = !hasUnclosedBacktick && !hasUnclosedCodeFence;
|
|
4641
|
+
if (shouldCloseParens) {
|
|
4642
|
+
const lastOpenParen = result.lastIndexOf("(");
|
|
4643
|
+
if (lastOpenParen !== -1) {
|
|
4644
|
+
if ((result.substring(0, lastOpenParen).match(/`/g) || []).length % 2 === 1) shouldCloseParens = false;
|
|
4645
|
+
}
|
|
4646
|
+
}
|
|
4647
|
+
if (shouldCloseParens) {
|
|
4648
|
+
const openParens = (result.match(/\(/g) || []).length;
|
|
4649
|
+
const closeParens = (result.match(/\)/g) || []).length;
|
|
4650
|
+
if (openParens > closeParens) result += ")".repeat(openParens - closeParens);
|
|
4651
|
+
}
|
|
4652
|
+
return result;
|
|
3788
4653
|
}
|
|
3789
4654
|
|
|
3790
4655
|
//#endregion
|
|
@@ -3799,6 +4664,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
3799
4664
|
isLoading: false,
|
|
3800
4665
|
isFetchingNextPage: false,
|
|
3801
4666
|
error: null,
|
|
4667
|
+
fetchMoreError: null,
|
|
3802
4668
|
context: null,
|
|
3803
4669
|
sessionId: 0,
|
|
3804
4670
|
metadataCredentialsRequested: false,
|
|
@@ -3886,6 +4752,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
3886
4752
|
isLoading: Boolean(context),
|
|
3887
4753
|
isFetchingNextPage: false,
|
|
3888
4754
|
error: null,
|
|
4755
|
+
fetchMoreError: null,
|
|
3889
4756
|
metadataCredentialsRequested: false,
|
|
3890
4757
|
metadataJoinCode: null,
|
|
3891
4758
|
nextCursor: null,
|
|
@@ -3897,6 +4764,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
3897
4764
|
isLoading: false,
|
|
3898
4765
|
isFetchingNextPage: false,
|
|
3899
4766
|
error: null,
|
|
4767
|
+
fetchMoreError: null,
|
|
3900
4768
|
metadataCredentialsRequested: false,
|
|
3901
4769
|
metadataJoinCode: null,
|
|
3902
4770
|
nextCursor: null,
|
|
@@ -3907,7 +4775,8 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
3907
4775
|
return {
|
|
3908
4776
|
...state,
|
|
3909
4777
|
isLoading: true,
|
|
3910
|
-
error: null
|
|
4778
|
+
error: null,
|
|
4779
|
+
fetchMoreError: null
|
|
3911
4780
|
};
|
|
3912
4781
|
}), on(threadRestEvents.listSucceeded, (state, { sessionId, threads, joinCode, nextCursor }) => {
|
|
3913
4782
|
if (sessionId !== state.sessionId) return state;
|
|
@@ -3917,6 +4786,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
3917
4786
|
threads: sortThreadsByRecency(threads),
|
|
3918
4787
|
isLoading: false,
|
|
3919
4788
|
error: null,
|
|
4789
|
+
fetchMoreError: null,
|
|
3920
4790
|
metadataJoinCode: joinCode,
|
|
3921
4791
|
metadataCredentialsRequested: joinCodeChanged ? false : state.metadataCredentialsRequested,
|
|
3922
4792
|
nextCursor
|
|
@@ -3936,6 +4806,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
3936
4806
|
...state,
|
|
3937
4807
|
threads: merged,
|
|
3938
4808
|
isFetchingNextPage: false,
|
|
4809
|
+
fetchMoreError: null,
|
|
3939
4810
|
nextCursor
|
|
3940
4811
|
};
|
|
3941
4812
|
}), on(threadRestEvents.nextPageFailed, (state, { sessionId, error }) => {
|
|
@@ -3943,7 +4814,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
3943
4814
|
return {
|
|
3944
4815
|
...state,
|
|
3945
4816
|
isFetchingNextPage: false,
|
|
3946
|
-
error
|
|
4817
|
+
fetchMoreError: error
|
|
3947
4818
|
};
|
|
3948
4819
|
}), on(threadRestEvents.metadataCredentialsFailed, (state, { sessionId }) => {
|
|
3949
4820
|
if (sessionId !== state.sessionId) return state;
|
|
@@ -3961,7 +4832,8 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
3961
4832
|
if (!state.nextCursor || state.isFetchingNextPage) return state;
|
|
3962
4833
|
return {
|
|
3963
4834
|
...state,
|
|
3964
|
-
isFetchingNextPage: true
|
|
4835
|
+
isFetchingNextPage: true,
|
|
4836
|
+
fetchMoreError: null
|
|
3965
4837
|
};
|
|
3966
4838
|
}), on(threadAdapterEvents.renameRequested, (state, { threadId, name }) => {
|
|
3967
4839
|
const existing = state.threads.find((thread) => thread.id === threadId);
|
|
@@ -4091,6 +4963,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
4091
4963
|
threads: createSelector((state) => state.threads),
|
|
4092
4964
|
isLoading: createSelector((state) => state.isLoading),
|
|
4093
4965
|
error: createSelector((state) => state.error),
|
|
4966
|
+
fetchMoreError: createSelector((state) => state.fetchMoreError),
|
|
4094
4967
|
hasNextPage: createSelector((state) => state.nextCursor != null),
|
|
4095
4968
|
isFetchingNextPage: createSelector((state) => state.isFetchingNextPage),
|
|
4096
4969
|
isMutating: createSelector((state) => state.inFlightMutationCount > 0)
|
|
@@ -4100,6 +4973,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
4100
4973
|
const selectThreads = standaloneSelectors.threads;
|
|
4101
4974
|
const selectThreadsIsLoading = standaloneSelectors.isLoading;
|
|
4102
4975
|
const selectThreadsError = standaloneSelectors.error;
|
|
4976
|
+
const selectFetchMoreError = standaloneSelectors.fetchMoreError;
|
|
4103
4977
|
const selectHasNextPage = standaloneSelectors.hasNextPage;
|
|
4104
4978
|
const selectIsFetchingNextPage = standaloneSelectors.isFetchingNextPage;
|
|
4105
4979
|
const selectIsMutating = standaloneSelectors.isMutating;
|
|
@@ -4485,6 +5359,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
4485
5359
|
const ɵselectThreads = selectThreads;
|
|
4486
5360
|
const ɵselectThreadsIsLoading = selectThreadsIsLoading;
|
|
4487
5361
|
const ɵselectThreadsError = selectThreadsError;
|
|
5362
|
+
const ɵselectFetchMoreError = selectFetchMoreError;
|
|
4488
5363
|
const ɵselectHasNextPage = selectHasNextPage;
|
|
4489
5364
|
const ɵselectIsFetchingNextPage = selectIsFetchingNextPage;
|
|
4490
5365
|
const ɵselectIsMutating = selectIsMutating;
|
|
@@ -4549,6 +5424,8 @@ exports.CopilotKitCore = CopilotKitCore;
|
|
|
4549
5424
|
exports.CopilotKitCoreErrorCode = CopilotKitCoreErrorCode;
|
|
4550
5425
|
exports.CopilotKitCoreRuntimeConnectionStatus = CopilotKitCoreRuntimeConnectionStatus;
|
|
4551
5426
|
exports.IntelligenceAgent = IntelligenceAgent;
|
|
5427
|
+
exports.MEMORY_ERROR_REGISTRY = MEMORY_ERROR_REGISTRY;
|
|
5428
|
+
exports.MemoryError = MemoryError;
|
|
4552
5429
|
exports.ProxiedCopilotRuntimeAgent = ProxiedCopilotRuntimeAgent;
|
|
4553
5430
|
exports.RunHandler = RunHandler;
|
|
4554
5431
|
exports.StateManager = StateManager;
|
|
@@ -4562,6 +5439,7 @@ exports.createSelector = createSelector;
|
|
|
4562
5439
|
exports.createStore = createStore;
|
|
4563
5440
|
exports.empty = empty;
|
|
4564
5441
|
exports.ensureObjectArgs = ensureObjectArgs;
|
|
5442
|
+
exports.isAbortError = isAbortError;
|
|
4565
5443
|
exports.isRunCompletionAware = isRunCompletionAware;
|
|
4566
5444
|
exports.ofType = ofType;
|
|
4567
5445
|
exports.on = on;
|
|
@@ -4570,19 +5448,33 @@ exports.props = props;
|
|
|
4570
5448
|
exports.select = select;
|
|
4571
5449
|
exports.ɵCOPILOTKIT_FEATURES = ɵCOPILOTKIT_FEATURES;
|
|
4572
5450
|
exports.ɵMAX_SOCKET_RETRIES = ɵMAX_SOCKET_RETRIES;
|
|
5451
|
+
exports.ɵcreateMemoryStore = createMemoryStore;
|
|
4573
5452
|
exports.ɵcreateThreadSelectors = ɵcreateThreadSelectors;
|
|
4574
5453
|
exports.ɵcreateThreadStore = createThreadStore;
|
|
4575
5454
|
exports.ɵisCopilotKitFeature = ɵisCopilotKitFeature;
|
|
5455
|
+
exports.ɵisRetryableMemoryStatus = isRetryableStatus;
|
|
4576
5456
|
exports.ɵjoinPhoenixChannel$ = ɵjoinPhoenixChannel$;
|
|
5457
|
+
exports.ɵmapMemoryMetadataEvent = ɵmapMemoryMetadataEvent;
|
|
5458
|
+
exports.ɵmemoryAdapterEvents = ɵmemoryAdapterEvents;
|
|
5459
|
+
exports.ɵmemoryDomainEvents = ɵmemoryDomainEvents;
|
|
5460
|
+
exports.ɵmemoryReducer = ɵmemoryReducer;
|
|
5461
|
+
exports.ɵmemoryRestEvents = ɵmemoryRestEvents;
|
|
4577
5462
|
exports.ɵobservePhoenixEvent$ = ɵobservePhoenixEvent$;
|
|
4578
5463
|
exports.ɵobservePhoenixJoinOutcome$ = ɵobservePhoenixJoinOutcome$;
|
|
4579
5464
|
exports.ɵobservePhoenixSocketHealth$ = ɵobservePhoenixSocketHealth$;
|
|
4580
5465
|
exports.ɵobservePhoenixSocketSignals$ = ɵobservePhoenixSocketSignals$;
|
|
4581
5466
|
exports.ɵphoenixChannel$ = ɵphoenixChannel$;
|
|
4582
5467
|
exports.ɵphoenixSocket$ = ɵphoenixSocket$;
|
|
5468
|
+
exports.ɵselectFetchMoreError = ɵselectFetchMoreError;
|
|
4583
5469
|
exports.ɵselectHasNextPage = ɵselectHasNextPage;
|
|
4584
5470
|
exports.ɵselectIsFetchingNextPage = ɵselectIsFetchingNextPage;
|
|
4585
5471
|
exports.ɵselectIsMutating = ɵselectIsMutating;
|
|
5472
|
+
exports.ɵselectMemories = ɵselectMemories;
|
|
5473
|
+
exports.ɵselectMemoriesAvailable = ɵselectMemoriesAvailable;
|
|
5474
|
+
exports.ɵselectMemoriesError = ɵselectMemoriesError;
|
|
5475
|
+
exports.ɵselectMemoriesIsLoading = ɵselectMemoriesIsLoading;
|
|
5476
|
+
exports.ɵselectMemoriesIsMutating = ɵselectMemoriesIsMutating;
|
|
5477
|
+
exports.ɵselectMemoriesRealtimeStatus = ɵselectMemoriesRealtimeStatus;
|
|
4586
5478
|
exports.ɵselectThreads = ɵselectThreads;
|
|
4587
5479
|
exports.ɵselectThreadsError = ɵselectThreadsError;
|
|
4588
5480
|
exports.ɵselectThreadsIsLoading = ɵselectThreadsIsLoading;
|