@copilotkit/core 1.62.1 → 1.62.2-canary.1784333495
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 +1766 -729
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +525 -4
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +525 -4
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1758 -738
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +1767 -727
- package/dist/index.umd.js.map +1 -1
- package/package.json +3 -3
package/dist/index.umd.js
CHANGED
|
@@ -170,6 +170,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
170
170
|
const REPLAY_COMPLETE_EVENT = "replay_complete";
|
|
171
171
|
const STREAM_IDLE_EVENT = "stream_idle";
|
|
172
172
|
const STOP_RUN_EVENT = "stop_run";
|
|
173
|
+
const CONNECT_STREAM_IDLE_REPLAY_FALLBACK_MS = 100;
|
|
173
174
|
var AgentThreadLockedError = class extends Error {
|
|
174
175
|
constructor(threadId) {
|
|
175
176
|
super(threadId ? `Thread ${threadId} is locked` : "Thread is locked");
|
|
@@ -320,12 +321,14 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
320
321
|
connect(input) {
|
|
321
322
|
this.threadId = input.threadId;
|
|
322
323
|
this.canonicalRunId = null;
|
|
323
|
-
|
|
324
|
+
const replayCursor = this.getReconnectCursor(input);
|
|
325
|
+
return (0, rxjs.defer)(() => this.requestJoinCredentials$("connect", input, replayCursor)).pipe((0, rxjs.switchMap)((credentials) => {
|
|
324
326
|
if (credentials === null) return rxjs.EMPTY;
|
|
325
327
|
const canonicalInput = this.applyCanonicalRunIdentity(input, credentials, { fallbackToInputRunId: false });
|
|
326
328
|
return this.observeThread$(canonicalInput, credentials, {
|
|
327
329
|
completeOnRunError: false,
|
|
328
|
-
streamMode: "connect"
|
|
330
|
+
streamMode: "connect",
|
|
331
|
+
replayCursor
|
|
329
332
|
});
|
|
330
333
|
}));
|
|
331
334
|
}
|
|
@@ -348,7 +351,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
348
351
|
cleanup() {
|
|
349
352
|
this.cleanupOwned(this.activeChannel, this.socket);
|
|
350
353
|
}
|
|
351
|
-
requestJoinCredentials$(mode, input) {
|
|
354
|
+
requestJoinCredentials$(mode, input, replayCursor) {
|
|
352
355
|
return (0, rxjs.defer)(async () => {
|
|
353
356
|
try {
|
|
354
357
|
const response = await fetch(this.buildRuntimeUrl(mode), {
|
|
@@ -365,7 +368,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
365
368
|
context: input.context,
|
|
366
369
|
state: input.state,
|
|
367
370
|
forwardedProps: input.forwardedProps,
|
|
368
|
-
...mode === "connect" ? { lastSeenEventId: this.getReconnectCursor(input) } : {}
|
|
371
|
+
...mode === "connect" ? { lastSeenEventId: replayCursor === void 0 ? this.getReconnectCursor(input) : replayCursor } : {}
|
|
369
372
|
}),
|
|
370
373
|
...this.config.credentials ? { credentials: this.config.credentials } : {}
|
|
371
374
|
});
|
|
@@ -401,16 +404,17 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
401
404
|
observeThread$(input, credentials, options) {
|
|
402
405
|
return this.observeThreadSession$(input, credentials, options).pipe((0, rxjs_operators.catchError)((error) => {
|
|
403
406
|
if (!this.isSocketReconnectExhaustedError(error)) return (0, rxjs.throwError)(() => error);
|
|
404
|
-
|
|
407
|
+
const replayCursor = this.getReconnectCursor(input);
|
|
408
|
+
return this.requestJoinCredentials$("connect", input, replayCursor).pipe((0, rxjs.switchMap)((refreshedCredentials) => refreshedCredentials === null ? rxjs.EMPTY : this.observeThread$(this.applyCanonicalRunIdentity(input, refreshedCredentials, { fallbackToInputRunId: options.streamMode === "run" }), refreshedCredentials, {
|
|
405
409
|
...options,
|
|
406
410
|
channelMode: "connect",
|
|
407
|
-
replayCursor
|
|
411
|
+
replayCursor
|
|
408
412
|
})));
|
|
409
413
|
}));
|
|
410
414
|
}
|
|
411
415
|
observeThreadSession$(input, credentials, options) {
|
|
412
416
|
return (0, rxjs.defer)(() => {
|
|
413
|
-
var _options$channelMode;
|
|
417
|
+
var _options$channelMode, _options$replayCursor;
|
|
414
418
|
let ownSocket = null;
|
|
415
419
|
let ownChannel = null;
|
|
416
420
|
const socket$ = ɵphoenixSocket$({
|
|
@@ -442,15 +446,24 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
442
446
|
bufferSize: 1,
|
|
443
447
|
refCount: true
|
|
444
448
|
}));
|
|
445
|
-
const
|
|
446
|
-
|
|
449
|
+
const reconnectCursor = this.readDurableEventId((_options$replayCursor = options.replayCursor) !== null && _options$replayCursor !== void 0 ? _options$replayCursor : this.getReconnectCursor(input));
|
|
450
|
+
let latestObservedReplayCursor = null;
|
|
451
|
+
const threadEvents$ = this.observeThreadEvents$(input.threadId, channel$, options).pipe((0, rxjs_operators.tap)((payload) => {
|
|
452
|
+
var _this$readEventId;
|
|
453
|
+
latestObservedReplayCursor = (_this$readEventId = this.readEventId(payload)) !== null && _this$readEventId !== void 0 ? _this$readEventId : latestObservedReplayCursor;
|
|
454
|
+
}), (0, rxjs_operators.share)());
|
|
455
|
+
const replayComplete$ = this.observeControlEvent$(input.threadId, channel$, REPLAY_COMPLETE_EVENT).pipe((0, rxjs_operators.shareReplay)({
|
|
456
|
+
bufferSize: 1,
|
|
457
|
+
refCount: true
|
|
458
|
+
}));
|
|
447
459
|
const streamIdle$ = this.observeControlEvent$(input.threadId, channel$, STREAM_IDLE_EVENT).pipe((0, rxjs_operators.shareReplay)({
|
|
448
460
|
bufferSize: 1,
|
|
449
461
|
refCount: true
|
|
450
462
|
}));
|
|
451
|
-
const streamIdleCompletion$ = options.streamMode === "connect" ? streamIdle$.pipe((0, rxjs_operators.take)(1)) : rxjs.EMPTY;
|
|
452
|
-
const
|
|
453
|
-
|
|
463
|
+
const streamIdleCompletion$ = options.streamMode === "connect" ? (0, rxjs.merge)((0, rxjs.combineLatest)([replayComplete$.pipe((0, rxjs_operators.take)(1)), streamIdle$.pipe((0, rxjs_operators.take)(1))]), streamIdle$.pipe((0, rxjs_operators.take)(1), (0, rxjs_operators.filter)((payload) => this.canFallbackCompleteConnect(payload, reconnectCursor, latestObservedReplayCursor)), (0, rxjs_operators.delay)(CONNECT_STREAM_IDLE_REPLAY_FALLBACK_MS))).pipe((0, rxjs_operators.take)(1)) : rxjs.EMPTY;
|
|
464
|
+
const threadCompleted$ = threadEvents$.pipe((0, rxjs_operators.ignoreElements)(), (0, rxjs_operators.endWith)(null), (0, rxjs_operators.take)(1));
|
|
465
|
+
const terminal$ = (0, rxjs.merge)(threadCompleted$, streamIdleCompletion$);
|
|
466
|
+
return (0, rxjs.merge)(this.joinThreadChannel$(channel$), this.observeSocketHealth$(socket$).pipe((0, rxjs_operators.takeUntil)(terminal$)), threadEvents$.pipe((0, rxjs_operators.takeUntil)(streamIdleCompletion$)), replayComplete$.pipe((0, rxjs_operators.ignoreElements)(), (0, rxjs_operators.takeUntil)(terminal$)), streamIdleCompletion$.pipe((0, rxjs_operators.ignoreElements)(), (0, rxjs_operators.takeUntil)(threadCompleted$))).pipe((0, rxjs_operators.finalize)(() => this.cleanupOwned(ownChannel, ownSocket)));
|
|
454
467
|
});
|
|
455
468
|
}
|
|
456
469
|
joinThreadChannel$(channel$) {
|
|
@@ -518,23 +531,37 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
518
531
|
updateLastSeenEventId(threadId, payload) {
|
|
519
532
|
const eventId = this.readEventId(payload);
|
|
520
533
|
if (!eventId) return;
|
|
521
|
-
this.
|
|
534
|
+
this.advanceLastSeenEventId(threadId, eventId);
|
|
522
535
|
}
|
|
523
536
|
updateLastSeenEventIdFromControl(threadId, payload) {
|
|
524
537
|
const eventId = this.readControlEventId(payload);
|
|
525
538
|
if (!eventId) return;
|
|
539
|
+
this.advanceLastSeenEventId(threadId, eventId);
|
|
540
|
+
}
|
|
541
|
+
advanceLastSeenEventId(threadId, eventId) {
|
|
526
542
|
this.sharedState.lastSeenEventIds.set(threadId, eventId);
|
|
527
543
|
}
|
|
528
544
|
readEventId(payload) {
|
|
529
545
|
const metadata = payload.metadata;
|
|
530
546
|
if (!metadata || typeof metadata !== "object") return null;
|
|
531
|
-
const
|
|
532
|
-
return
|
|
547
|
+
const eventMetadata = metadata;
|
|
548
|
+
return this.readDurableEventId(eventMetadata.cpki_event_id);
|
|
533
549
|
}
|
|
534
550
|
readControlEventId(payload) {
|
|
551
|
+
var _controlPayload$lates;
|
|
535
552
|
if (!payload || typeof payload !== "object") return null;
|
|
536
|
-
const
|
|
537
|
-
|
|
553
|
+
const controlPayload = payload;
|
|
554
|
+
const latestEventId = (_controlPayload$lates = controlPayload.latestEventId) !== null && _controlPayload$lates !== void 0 ? _controlPayload$lates : controlPayload.latest_event_id;
|
|
555
|
+
return this.readDurableEventId(latestEventId);
|
|
556
|
+
}
|
|
557
|
+
readDurableEventId(eventId) {
|
|
558
|
+
if (typeof eventId !== "string" || eventId.trim() === "") return null;
|
|
559
|
+
return eventId.startsWith("cpki_ingested") ? null : eventId;
|
|
560
|
+
}
|
|
561
|
+
canFallbackCompleteConnect(streamIdlePayload, reconnectCursor, latestObservedReplayCursor) {
|
|
562
|
+
const idleCursor = this.readControlEventId(streamIdlePayload);
|
|
563
|
+
if (!idleCursor) return true;
|
|
564
|
+
return idleCursor === reconnectCursor || idleCursor === latestObservedReplayCursor;
|
|
538
565
|
}
|
|
539
566
|
applyCanonicalRunIdentity(input, credentials, options) {
|
|
540
567
|
var _credentials$runId;
|
|
@@ -1769,7 +1796,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1769
1796
|
_defineProperty(this, "_tools", []);
|
|
1770
1797
|
_defineProperty(this, "_runAbortController", null);
|
|
1771
1798
|
_defineProperty(this, "_runDepth", 0);
|
|
1772
|
-
_defineProperty(this, "
|
|
1799
|
+
_defineProperty(this, "_lastConnectedThreadIdsByAgent", /* @__PURE__ */ new Map());
|
|
1800
|
+
_defineProperty(this, "_anonymousAgentIds", /* @__PURE__ */ new WeakMap());
|
|
1801
|
+
_defineProperty(this, "_nextAnonymousAgentId", 0);
|
|
1773
1802
|
}
|
|
1774
1803
|
/**
|
|
1775
1804
|
* Abort the current run. Called by `CopilotKitCore.stopAgent()` to signal
|
|
@@ -1788,6 +1817,20 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1788
1817
|
return this.core;
|
|
1789
1818
|
}
|
|
1790
1819
|
/**
|
|
1820
|
+
* Return a stable restore-tracking key for the logical agent being
|
|
1821
|
+
* connected. Named agents share their last-thread marker across proxy
|
|
1822
|
+
* instances; anonymous agents fall back to object identity.
|
|
1823
|
+
*/
|
|
1824
|
+
getConnectRestoreKey(agent) {
|
|
1825
|
+
if (agent.agentId) return `agent:${agent.agentId}`;
|
|
1826
|
+
const existing = this._anonymousAgentIds.get(agent);
|
|
1827
|
+
if (existing) return existing;
|
|
1828
|
+
const anonymousId = `anonymous:${this._nextAnonymousAgentId}`;
|
|
1829
|
+
this._nextAnonymousAgentId += 1;
|
|
1830
|
+
this._anonymousAgentIds.set(agent, anonymousId);
|
|
1831
|
+
return anonymousId;
|
|
1832
|
+
}
|
|
1833
|
+
/**
|
|
1791
1834
|
* Get all tools as a readonly array
|
|
1792
1835
|
*/
|
|
1793
1836
|
get tools() {
|
|
@@ -1842,16 +1885,20 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1842
1885
|
*/
|
|
1843
1886
|
async connectAgent({ agent }) {
|
|
1844
1887
|
try {
|
|
1845
|
-
var _agent$threadId;
|
|
1888
|
+
var _agent$threadId, _this$_lastConnectedT;
|
|
1846
1889
|
const incomingThreadId = (_agent$threadId = agent.threadId) !== null && _agent$threadId !== void 0 ? _agent$threadId : null;
|
|
1847
|
-
const
|
|
1848
|
-
this.
|
|
1890
|
+
const restoreKey = this.getConnectRestoreKey(agent);
|
|
1891
|
+
const isFreshRestore = incomingThreadId !== ((_this$_lastConnectedT = this._lastConnectedThreadIdsByAgent.get(restoreKey)) !== null && _this$_lastConnectedT !== void 0 ? _this$_lastConnectedT : null);
|
|
1892
|
+
this._lastConnectedThreadIdsByAgent.set(restoreKey, incomingThreadId);
|
|
1849
1893
|
await agent.detachActiveRun();
|
|
1850
1894
|
if (isFreshRestore) {
|
|
1851
1895
|
agent.setMessages([]);
|
|
1852
1896
|
agent.setState({});
|
|
1853
|
-
const
|
|
1854
|
-
if (incomingThreadId
|
|
1897
|
+
const cursorAware = agent;
|
|
1898
|
+
if (incomingThreadId) {
|
|
1899
|
+
if (typeof cursorAware.clearReplayCursor === "function") cursorAware.clearReplayCursor(incomingThreadId);
|
|
1900
|
+
if (typeof cursorAware.clearReconnectCursor === "function") cursorAware.clearReconnectCursor(incomingThreadId);
|
|
1901
|
+
}
|
|
1855
1902
|
}
|
|
1856
1903
|
this._internal.applyHeadersToAgent(agent);
|
|
1857
1904
|
await this._internal.notifySubscribers((subscriber) => {
|
|
@@ -1868,7 +1915,8 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1868
1915
|
}, this.createAgentErrorSubscriber(agent));
|
|
1869
1916
|
return this.processAgentResult({
|
|
1870
1917
|
runAgentResult,
|
|
1871
|
-
agent
|
|
1918
|
+
agent,
|
|
1919
|
+
executeFrontendTools: false
|
|
1872
1920
|
});
|
|
1873
1921
|
} catch (error) {
|
|
1874
1922
|
const connectError = error instanceof Error ? error : new Error(String(error));
|
|
@@ -1890,7 +1938,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1890
1938
|
/**
|
|
1891
1939
|
* Run an agent
|
|
1892
1940
|
*/
|
|
1893
|
-
async runAgent({ agent, forwardedProps, resume }) {
|
|
1941
|
+
async runAgent({ agent, forwardedProps, resume, runId }) {
|
|
1894
1942
|
if (agent.agentId) this._internal.suggestionEngine.clearSuggestions(agent.agentId);
|
|
1895
1943
|
this._internal.applyHeadersToAgent(agent);
|
|
1896
1944
|
if (agent.detachActiveRun) await agent.detachActiveRun();
|
|
@@ -1920,6 +1968,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1920
1968
|
...forwardedProps
|
|
1921
1969
|
},
|
|
1922
1970
|
...resume !== void 0 ? { resume } : {},
|
|
1971
|
+
...runId !== void 0 ? { runId } : {},
|
|
1923
1972
|
tools: this.buildFrontendTools(agent.agentId),
|
|
1924
1973
|
context: this._internal.getContextForAgent(agent.agentId)
|
|
1925
1974
|
}, this.createAgentErrorSubscriber(agent));
|
|
@@ -1948,26 +1997,28 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1948
1997
|
/**
|
|
1949
1998
|
* Process agent result and execute tools
|
|
1950
1999
|
*/
|
|
1951
|
-
async processAgentResult({ runAgentResult, agent }) {
|
|
2000
|
+
async processAgentResult({ runAgentResult, agent, executeFrontendTools = true }) {
|
|
1952
2001
|
var _this$_runAbortContro2;
|
|
1953
2002
|
const { newMessages } = runAgentResult;
|
|
1954
2003
|
const agentId = agent.agentId;
|
|
1955
2004
|
let needsFollowUp = false;
|
|
1956
|
-
|
|
1957
|
-
for (const
|
|
1958
|
-
const tool
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
});
|
|
1962
|
-
if (tool) {
|
|
1963
|
-
if (await this.executeSpecificTool(tool, toolCall, message, agent, agentId)) needsFollowUp = true;
|
|
1964
|
-
} else {
|
|
1965
|
-
const wildcardTool = this.getTool({
|
|
1966
|
-
toolName: "*",
|
|
2005
|
+
if (executeFrontendTools) {
|
|
2006
|
+
for (const message of newMessages) if (message.role === "assistant") {
|
|
2007
|
+
for (const toolCall of message.toolCalls || []) if (newMessages.findIndex((m) => m.role === "tool" && m.toolCallId === toolCall.id) === -1) {
|
|
2008
|
+
const tool = this.getTool({
|
|
2009
|
+
toolName: toolCall.function.name,
|
|
1967
2010
|
agentId: agent.agentId
|
|
1968
2011
|
});
|
|
1969
|
-
if (
|
|
1970
|
-
if (await this.
|
|
2012
|
+
if (tool) {
|
|
2013
|
+
if (await this.executeSpecificTool(tool, toolCall, message, agent, agentId)) needsFollowUp = true;
|
|
2014
|
+
} else {
|
|
2015
|
+
const wildcardTool = this.getTool({
|
|
2016
|
+
toolName: "*",
|
|
2017
|
+
agentId: agent.agentId
|
|
2018
|
+
});
|
|
2019
|
+
if (wildcardTool) {
|
|
2020
|
+
if (await this.executeWildcardTool(wildcardTool, toolCall, message, agent, agentId)) needsFollowUp = true;
|
|
2021
|
+
}
|
|
1971
2022
|
}
|
|
1972
2023
|
}
|
|
1973
2024
|
}
|
|
@@ -2603,6 +2654,129 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
2603
2654
|
}
|
|
2604
2655
|
};
|
|
2605
2656
|
|
|
2657
|
+
//#endregion
|
|
2658
|
+
//#region src/core/subagent-registry.ts
|
|
2659
|
+
/**
|
|
2660
|
+
* Tracks subagent lifecycle events (SUBAGENT_STARTED / FINISHED / ERROR) per
|
|
2661
|
+
* owning agent so consumers can resolve a message's `subagentId` to a name,
|
|
2662
|
+
* description, and running status.
|
|
2663
|
+
*
|
|
2664
|
+
* Modeled on {@link SuggestionEngine}: an in-memory `Record` keyed by (owning)
|
|
2665
|
+
* agentId, mutated from streamed AG-UI events, made reactive by calling
|
|
2666
|
+
* `notifySubscribers(onSubagentsChanged)` after every change. It owns its own
|
|
2667
|
+
* per-agent `agent.subscribe` (like {@link StateManager}) so it is fully
|
|
2668
|
+
* self-contained and adds no coupling to the state/message tracking path.
|
|
2669
|
+
*
|
|
2670
|
+
* No-op for runs without subagents (a normal LangGraph run never emits
|
|
2671
|
+
* SUBAGENT_* events), so the registry simply stays empty.
|
|
2672
|
+
*/
|
|
2673
|
+
var SubagentRegistry = class {
|
|
2674
|
+
constructor(core) {
|
|
2675
|
+
this.core = core;
|
|
2676
|
+
_defineProperty(this, "_subagents", {});
|
|
2677
|
+
_defineProperty(this, "agentSubscriptions", /* @__PURE__ */ new Map());
|
|
2678
|
+
}
|
|
2679
|
+
/**
|
|
2680
|
+
* Subscribe to an agent's subagent lifecycle events. Idempotent per agentId:
|
|
2681
|
+
* an existing subscription for the same agent is revoked and replaced.
|
|
2682
|
+
*/
|
|
2683
|
+
subscribeToAgent(agent) {
|
|
2684
|
+
if (!agent.agentId) return;
|
|
2685
|
+
const agentId = agent.agentId;
|
|
2686
|
+
const existingUnsubscribe = this.agentSubscriptions.get(agentId);
|
|
2687
|
+
if (existingUnsubscribe) {
|
|
2688
|
+
existingUnsubscribe();
|
|
2689
|
+
this.agentSubscriptions.delete(agentId);
|
|
2690
|
+
}
|
|
2691
|
+
let revoked = false;
|
|
2692
|
+
const { unsubscribe } = agent.subscribe({
|
|
2693
|
+
onSubagentStartedEvent: ({ event }) => {
|
|
2694
|
+
if (revoked) return;
|
|
2695
|
+
this.handleStarted(agentId, event);
|
|
2696
|
+
},
|
|
2697
|
+
onSubagentFinishedEvent: ({ event }) => {
|
|
2698
|
+
if (revoked) return;
|
|
2699
|
+
this.handleFinished(agentId, event);
|
|
2700
|
+
},
|
|
2701
|
+
onSubagentErrorEvent: ({ event }) => {
|
|
2702
|
+
if (revoked) return;
|
|
2703
|
+
this.handleError(agentId, event);
|
|
2704
|
+
}
|
|
2705
|
+
});
|
|
2706
|
+
this.agentSubscriptions.set(agentId, () => {
|
|
2707
|
+
revoked = true;
|
|
2708
|
+
unsubscribe();
|
|
2709
|
+
});
|
|
2710
|
+
}
|
|
2711
|
+
/**
|
|
2712
|
+
* Unsubscribe an agent's subscription (symmetric with StateManager cleanup).
|
|
2713
|
+
*/
|
|
2714
|
+
unsubscribeFromAgent(agentId) {
|
|
2715
|
+
const unsubscribe = this.agentSubscriptions.get(agentId);
|
|
2716
|
+
if (unsubscribe) {
|
|
2717
|
+
unsubscribe();
|
|
2718
|
+
this.agentSubscriptions.delete(agentId);
|
|
2719
|
+
}
|
|
2720
|
+
}
|
|
2721
|
+
/**
|
|
2722
|
+
* Get the subagents observed for an owning agent, keyed by subagentId.
|
|
2723
|
+
* Returns a fresh shallow copy each call so consumers (and React state) see
|
|
2724
|
+
* a new reference when anything changed.
|
|
2725
|
+
*/
|
|
2726
|
+
getSubagents(agentId) {
|
|
2727
|
+
return { ...this._subagents[agentId] };
|
|
2728
|
+
}
|
|
2729
|
+
handleStarted(agentId, event) {
|
|
2730
|
+
var _this$_subagents, _this$_subagents$agen;
|
|
2731
|
+
const bucket = (_this$_subagents$agen = (_this$_subagents = this._subagents)[agentId]) !== null && _this$_subagents$agen !== void 0 ? _this$_subagents$agen : _this$_subagents[agentId] = {};
|
|
2732
|
+
bucket[event.subagentId] = {
|
|
2733
|
+
subagentId: event.subagentId,
|
|
2734
|
+
name: event.name,
|
|
2735
|
+
description: event.description,
|
|
2736
|
+
parentSubagentId: event.parentSubagentId,
|
|
2737
|
+
status: "running"
|
|
2738
|
+
};
|
|
2739
|
+
this.notifySubagentsChanged(agentId);
|
|
2740
|
+
}
|
|
2741
|
+
handleFinished(agentId, event) {
|
|
2742
|
+
const bucket = this._subagents[agentId];
|
|
2743
|
+
const existing = bucket === null || bucket === void 0 ? void 0 : bucket[event.subagentId];
|
|
2744
|
+
if (!bucket || !existing) return;
|
|
2745
|
+
bucket[event.subagentId] = {
|
|
2746
|
+
...existing,
|
|
2747
|
+
status: "finished"
|
|
2748
|
+
};
|
|
2749
|
+
this.notifySubagentsChanged(agentId);
|
|
2750
|
+
}
|
|
2751
|
+
handleError(agentId, event) {
|
|
2752
|
+
var _this$_subagents2, _this$_subagents2$age;
|
|
2753
|
+
const bucket = (_this$_subagents2$age = (_this$_subagents2 = this._subagents)[agentId]) !== null && _this$_subagents2$age !== void 0 ? _this$_subagents2$age : _this$_subagents2[agentId] = {};
|
|
2754
|
+
const existing = bucket[event.subagentId];
|
|
2755
|
+
bucket[event.subagentId] = existing ? {
|
|
2756
|
+
...existing,
|
|
2757
|
+
status: "error",
|
|
2758
|
+
error: event.message
|
|
2759
|
+
} : {
|
|
2760
|
+
subagentId: event.subagentId,
|
|
2761
|
+
name: event.subagentId,
|
|
2762
|
+
status: "error",
|
|
2763
|
+
error: event.message
|
|
2764
|
+
};
|
|
2765
|
+
this.notifySubagentsChanged(agentId);
|
|
2766
|
+
}
|
|
2767
|
+
async notifySubagentsChanged(agentId) {
|
|
2768
|
+
const subagents = this.getSubagents(agentId);
|
|
2769
|
+
await this.core.notifySubscribers((subscriber) => {
|
|
2770
|
+
var _subscriber$onSubagen;
|
|
2771
|
+
return (_subscriber$onSubagen = subscriber.onSubagentsChanged) === null || _subscriber$onSubagen === void 0 ? void 0 : _subscriber$onSubagen.call(subscriber, {
|
|
2772
|
+
copilotkit: this.core,
|
|
2773
|
+
agentId,
|
|
2774
|
+
subagents
|
|
2775
|
+
});
|
|
2776
|
+
}, "Subscriber onSubagentsChanged error:");
|
|
2777
|
+
}
|
|
2778
|
+
};
|
|
2779
|
+
|
|
2606
2780
|
//#endregion
|
|
2607
2781
|
//#region src/core/thread-store-registry.ts
|
|
2608
2782
|
var ThreadStoreRegistry = class {
|
|
@@ -2665,206 +2839,1196 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
2665
2839
|
};
|
|
2666
2840
|
|
|
2667
2841
|
//#endregion
|
|
2668
|
-
//#region src/
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
CopilotKitCoreErrorCode["TOOL_ARGUMENT_PARSE_FAILED"] = "tool_argument_parse_failed";
|
|
2676
|
-
CopilotKitCoreErrorCode["TOOL_HANDLER_FAILED"] = "tool_handler_failed";
|
|
2677
|
-
CopilotKitCoreErrorCode["TOOL_NOT_FOUND"] = "tool_not_found";
|
|
2678
|
-
CopilotKitCoreErrorCode["AGENT_NOT_FOUND"] = "agent_not_found";
|
|
2679
|
-
/**
|
|
2680
|
-
* Emitted when an agent run fails because the thread is already locked
|
|
2681
|
-
* by another active run.
|
|
2682
|
-
*
|
|
2683
|
-
* @example
|
|
2684
|
-
* ```tsx
|
|
2685
|
-
* <CopilotKitProvider
|
|
2686
|
-
* onError={({ code, error, context }) => {
|
|
2687
|
-
* if (code === "agent_thread_locked") {
|
|
2688
|
-
* // Show "Agent is busy, retry?" UI
|
|
2689
|
-
* }
|
|
2690
|
-
* }}
|
|
2691
|
-
* />
|
|
2692
|
-
* ```
|
|
2693
|
-
*/
|
|
2694
|
-
CopilotKitCoreErrorCode["AGENT_THREAD_LOCKED"] = "agent_thread_locked";
|
|
2695
|
-
CopilotKitCoreErrorCode["TRANSCRIPTION_FAILED"] = "transcription_failed";
|
|
2696
|
-
CopilotKitCoreErrorCode["TRANSCRIPTION_SERVICE_NOT_CONFIGURED"] = "transcription_service_not_configured";
|
|
2697
|
-
CopilotKitCoreErrorCode["TRANSCRIPTION_INVALID_AUDIO"] = "transcription_invalid_audio";
|
|
2698
|
-
CopilotKitCoreErrorCode["TRANSCRIPTION_RATE_LIMITED"] = "transcription_rate_limited";
|
|
2699
|
-
CopilotKitCoreErrorCode["TRANSCRIPTION_AUTH_FAILED"] = "transcription_auth_failed";
|
|
2700
|
-
CopilotKitCoreErrorCode["TRANSCRIPTION_NETWORK_ERROR"] = "transcription_network_error";
|
|
2701
|
-
CopilotKitCoreErrorCode["SUBSCRIBER_CALLBACK_FAILED"] = "subscriber_callback_failed";
|
|
2702
|
-
return CopilotKitCoreErrorCode;
|
|
2703
|
-
}({});
|
|
2842
|
+
//#region src/utils/micro-redux.ts
|
|
2843
|
+
const INTERNAL_ACTION_TYPES = {
|
|
2844
|
+
boot: "@@micro-redux/boot",
|
|
2845
|
+
init: "@@micro-redux/init",
|
|
2846
|
+
stop: "@@micro-redux/stop"
|
|
2847
|
+
};
|
|
2848
|
+
const INTERNAL_BOOT_ACTION = { type: INTERNAL_ACTION_TYPES.boot };
|
|
2704
2849
|
/**
|
|
2705
|
-
*
|
|
2706
|
-
* to module scope so the Set is allocated once, not per-subscription.
|
|
2850
|
+
* Builds a typed action creator from a type string and payload factory.
|
|
2707
2851
|
*/
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
CopilotKitCoreRuntimeConnectionStatus["Disconnected"] = "disconnected";
|
|
2718
|
-
CopilotKitCoreRuntimeConnectionStatus["Connected"] = "connected";
|
|
2719
|
-
CopilotKitCoreRuntimeConnectionStatus["Connecting"] = "connecting";
|
|
2720
|
-
CopilotKitCoreRuntimeConnectionStatus["Error"] = "error";
|
|
2721
|
-
return CopilotKitCoreRuntimeConnectionStatus;
|
|
2722
|
-
}({});
|
|
2852
|
+
function createTypedActionCreator(type, factory) {
|
|
2853
|
+
const creator = ((...args) => ({
|
|
2854
|
+
...factory(...args),
|
|
2855
|
+
type
|
|
2856
|
+
}));
|
|
2857
|
+
creator.type = type;
|
|
2858
|
+
creator.match = (action) => action.type === type;
|
|
2859
|
+
return creator;
|
|
2860
|
+
}
|
|
2723
2861
|
/**
|
|
2724
|
-
*
|
|
2725
|
-
*
|
|
2726
|
-
*
|
|
2727
|
-
*
|
|
2862
|
+
* Declares a payload-based action config for `createActionGroup`.
|
|
2863
|
+
*
|
|
2864
|
+
* @example
|
|
2865
|
+
* ```ts
|
|
2866
|
+
* const actions = createActionGroup("User", {
|
|
2867
|
+
* loaded: props<{ id: string }>(),
|
|
2868
|
+
* });
|
|
2869
|
+
* ```
|
|
2728
2870
|
*/
|
|
2729
|
-
function
|
|
2730
|
-
return
|
|
2871
|
+
function props() {
|
|
2872
|
+
return { kind: "props" };
|
|
2731
2873
|
}
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
this.agentRegistry.setRuntimeTransport(runtimeTransport);
|
|
2762
|
-
this.agentRegistry.setRuntimeUrl(runtimeUrl);
|
|
2763
|
-
this.previousAgentIds = new Set(Object.keys(agents__unsafe_dev_only));
|
|
2764
|
-
this.subscribe({ onAgentsChanged: ({ agents }) => {
|
|
2765
|
-
Object.values(agents).forEach((agent) => {
|
|
2766
|
-
if (agent.agentId) this.stateManager.subscribeToAgent(agent);
|
|
2767
|
-
});
|
|
2768
|
-
const currentAgentIds = new Set(Object.keys(agents));
|
|
2769
|
-
for (const agentId of Object.keys(this.threadStoreRegistry.getAll())) if (this.previousAgentIds.has(agentId) && !currentAgentIds.has(agentId)) try {
|
|
2770
|
-
this.threadStoreRegistry.unregister(agentId);
|
|
2771
|
-
} catch (err) {
|
|
2772
|
-
console.error(`CopilotKitCore.onAgentsChanged: threadStoreRegistry.unregister failed for "${agentId}":`, err);
|
|
2773
|
-
}
|
|
2774
|
-
for (const agentId of this.previousAgentIds) if (!currentAgentIds.has(agentId)) try {
|
|
2775
|
-
this.stateManager.unsubscribeFromAgent(agentId);
|
|
2776
|
-
} catch (err) {
|
|
2777
|
-
console.error(`CopilotKitCore.onAgentsChanged: stateManager.unsubscribeFromAgent failed for "${agentId}":`, err);
|
|
2778
|
-
}
|
|
2779
|
-
this.previousAgentIds = currentAgentIds;
|
|
2780
|
-
} });
|
|
2781
|
-
}
|
|
2782
|
-
/**
|
|
2783
|
-
* Internal method used by delegate classes and subclasses to notify subscribers
|
|
2784
|
-
*/
|
|
2785
|
-
async notifySubscribers(handler, errorMessage) {
|
|
2786
|
-
await Promise.all(Array.from(this.subscribers).map(async (subscriber) => {
|
|
2787
|
-
try {
|
|
2788
|
-
await handler(subscriber);
|
|
2789
|
-
} catch (error) {
|
|
2790
|
-
console.error(errorMessage, error);
|
|
2791
|
-
}
|
|
2792
|
-
}));
|
|
2793
|
-
}
|
|
2794
|
-
/**
|
|
2795
|
-
* Internal method used by delegate classes to emit errors
|
|
2796
|
-
*/
|
|
2797
|
-
async emitError({ error, code, context = {} }) {
|
|
2798
|
-
await this.notifySubscribers((subscriber) => {
|
|
2799
|
-
var _subscriber$onError;
|
|
2800
|
-
return (_subscriber$onError = subscriber.onError) === null || _subscriber$onError === void 0 ? void 0 : _subscriber$onError.call(subscriber, {
|
|
2801
|
-
copilotkit: this,
|
|
2802
|
-
error,
|
|
2803
|
-
code,
|
|
2804
|
-
context
|
|
2805
|
-
});
|
|
2806
|
-
}, "Subscriber onError error:");
|
|
2874
|
+
/**
|
|
2875
|
+
* Declares a no-payload action config for `createActionGroup`.
|
|
2876
|
+
*
|
|
2877
|
+
* @example
|
|
2878
|
+
* ```ts
|
|
2879
|
+
* const actions = createActionGroup("User", {
|
|
2880
|
+
* reset: empty(),
|
|
2881
|
+
* });
|
|
2882
|
+
* ```
|
|
2883
|
+
*/
|
|
2884
|
+
function empty() {
|
|
2885
|
+
return { kind: "empty" };
|
|
2886
|
+
}
|
|
2887
|
+
/**
|
|
2888
|
+
* Creates a namespaced group of typed action creators.
|
|
2889
|
+
*
|
|
2890
|
+
* Action types are formatted as: `[Source] actionName`.
|
|
2891
|
+
*/
|
|
2892
|
+
function createActionGroup(source, config) {
|
|
2893
|
+
const group = {};
|
|
2894
|
+
for (const eventName of Object.keys(config)) {
|
|
2895
|
+
const eventConfig = config[eventName];
|
|
2896
|
+
if (!eventConfig) continue;
|
|
2897
|
+
const actionType = `[${source}] ${eventName}`;
|
|
2898
|
+
if (eventConfig.kind === "props") {
|
|
2899
|
+
group[eventName] = createTypedActionCreator(actionType, (payload) => ({ ...payload }));
|
|
2900
|
+
continue;
|
|
2901
|
+
}
|
|
2902
|
+
group[eventName] = createTypedActionCreator(actionType, () => ({}));
|
|
2807
2903
|
}
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
}
|
|
2836
|
-
get runtimeTransport() {
|
|
2837
|
-
return this.agentRegistry.runtimeTransport;
|
|
2838
|
-
}
|
|
2839
|
-
setRuntimeTransport(runtimeTransport) {
|
|
2840
|
-
this.agentRegistry.setRuntimeTransport(runtimeTransport);
|
|
2841
|
-
}
|
|
2842
|
-
get runtimeVersion() {
|
|
2843
|
-
return this.agentRegistry.runtimeVersion;
|
|
2844
|
-
}
|
|
2845
|
-
get headers() {
|
|
2846
|
-
return this._headers;
|
|
2904
|
+
return group;
|
|
2905
|
+
}
|
|
2906
|
+
/**
|
|
2907
|
+
* Registers one reducer handler for one or more action creators.
|
|
2908
|
+
*
|
|
2909
|
+
* @throws Error when called without at least one action creator and reducer.
|
|
2910
|
+
*/
|
|
2911
|
+
function on(...args) {
|
|
2912
|
+
if (args.length < 2) throw new Error("on requires at least one action creator and one reducer");
|
|
2913
|
+
const reducer = args[args.length - 1];
|
|
2914
|
+
return {
|
|
2915
|
+
creators: args.slice(0, -1),
|
|
2916
|
+
reducer
|
|
2917
|
+
};
|
|
2918
|
+
}
|
|
2919
|
+
/**
|
|
2920
|
+
* Creates a reducer from an initial state and `on(...)` handler entries.
|
|
2921
|
+
*
|
|
2922
|
+
* Unknown action types return the current state unchanged.
|
|
2923
|
+
*/
|
|
2924
|
+
function createReducer(initialState, ...entries) {
|
|
2925
|
+
const reducerMap = /* @__PURE__ */ new Map();
|
|
2926
|
+
for (const entry of entries) for (const creator of entry.creators) {
|
|
2927
|
+
var _reducerMap$get;
|
|
2928
|
+
const handlers = (_reducerMap$get = reducerMap.get(creator.type)) !== null && _reducerMap$get !== void 0 ? _reducerMap$get : [];
|
|
2929
|
+
handlers.push(entry.reducer);
|
|
2930
|
+
reducerMap.set(creator.type, handlers);
|
|
2847
2931
|
}
|
|
2848
|
-
|
|
2849
|
-
|
|
2932
|
+
return (state, action) => {
|
|
2933
|
+
const currentState = state !== null && state !== void 0 ? state : initialState;
|
|
2934
|
+
const handlers = reducerMap.get(action.type);
|
|
2935
|
+
if (!handlers || handlers.length === 0) return currentState;
|
|
2936
|
+
let nextState = currentState;
|
|
2937
|
+
for (const handler of handlers) nextState = handler(nextState, action);
|
|
2938
|
+
return nextState;
|
|
2939
|
+
};
|
|
2940
|
+
}
|
|
2941
|
+
/**
|
|
2942
|
+
* Creates a selector that caches and reuses the last computed result
|
|
2943
|
+
* when all input references are unchanged.
|
|
2944
|
+
*/
|
|
2945
|
+
function createSelector(...args) {
|
|
2946
|
+
if (args.length === 1) {
|
|
2947
|
+
const projector = args[0];
|
|
2948
|
+
let hasCached = false;
|
|
2949
|
+
let lastState;
|
|
2950
|
+
let lastResult;
|
|
2951
|
+
return (state) => {
|
|
2952
|
+
if (hasCached && state === lastState) return lastResult;
|
|
2953
|
+
lastState = state;
|
|
2954
|
+
lastResult = projector(state);
|
|
2955
|
+
hasCached = true;
|
|
2956
|
+
return lastResult;
|
|
2957
|
+
};
|
|
2850
2958
|
}
|
|
2851
|
-
|
|
2852
|
-
|
|
2959
|
+
const projector = args[args.length - 1];
|
|
2960
|
+
const selectors = args.slice(0, -1);
|
|
2961
|
+
let hasCached = false;
|
|
2962
|
+
let lastInputs = [];
|
|
2963
|
+
let lastResult;
|
|
2964
|
+
return (state) => {
|
|
2965
|
+
const inputs = selectors.map((selector) => selector(state));
|
|
2966
|
+
if (hasCached && inputs.length === lastInputs.length && inputs.every((value, index) => value === lastInputs[index])) return lastResult;
|
|
2967
|
+
lastInputs = inputs;
|
|
2968
|
+
lastResult = projector(...inputs);
|
|
2969
|
+
hasCached = true;
|
|
2970
|
+
return lastResult;
|
|
2971
|
+
};
|
|
2972
|
+
}
|
|
2973
|
+
/**
|
|
2974
|
+
* RxJS operator that maps state emissions through a selector and suppresses
|
|
2975
|
+
* unchanged projected values via reference equality.
|
|
2976
|
+
*/
|
|
2977
|
+
function select(selector) {
|
|
2978
|
+
return (source$) => source$.pipe((0, rxjs_operators.map)(selector), (0, rxjs_operators.distinctUntilChanged)());
|
|
2979
|
+
}
|
|
2980
|
+
/**
|
|
2981
|
+
* RxJS operator that filters an action stream by action creators and narrows
|
|
2982
|
+
* the output action type to the matched creator union.
|
|
2983
|
+
*
|
|
2984
|
+
* @throws Error when called without at least one action creator.
|
|
2985
|
+
*/
|
|
2986
|
+
function ofType(...creators) {
|
|
2987
|
+
if (creators.length === 0) throw new Error("ofType requires at least one action creator");
|
|
2988
|
+
const actionTypes = new Set(creators.map((creator) => creator.type));
|
|
2989
|
+
return (source$) => {
|
|
2990
|
+
return source$.pipe((0, rxjs_operators.filter)((action) => {
|
|
2991
|
+
return actionTypes.has(action.type);
|
|
2992
|
+
}));
|
|
2993
|
+
};
|
|
2994
|
+
}
|
|
2995
|
+
/**
|
|
2996
|
+
* Creates an effect descriptor consumed by `createStore`.
|
|
2997
|
+
*/
|
|
2998
|
+
function createEffect(factory, options = {}) {
|
|
2999
|
+
if (options.dispatch === false) return {
|
|
3000
|
+
run: factory,
|
|
3001
|
+
dispatch: false
|
|
3002
|
+
};
|
|
3003
|
+
return {
|
|
3004
|
+
run: factory,
|
|
3005
|
+
dispatch: true
|
|
3006
|
+
};
|
|
3007
|
+
}
|
|
3008
|
+
/**
|
|
3009
|
+
* Creates a small observable store with reducer + effects.
|
|
3010
|
+
*
|
|
3011
|
+
* Behavior:
|
|
3012
|
+
* - `init()` starts effects and dispatches `@@micro-redux/init`.
|
|
3013
|
+
* - `stop()` dispatches `@@micro-redux/stop` and unsubscribes all effects.
|
|
3014
|
+
* - Effect action observation is scheduled on `asapScheduler` to avoid
|
|
3015
|
+
* synchronous re-entrancy in the effect loop.
|
|
3016
|
+
* - Any effect error triggers fail-fast teardown and errors both `actions$`
|
|
3017
|
+
* and `state$`.
|
|
3018
|
+
*/
|
|
3019
|
+
function createStore(options) {
|
|
3020
|
+
var _options$effects;
|
|
3021
|
+
const reducer = options.reducer;
|
|
3022
|
+
const effects = (_options$effects = options.effects) !== null && _options$effects !== void 0 ? _options$effects : [];
|
|
3023
|
+
let hasFatalError = false;
|
|
3024
|
+
let isRunning = false;
|
|
3025
|
+
let effectSubscriptions = new rxjs.Subscription();
|
|
3026
|
+
let currentState = reducer(void 0, INTERNAL_BOOT_ACTION);
|
|
3027
|
+
const stateSubject = new rxjs.BehaviorSubject(currentState);
|
|
3028
|
+
const actionsSubject = new rxjs.Subject();
|
|
3029
|
+
const dispatchInternal = (action) => {
|
|
3030
|
+
if (hasFatalError) throw new Error("Store is in a failed state due to an effect error");
|
|
3031
|
+
currentState = reducer(currentState, action);
|
|
3032
|
+
stateSubject.next(currentState);
|
|
3033
|
+
actionsSubject.next(action);
|
|
3034
|
+
};
|
|
3035
|
+
const failFast = (error) => {
|
|
3036
|
+
if (hasFatalError) return;
|
|
3037
|
+
hasFatalError = true;
|
|
3038
|
+
isRunning = false;
|
|
3039
|
+
effectSubscriptions.unsubscribe();
|
|
3040
|
+
effectSubscriptions = new rxjs.Subscription();
|
|
3041
|
+
actionsSubject.error(error);
|
|
3042
|
+
stateSubject.error(error);
|
|
3043
|
+
};
|
|
3044
|
+
const startEffects = () => {
|
|
3045
|
+
for (const effect of effects) {
|
|
3046
|
+
const scheduledActions$ = actionsSubject.asObservable().pipe((0, rxjs_operators.observeOn)(rxjs.asapScheduler));
|
|
3047
|
+
const state$ = stateSubject.asObservable();
|
|
3048
|
+
if (effect.dispatch) {
|
|
3049
|
+
const subscription = effect.run(scheduledActions$, state$).subscribe({
|
|
3050
|
+
next: (effectAction) => {
|
|
3051
|
+
if (hasFatalError) return;
|
|
3052
|
+
dispatchInternal(effectAction);
|
|
3053
|
+
},
|
|
3054
|
+
error: (error) => {
|
|
3055
|
+
failFast(error);
|
|
3056
|
+
}
|
|
3057
|
+
});
|
|
3058
|
+
effectSubscriptions.add(subscription);
|
|
3059
|
+
continue;
|
|
3060
|
+
}
|
|
3061
|
+
const subscription = effect.run(scheduledActions$, state$).subscribe({ error: (error) => {
|
|
3062
|
+
failFast(error);
|
|
3063
|
+
} });
|
|
3064
|
+
effectSubscriptions.add(subscription);
|
|
3065
|
+
}
|
|
3066
|
+
};
|
|
3067
|
+
return {
|
|
3068
|
+
dispatch(action) {
|
|
3069
|
+
dispatchInternal(action);
|
|
3070
|
+
},
|
|
3071
|
+
getState() {
|
|
3072
|
+
return currentState;
|
|
3073
|
+
},
|
|
3074
|
+
get state$() {
|
|
3075
|
+
return stateSubject.asObservable();
|
|
3076
|
+
},
|
|
3077
|
+
get actions$() {
|
|
3078
|
+
return actionsSubject.asObservable();
|
|
3079
|
+
},
|
|
3080
|
+
select(selector) {
|
|
3081
|
+
return stateSubject.asObservable().pipe(select(selector));
|
|
3082
|
+
},
|
|
3083
|
+
init() {
|
|
3084
|
+
if (hasFatalError || isRunning) return;
|
|
3085
|
+
isRunning = true;
|
|
3086
|
+
startEffects();
|
|
3087
|
+
if (hasFatalError) return;
|
|
3088
|
+
dispatchInternal({ type: INTERNAL_ACTION_TYPES.init });
|
|
3089
|
+
},
|
|
3090
|
+
stop() {
|
|
3091
|
+
if (hasFatalError || !isRunning) return;
|
|
3092
|
+
dispatchInternal({ type: INTERNAL_ACTION_TYPES.stop });
|
|
3093
|
+
effectSubscriptions.unsubscribe();
|
|
3094
|
+
effectSubscriptions = new rxjs.Subscription();
|
|
3095
|
+
isRunning = false;
|
|
3096
|
+
}
|
|
3097
|
+
};
|
|
3098
|
+
}
|
|
3099
|
+
|
|
3100
|
+
//#endregion
|
|
3101
|
+
//#region src/memory-errors.ts
|
|
3102
|
+
/**
|
|
3103
|
+
* The memory error registry: the single source of truth for memory error
|
|
3104
|
+
* metadata. Keyed by `code` so a code maps to exactly one category/retryable
|
|
3105
|
+
* default.
|
|
3106
|
+
*
|
|
3107
|
+
* Categories/retryable rationale:
|
|
3108
|
+
* - List/credentials/mutation failures are `dependency` (the runtime/platform
|
|
3109
|
+
* the store calls failed). A 5xx is transient (`retryable: true`); a 4xx is
|
|
3110
|
+
* caller-caused, so the helpers below downgrade those to non-retryable.
|
|
3111
|
+
* - Timeouts are `dependency` and `retryable: true` (the request may simply be
|
|
3112
|
+
* slow).
|
|
3113
|
+
*/
|
|
3114
|
+
const MEMORY_ERROR_REGISTRY = Object.freeze({
|
|
3115
|
+
MEMORY_LIST_FAILED: {
|
|
3116
|
+
code: "MEMORY_LIST_FAILED",
|
|
3117
|
+
category: "dependency",
|
|
3118
|
+
retryable: true,
|
|
3119
|
+
message: "Failed to fetch memories",
|
|
3120
|
+
docsPath: "docs/errors/memory.md#memory_list_failed"
|
|
3121
|
+
},
|
|
3122
|
+
MEMORY_CREDENTIALS_FAILED: {
|
|
3123
|
+
code: "MEMORY_CREDENTIALS_FAILED",
|
|
3124
|
+
category: "dependency",
|
|
3125
|
+
retryable: true,
|
|
3126
|
+
message: "Failed to fetch memory subscribe credentials",
|
|
3127
|
+
docsPath: "docs/errors/memory.md#memory_credentials_failed"
|
|
3128
|
+
},
|
|
3129
|
+
MEMORY_MUTATION_FAILED: {
|
|
3130
|
+
code: "MEMORY_MUTATION_FAILED",
|
|
3131
|
+
category: "dependency",
|
|
3132
|
+
retryable: true,
|
|
3133
|
+
message: "Memory mutation request failed",
|
|
3134
|
+
docsPath: "docs/errors/memory.md#memory_mutation_failed"
|
|
3135
|
+
},
|
|
3136
|
+
MEMORY_REQUEST_TIMEOUT: {
|
|
3137
|
+
code: "MEMORY_REQUEST_TIMEOUT",
|
|
3138
|
+
category: "dependency",
|
|
3139
|
+
retryable: true,
|
|
3140
|
+
message: "Request timed out",
|
|
3141
|
+
docsPath: "docs/errors/memory.md#memory_request_timeout"
|
|
2853
3142
|
}
|
|
3143
|
+
});
|
|
3144
|
+
/**
|
|
3145
|
+
* An `Error` carrying a stable memory error `code`, `category`, and `retryable`
|
|
3146
|
+
* flag so consumers and observability can branch on it without string-matching
|
|
3147
|
+
* the message.
|
|
3148
|
+
*
|
|
3149
|
+
* It is a real `Error` subclass: `instanceof Error` is true, so the public
|
|
3150
|
+
* `MemoryState.error: Error | null` contract (and the `error: Error | null`
|
|
3151
|
+
* surfaced by `useMemories` / `injectMemories`) holds unchanged. Existing
|
|
3152
|
+
* consumers that only read `.message` keep working; the richer fields are
|
|
3153
|
+
* additive.
|
|
3154
|
+
*/
|
|
3155
|
+
var MemoryError = class MemoryError extends Error {
|
|
2854
3156
|
/**
|
|
2855
|
-
*
|
|
2856
|
-
*
|
|
2857
|
-
* `
|
|
3157
|
+
* @param code - Registry code identifying this error.
|
|
3158
|
+
* @param options - Optional overrides:
|
|
3159
|
+
* - `message`: human-readable message (defaults to the registry message;
|
|
3160
|
+
* callers pass a status-bearing string to preserve prior wording).
|
|
3161
|
+
* - `retryable`: overrides the registry default (e.g. a 4xx list failure is
|
|
3162
|
+
* not retryable even though the code's default is).
|
|
3163
|
+
* - `cause`: the underlying error, preserved for debugging.
|
|
2858
3164
|
*/
|
|
2859
|
-
|
|
2860
|
-
|
|
3165
|
+
constructor(code, options) {
|
|
3166
|
+
var _options$message, _options$retryable;
|
|
3167
|
+
const entry = MEMORY_ERROR_REGISTRY[code];
|
|
3168
|
+
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 });
|
|
3169
|
+
_defineProperty(this, "code", void 0);
|
|
3170
|
+
_defineProperty(this, "category", void 0);
|
|
3171
|
+
_defineProperty(this, "retryable", void 0);
|
|
3172
|
+
this.name = "MemoryError";
|
|
3173
|
+
this.code = code;
|
|
3174
|
+
this.category = entry.category;
|
|
3175
|
+
this.retryable = (_options$retryable = options === null || options === void 0 ? void 0 : options.retryable) !== null && _options$retryable !== void 0 ? _options$retryable : entry.retryable;
|
|
3176
|
+
Object.setPrototypeOf(this, MemoryError.prototype);
|
|
2861
3177
|
}
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
3178
|
+
};
|
|
3179
|
+
/**
|
|
3180
|
+
* Narrows an HTTP status to whether the failure is worth retrying: a 5xx (or a
|
|
3181
|
+
* missing/0 status) is a transient dependency failure and retryable; a 4xx is
|
|
3182
|
+
* caller-caused and not. Used so a `MEMORY_LIST_FAILED`/`MEMORY_MUTATION_FAILED`
|
|
3183
|
+
* carries an accurate `retryable` flag derived from the response status.
|
|
3184
|
+
*/
|
|
3185
|
+
function isRetryableStatus(status) {
|
|
3186
|
+
return !(Number.isInteger(status) && status >= 400 && status <= 499);
|
|
3187
|
+
}
|
|
3188
|
+
|
|
3189
|
+
//#endregion
|
|
3190
|
+
//#region src/memory.ts
|
|
3191
|
+
const MEMORIES_PATH = "/memories";
|
|
3192
|
+
const MEMORIES_SUBSCRIBE_PATH = "/memories/subscribe";
|
|
3193
|
+
const REQUEST_TIMEOUT_MS$1 = 15e3;
|
|
3194
|
+
/** Consecutive socket errors tolerated before the realtime stream gives up. */
|
|
3195
|
+
const MAX_SOCKET_RETRIES$1 = 5;
|
|
3196
|
+
/**
|
|
3197
|
+
* HTTP status codes that indicate memory routes are not configured (non-fatal).
|
|
3198
|
+
* 404/501 mean the route is absent/unimplemented; 422 is the runtime's
|
|
3199
|
+
* MISSING_INTELLIGENCE signal (intelligence not configured on the deployment —
|
|
3200
|
+
* see packages/runtime/.../handlers/intelligence/memories.ts). All three map to
|
|
3201
|
+
* the graceful "not available" locked-teaser path, not a hard error.
|
|
3202
|
+
*/
|
|
3203
|
+
const ROUTE_UNAVAILABLE_STATUSES = new Set([
|
|
3204
|
+
404,
|
|
3205
|
+
422,
|
|
3206
|
+
501
|
|
3207
|
+
]);
|
|
3208
|
+
/**
|
|
3209
|
+
* Thrown when a memory route returns a 404/422/501 — treated as "not
|
|
3210
|
+
* configured" (422 is the runtime's MISSING_INTELLIGENCE signal).
|
|
3211
|
+
*/
|
|
3212
|
+
var MemoryRouteUnavailableError = class extends Error {};
|
|
3213
|
+
const initialMemoryState = Object.freeze({
|
|
3214
|
+
memories: Object.freeze([]),
|
|
3215
|
+
isLoading: false,
|
|
3216
|
+
inFlightMutationCount: 0,
|
|
3217
|
+
error: null,
|
|
3218
|
+
context: null,
|
|
3219
|
+
sessionId: 0,
|
|
3220
|
+
available: true,
|
|
3221
|
+
realtimeStatus: "connecting"
|
|
3222
|
+
});
|
|
3223
|
+
const memoryAdapterEvents = createActionGroup("Memory Adapter", {
|
|
3224
|
+
started: empty(),
|
|
3225
|
+
stopped: empty(),
|
|
3226
|
+
contextChanged: props(),
|
|
3227
|
+
addRequested: props(),
|
|
3228
|
+
updateRequested: props(),
|
|
3229
|
+
removeRequested: props()
|
|
3230
|
+
});
|
|
3231
|
+
const memoryRestEvents = createActionGroup("Memory REST", {
|
|
3232
|
+
listRequested: props(),
|
|
3233
|
+
listSucceeded: props(),
|
|
3234
|
+
listFailed: props(),
|
|
3235
|
+
listUnavailable: props(),
|
|
3236
|
+
mutationFinished: props(),
|
|
3237
|
+
credentialsRequested: props(),
|
|
3238
|
+
credentialsSucceeded: props(),
|
|
3239
|
+
credentialsFailed: props(),
|
|
3240
|
+
credentialsUnavailable: props()
|
|
3241
|
+
});
|
|
3242
|
+
const memoryDomainEvents = createActionGroup("Memory Domain", {
|
|
3243
|
+
memoryUpserted: props(),
|
|
3244
|
+
memoryInvalidated: props(),
|
|
3245
|
+
realtimeConnecting: props(),
|
|
3246
|
+
realtimeConnected: props(),
|
|
3247
|
+
realtimeUnavailable: props()
|
|
3248
|
+
});
|
|
3249
|
+
/** Projects a wire memory to the public {@link Memory} shape (drops tenant ids). */
|
|
3250
|
+
function toMemory(memory) {
|
|
3251
|
+
return {
|
|
3252
|
+
id: memory.id,
|
|
3253
|
+
kind: memory.kind,
|
|
3254
|
+
scope: memory.scope,
|
|
3255
|
+
content: memory.content,
|
|
3256
|
+
sourceThreadIds: memory.sourceThreadIds,
|
|
3257
|
+
invalidatedAt: memory.invalidatedAt
|
|
3258
|
+
};
|
|
3259
|
+
}
|
|
3260
|
+
/**
|
|
3261
|
+
* Maps a realtime `memory_metadata` event to the domain action that applies it:
|
|
3262
|
+
* `created`/`updated` upsert the projected memory, `invalidated` removes it by
|
|
3263
|
+
* id. Carries the current `sessionId` so the reducer's session guard can drop
|
|
3264
|
+
* deltas left over from a previous context.
|
|
3265
|
+
*/
|
|
3266
|
+
function mapMemoryMetadataEvent(event, sessionId) {
|
|
3267
|
+
if (event.operation === "invalidated") return memoryDomainEvents.memoryInvalidated({
|
|
3268
|
+
sessionId,
|
|
3269
|
+
memoryId: event.invalidated.id
|
|
3270
|
+
});
|
|
3271
|
+
return memoryDomainEvents.memoryUpserted({
|
|
3272
|
+
sessionId,
|
|
3273
|
+
memory: toMemory(event.memory)
|
|
3274
|
+
});
|
|
3275
|
+
}
|
|
3276
|
+
/**
|
|
3277
|
+
* Inserts or replaces a memory by id. A new memory is prepended (newest first,
|
|
3278
|
+
* matching the REST list's `created_at DESC` ordering without needing a date
|
|
3279
|
+
* field on the public projection); an existing memory is replaced in place.
|
|
3280
|
+
*/
|
|
3281
|
+
function upsertMemory(memories, memory) {
|
|
3282
|
+
const existingIndex = memories.findIndex((item) => item.id === memory.id);
|
|
3283
|
+
if (existingIndex === -1) return [memory, ...memories];
|
|
3284
|
+
const next = [...memories];
|
|
3285
|
+
next[existingIndex] = memory;
|
|
3286
|
+
return next;
|
|
3287
|
+
}
|
|
3288
|
+
const memoryReducer = createReducer(initialMemoryState, on(memoryAdapterEvents.contextChanged, (state, { context }) => ({
|
|
3289
|
+
...state,
|
|
3290
|
+
context,
|
|
3291
|
+
sessionId: state.sessionId + 1,
|
|
3292
|
+
memories: [],
|
|
3293
|
+
isLoading: Boolean(context),
|
|
3294
|
+
inFlightMutationCount: 0,
|
|
3295
|
+
error: null,
|
|
3296
|
+
available: true,
|
|
3297
|
+
realtimeStatus: "connecting"
|
|
3298
|
+
})), on(memoryAdapterEvents.stopped, (state) => ({
|
|
3299
|
+
...state,
|
|
3300
|
+
memories: [],
|
|
3301
|
+
isLoading: false,
|
|
3302
|
+
inFlightMutationCount: 0,
|
|
3303
|
+
error: null,
|
|
3304
|
+
available: true,
|
|
3305
|
+
realtimeStatus: "connecting"
|
|
3306
|
+
})), on(memoryRestEvents.listRequested, (state, { sessionId }) => {
|
|
3307
|
+
if (sessionId !== state.sessionId || !state.context) return state;
|
|
3308
|
+
return {
|
|
3309
|
+
...state,
|
|
3310
|
+
isLoading: true,
|
|
3311
|
+
error: null,
|
|
3312
|
+
available: true
|
|
3313
|
+
};
|
|
3314
|
+
}), on(memoryRestEvents.listFailed, (state, { sessionId, error }) => {
|
|
3315
|
+
if (sessionId !== state.sessionId) return state;
|
|
3316
|
+
return {
|
|
3317
|
+
...state,
|
|
3318
|
+
isLoading: false,
|
|
3319
|
+
error
|
|
3320
|
+
};
|
|
3321
|
+
}), on(memoryRestEvents.listUnavailable, (state, { sessionId }) => {
|
|
3322
|
+
if (sessionId !== state.sessionId) return state;
|
|
3323
|
+
return {
|
|
3324
|
+
...state,
|
|
3325
|
+
memories: [],
|
|
3326
|
+
isLoading: false,
|
|
3327
|
+
error: null,
|
|
3328
|
+
available: false
|
|
3329
|
+
};
|
|
3330
|
+
}), on(memoryAdapterEvents.addRequested, memoryAdapterEvents.updateRequested, memoryAdapterEvents.removeRequested, (state) => ({
|
|
3331
|
+
...state,
|
|
3332
|
+
inFlightMutationCount: state.inFlightMutationCount + 1
|
|
3333
|
+
})), on(memoryRestEvents.mutationFinished, (state, { outcome }) => {
|
|
3334
|
+
if (outcome.sessionId !== state.sessionId) return state;
|
|
3335
|
+
return {
|
|
3336
|
+
...state,
|
|
3337
|
+
inFlightMutationCount: Math.max(0, state.inFlightMutationCount - 1),
|
|
3338
|
+
error: outcome.ok ? null : outcome.error
|
|
3339
|
+
};
|
|
3340
|
+
}), on(memoryRestEvents.listSucceeded, (state, { sessionId, memories }) => {
|
|
3341
|
+
if (sessionId !== state.sessionId) return state;
|
|
3342
|
+
return {
|
|
3343
|
+
...state,
|
|
3344
|
+
memories,
|
|
3345
|
+
isLoading: false,
|
|
3346
|
+
error: null,
|
|
3347
|
+
available: true
|
|
3348
|
+
};
|
|
3349
|
+
}), on(memoryDomainEvents.memoryUpserted, (state, { sessionId, memory }) => {
|
|
3350
|
+
if (sessionId !== state.sessionId) return state;
|
|
3351
|
+
return {
|
|
3352
|
+
...state,
|
|
3353
|
+
memories: upsertMemory(state.memories, memory)
|
|
3354
|
+
};
|
|
3355
|
+
}), on(memoryDomainEvents.memoryInvalidated, (state, { sessionId, memoryId }) => {
|
|
3356
|
+
if (sessionId !== state.sessionId) return state;
|
|
3357
|
+
return {
|
|
3358
|
+
...state,
|
|
3359
|
+
memories: state.memories.filter((memory) => memory.id !== memoryId)
|
|
3360
|
+
};
|
|
3361
|
+
}), on(memoryDomainEvents.realtimeConnecting, (state, { sessionId }) => {
|
|
3362
|
+
if (sessionId !== state.sessionId) return state;
|
|
3363
|
+
return {
|
|
3364
|
+
...state,
|
|
3365
|
+
realtimeStatus: "connecting"
|
|
3366
|
+
};
|
|
3367
|
+
}), on(memoryDomainEvents.realtimeConnected, (state, { sessionId }) => {
|
|
3368
|
+
if (sessionId !== state.sessionId) return state;
|
|
3369
|
+
return {
|
|
3370
|
+
...state,
|
|
3371
|
+
realtimeStatus: "connected"
|
|
3372
|
+
};
|
|
3373
|
+
}), on(memoryDomainEvents.realtimeUnavailable, (state, { sessionId }) => {
|
|
3374
|
+
if (sessionId !== state.sessionId) return state;
|
|
3375
|
+
return {
|
|
3376
|
+
...state,
|
|
3377
|
+
realtimeStatus: "unavailable"
|
|
3378
|
+
};
|
|
3379
|
+
}));
|
|
3380
|
+
const selectMemories = createSelector((state) => state.memories);
|
|
3381
|
+
const selectMemoriesIsLoading = createSelector((state) => state.isLoading);
|
|
3382
|
+
const selectMemoriesError = createSelector((state) => state.error);
|
|
3383
|
+
/**
|
|
3384
|
+
* Reports whether at least one mutation is in flight. Derived from
|
|
3385
|
+
* `inFlightMutationCount` so concurrent mutations stay correct: the boolean
|
|
3386
|
+
* only clears once every in-flight mutation has settled.
|
|
3387
|
+
*/
|
|
3388
|
+
const selectMemoriesIsMutating = createSelector((state) => state.inFlightMutationCount > 0);
|
|
3389
|
+
/**
|
|
3390
|
+
* Reports whether the memory routes are available. Becomes `false` after a
|
|
3391
|
+
* 404, 422 (the runtime's MISSING_INTELLIGENCE signal), or 501 response during
|
|
3392
|
+
* an auto-activation read; defaults to `true`.
|
|
3393
|
+
*/
|
|
3394
|
+
const selectMemoriesAvailable = createSelector((state) => state.available);
|
|
3395
|
+
/**
|
|
3396
|
+
* Reports the realtime-connection health (see {@link MemoryRealtimeStatus}).
|
|
3397
|
+
* Distinct from `available`/`error`: it reflects ONLY the live socket/channel,
|
|
3398
|
+
* so the UI can suppress a "live" indicator once realtime permanently dies even
|
|
3399
|
+
* while the REST list route stays healthy. Defaults to `"connecting"`.
|
|
3400
|
+
*/
|
|
3401
|
+
const selectMemoriesRealtimeStatus = createSelector((state) => state.realtimeStatus);
|
|
3402
|
+
const MEMORY_METADATA_EVENT = "memory_metadata";
|
|
3403
|
+
function memoryFromFetch(input, init) {
|
|
3404
|
+
return (0, rxjs_fetch.fromFetch)(input, init);
|
|
3405
|
+
}
|
|
3406
|
+
/**
|
|
3407
|
+
* Fetches the memory snapshot and maps it to a success/failure action. Keeps
|
|
3408
|
+
* only user-scoped memories (v1 surfaces user scope only; the realtime stream
|
|
3409
|
+
* is user-scoped too), so project-scoped rows visible to the caller are
|
|
3410
|
+
* dropped from the store.
|
|
3411
|
+
*/
|
|
3412
|
+
function createMemoryFetchObservable(environment, context, sessionId) {
|
|
3413
|
+
return (0, rxjs.defer)(() => {
|
|
3414
|
+
const qs = context.includeInvalidated ? "?includeInvalidated=true" : "";
|
|
3415
|
+
return memoryFromFetch(`${context.runtimeUrl}${MEMORIES_PATH}${qs}`, {
|
|
3416
|
+
selector: (response) => {
|
|
3417
|
+
if (!response.ok) {
|
|
3418
|
+
if (ROUTE_UNAVAILABLE_STATUSES.has(response.status)) throw new MemoryRouteUnavailableError(String(response.status));
|
|
3419
|
+
throw new MemoryError("MEMORY_LIST_FAILED", {
|
|
3420
|
+
message: `Failed to fetch memories: ${response.status}`,
|
|
3421
|
+
retryable: isRetryableStatus(response.status)
|
|
3422
|
+
});
|
|
3423
|
+
}
|
|
3424
|
+
return response.json();
|
|
3425
|
+
},
|
|
3426
|
+
fetch: environment.fetch,
|
|
3427
|
+
method: "GET",
|
|
3428
|
+
headers: { ...context.headers }
|
|
3429
|
+
}).pipe((0, rxjs_operators.timeout)({
|
|
3430
|
+
first: REQUEST_TIMEOUT_MS$1,
|
|
3431
|
+
with: () => {
|
|
3432
|
+
throw new MemoryError("MEMORY_REQUEST_TIMEOUT");
|
|
3433
|
+
}
|
|
3434
|
+
}), (0, rxjs_operators.map)((data) => memoryRestEvents.listSucceeded({
|
|
3435
|
+
sessionId,
|
|
3436
|
+
memories: data.memories.filter((memory) => memory.scope === "user")
|
|
3437
|
+
})), (0, rxjs_operators.catchError)((error) => {
|
|
3438
|
+
if (error instanceof MemoryRouteUnavailableError) return (0, rxjs.of)(memoryRestEvents.listUnavailable({ sessionId }));
|
|
3439
|
+
return (0, rxjs.of)(memoryRestEvents.listFailed({
|
|
3440
|
+
sessionId,
|
|
3441
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
3442
|
+
}));
|
|
3443
|
+
}));
|
|
3444
|
+
});
|
|
3445
|
+
}
|
|
3446
|
+
/**
|
|
3447
|
+
* Fetches join credentials from the `/memories/subscribe` endpoint and maps
|
|
3448
|
+
* the response to a success/failure action. Requires both `joinToken` and
|
|
3449
|
+
* `joinCode` to be non-empty strings; throws otherwise so the `catchError`
|
|
3450
|
+
* path emits `credentialsFailed`.
|
|
3451
|
+
*/
|
|
3452
|
+
function createMemoryCredentialsFetchObservable(environment, context, sessionId) {
|
|
3453
|
+
return (0, rxjs.defer)(() => memoryFromFetch(`${context.runtimeUrl}${MEMORIES_SUBSCRIBE_PATH}`, {
|
|
3454
|
+
selector: async (response) => {
|
|
3455
|
+
if (!response.ok) {
|
|
3456
|
+
if (ROUTE_UNAVAILABLE_STATUSES.has(response.status)) throw new MemoryRouteUnavailableError(String(response.status));
|
|
3457
|
+
throw new MemoryError("MEMORY_CREDENTIALS_FAILED", {
|
|
3458
|
+
message: `Failed to fetch memory subscribe credentials: ${response.status}`,
|
|
3459
|
+
retryable: isRetryableStatus(response.status)
|
|
3460
|
+
});
|
|
3461
|
+
}
|
|
3462
|
+
return response.json();
|
|
3463
|
+
},
|
|
3464
|
+
fetch: environment.fetch,
|
|
3465
|
+
method: "POST",
|
|
3466
|
+
headers: {
|
|
3467
|
+
...context.headers,
|
|
3468
|
+
"Content-Type": "application/json"
|
|
3469
|
+
},
|
|
3470
|
+
body: JSON.stringify({})
|
|
3471
|
+
}).pipe((0, rxjs_operators.timeout)({
|
|
3472
|
+
first: REQUEST_TIMEOUT_MS$1,
|
|
3473
|
+
with: () => {
|
|
3474
|
+
throw new MemoryError("MEMORY_REQUEST_TIMEOUT");
|
|
3475
|
+
}
|
|
3476
|
+
}), (0, rxjs_operators.map)((data) => {
|
|
3477
|
+
if (typeof data.joinToken !== "string" || data.joinToken.length === 0) throw new Error("missing joinToken");
|
|
3478
|
+
if (typeof data.joinCode !== "string" || data.joinCode.length === 0) throw new Error("missing joinCode");
|
|
3479
|
+
return memoryRestEvents.credentialsSucceeded({
|
|
3480
|
+
sessionId,
|
|
3481
|
+
joinToken: data.joinToken,
|
|
3482
|
+
joinCode: data.joinCode
|
|
3483
|
+
});
|
|
3484
|
+
}), (0, rxjs_operators.catchError)((error) => {
|
|
3485
|
+
if (error instanceof MemoryRouteUnavailableError) return (0, rxjs.of)(memoryRestEvents.credentialsUnavailable({ sessionId }));
|
|
3486
|
+
return (0, rxjs.of)(memoryRestEvents.credentialsFailed({
|
|
3487
|
+
sessionId,
|
|
3488
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
3489
|
+
}));
|
|
3490
|
+
})));
|
|
3491
|
+
}
|
|
3492
|
+
/** Projects a REST mutation response to the public {@link Memory} shape. */
|
|
3493
|
+
function responseToMemory(data) {
|
|
3494
|
+
return {
|
|
3495
|
+
id: data.id,
|
|
3496
|
+
kind: data.kind,
|
|
3497
|
+
scope: data.scope,
|
|
3498
|
+
content: data.content,
|
|
3499
|
+
sourceThreadIds: data.sourceThreadIds,
|
|
3500
|
+
invalidatedAt: data.invalidatedAt
|
|
3501
|
+
};
|
|
3502
|
+
}
|
|
3503
|
+
const MEMORY_KINDS = new Set([
|
|
3504
|
+
"topical",
|
|
3505
|
+
"episodic",
|
|
3506
|
+
"operational"
|
|
3507
|
+
]);
|
|
3508
|
+
const MEMORY_SCOPES = new Set(["user", "project"]);
|
|
3509
|
+
/**
|
|
3510
|
+
* Validates the required fields of a create/supersede REST response before it is
|
|
3511
|
+
* projected to a {@link Memory}. Returns an `Error` describing the first
|
|
3512
|
+
* missing/invalid field, or `null` when the body is well-formed. Without this a
|
|
3513
|
+
* malformed 200 body yields a Memory with undefined fields that gets upserted.
|
|
3514
|
+
*/
|
|
3515
|
+
function validateMutationResponse(data) {
|
|
3516
|
+
if (!data || typeof data !== "object") return /* @__PURE__ */ new Error("memory mutation response missing/invalid body");
|
|
3517
|
+
if (typeof data.id !== "string" || data.id.length === 0) return /* @__PURE__ */ new Error("memory mutation response missing/invalid id");
|
|
3518
|
+
if (typeof data.kind !== "string" || !MEMORY_KINDS.has(data.kind)) return /* @__PURE__ */ new Error("memory mutation response missing/invalid kind");
|
|
3519
|
+
if (typeof data.scope !== "string" || !MEMORY_SCOPES.has(data.scope)) return /* @__PURE__ */ new Error("memory mutation response missing/invalid scope");
|
|
3520
|
+
if (typeof data.content !== "string") return /* @__PURE__ */ new Error("memory mutation response missing/invalid content");
|
|
3521
|
+
if (!Array.isArray(data.sourceThreadIds) || !data.sourceThreadIds.every((id) => typeof id === "string")) return /* @__PURE__ */ new Error("memory mutation response missing/invalid sourceThreadIds");
|
|
3522
|
+
if (data.invalidatedAt !== null && typeof data.invalidatedAt !== "string") return /* @__PURE__ */ new Error("memory mutation response missing/invalid invalidatedAt");
|
|
3523
|
+
return null;
|
|
3524
|
+
}
|
|
3525
|
+
/**
|
|
3526
|
+
* Request body for create/supersede. `scope` is forwarded only when the caller
|
|
3527
|
+
* supplies it: the platform owns the default (`scope` defaults to `"user"` in
|
|
3528
|
+
* the `/api/memories` schema), so the store does not second-guess it here —
|
|
3529
|
+
* one default, at the contract owner. `sourceThreadIds` defaults to `[]`.
|
|
3530
|
+
*/
|
|
3531
|
+
function toMutationBody(input) {
|
|
3532
|
+
var _input$sourceThreadId;
|
|
3533
|
+
return {
|
|
3534
|
+
content: input.content,
|
|
3535
|
+
kind: input.kind,
|
|
3536
|
+
...input.scope !== void 0 ? { scope: input.scope } : {},
|
|
3537
|
+
sourceThreadIds: (_input$sourceThreadId = input.sourceThreadIds) !== null && _input$sourceThreadId !== void 0 ? _input$sourceThreadId : []
|
|
3538
|
+
};
|
|
3539
|
+
}
|
|
3540
|
+
/**
|
|
3541
|
+
* Builds the actions a successful mutation dispatches (server-authoritative):
|
|
3542
|
+
* the REST response is applied to local state immediately, and the realtime
|
|
3543
|
+
* event reconciles idempotently (upsert-by-id). `mutationFinished` resolves the
|
|
3544
|
+
* caller's promise.
|
|
3545
|
+
*/
|
|
3546
|
+
function buildMutationSuccessActions(request, data) {
|
|
3547
|
+
const { requestId, sessionId } = request;
|
|
3548
|
+
if (request.kind === "remove") return [memoryDomainEvents.memoryInvalidated({
|
|
3549
|
+
sessionId,
|
|
3550
|
+
memoryId: request.id
|
|
3551
|
+
}), memoryRestEvents.mutationFinished({ outcome: {
|
|
3552
|
+
requestId,
|
|
3553
|
+
sessionId,
|
|
3554
|
+
ok: true,
|
|
3555
|
+
memory: null
|
|
3556
|
+
} })];
|
|
3557
|
+
const validationError = validateMutationResponse(data);
|
|
3558
|
+
if (validationError) return [memoryRestEvents.mutationFinished({ outcome: {
|
|
3559
|
+
requestId,
|
|
3560
|
+
sessionId,
|
|
3561
|
+
ok: false,
|
|
3562
|
+
error: validationError
|
|
3563
|
+
} })];
|
|
3564
|
+
const memory = responseToMemory(data);
|
|
3565
|
+
if (request.kind === "update") {
|
|
3566
|
+
const retiredId = data.retiredId;
|
|
3567
|
+
if (typeof retiredId !== "string" || retiredId.length === 0) return [memoryRestEvents.mutationFinished({ outcome: {
|
|
3568
|
+
requestId,
|
|
3569
|
+
sessionId,
|
|
3570
|
+
ok: false,
|
|
3571
|
+
error: /* @__PURE__ */ new Error("supersede response missing retiredId")
|
|
3572
|
+
} })];
|
|
3573
|
+
return [
|
|
3574
|
+
memoryDomainEvents.memoryInvalidated({
|
|
3575
|
+
sessionId,
|
|
3576
|
+
memoryId: retiredId
|
|
3577
|
+
}),
|
|
3578
|
+
memoryDomainEvents.memoryUpserted({
|
|
3579
|
+
sessionId,
|
|
3580
|
+
memory
|
|
3581
|
+
}),
|
|
3582
|
+
memoryRestEvents.mutationFinished({ outcome: {
|
|
3583
|
+
requestId,
|
|
3584
|
+
sessionId,
|
|
3585
|
+
ok: true,
|
|
3586
|
+
memory
|
|
3587
|
+
} })
|
|
3588
|
+
];
|
|
3589
|
+
}
|
|
3590
|
+
return [memoryDomainEvents.memoryUpserted({
|
|
3591
|
+
sessionId,
|
|
3592
|
+
memory
|
|
3593
|
+
}), memoryRestEvents.mutationFinished({ outcome: {
|
|
3594
|
+
requestId,
|
|
3595
|
+
sessionId,
|
|
3596
|
+
ok: true,
|
|
3597
|
+
memory
|
|
3598
|
+
} })];
|
|
3599
|
+
}
|
|
3600
|
+
/** Performs a create/supersede/retire HTTP call and emits its resulting actions. */
|
|
3601
|
+
function createMemoryMutationObservable(environment, context, request) {
|
|
3602
|
+
const method = request.kind === "add" ? "POST" : request.kind === "update" ? "PATCH" : "DELETE";
|
|
3603
|
+
const path = request.kind === "add" ? MEMORIES_PATH : `${MEMORIES_PATH}/${encodeURIComponent(request.id)}`;
|
|
3604
|
+
return (0, rxjs.defer)(() => memoryFromFetch(`${context.runtimeUrl}${path}`, {
|
|
3605
|
+
selector: async (response) => {
|
|
3606
|
+
if (!response.ok) throw new MemoryError("MEMORY_MUTATION_FAILED", {
|
|
3607
|
+
message: `Request failed: ${response.status}`,
|
|
3608
|
+
retryable: isRetryableStatus(response.status)
|
|
3609
|
+
});
|
|
3610
|
+
return request.kind === "remove" ? null : await response.json();
|
|
3611
|
+
},
|
|
3612
|
+
fetch: environment.fetch,
|
|
3613
|
+
method,
|
|
3614
|
+
headers: {
|
|
3615
|
+
...context.headers,
|
|
3616
|
+
"Content-Type": "application/json"
|
|
3617
|
+
},
|
|
3618
|
+
body: request.kind === "remove" ? void 0 : JSON.stringify(request.body)
|
|
3619
|
+
}).pipe((0, rxjs_operators.timeout)({
|
|
3620
|
+
first: REQUEST_TIMEOUT_MS$1,
|
|
3621
|
+
with: () => {
|
|
3622
|
+
throw new MemoryError("MEMORY_REQUEST_TIMEOUT");
|
|
3623
|
+
}
|
|
3624
|
+
}), (0, rxjs_operators.mergeMap)((data) => (0, rxjs.of)(...buildMutationSuccessActions(request, data))), (0, rxjs_operators.catchError)((error) => (0, rxjs.of)(memoryRestEvents.mutationFinished({ outcome: {
|
|
3625
|
+
requestId: request.requestId,
|
|
3626
|
+
sessionId: request.sessionId,
|
|
3627
|
+
ok: false,
|
|
3628
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
3629
|
+
} })))));
|
|
3630
|
+
}
|
|
3631
|
+
/**
|
|
3632
|
+
* Creates the framework-agnostic memory store: a REST snapshot on `setContext`,
|
|
3633
|
+
* server-authoritative add/update/remove mutations, and realtime
|
|
3634
|
+
* `memory_metadata` deltas off the injected `user_meta` event source — all
|
|
3635
|
+
* reduced into observable state.
|
|
3636
|
+
*/
|
|
3637
|
+
function createMemoryStore(environment) {
|
|
3638
|
+
let memoryRequestId = 0;
|
|
3639
|
+
const createMemoryRequestId = () => {
|
|
3640
|
+
memoryRequestId += 1;
|
|
3641
|
+
return `memory-request-${memoryRequestId}`;
|
|
3642
|
+
};
|
|
3643
|
+
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 }))));
|
|
3644
|
+
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 }))));
|
|
3645
|
+
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) => ({
|
|
3646
|
+
action,
|
|
3647
|
+
context
|
|
3648
|
+
})), (0, rxjs_operators.takeUntil)(actions$.pipe(ofType(memoryAdapterEvents.contextChanged, memoryAdapterEvents.stopped))), (0, rxjs_operators.switchMap)(({ action: currentAction, context }) => createMemoryCredentialsFetchObservable(environment, context, currentAction.sessionId))))));
|
|
3649
|
+
const store = createStore({
|
|
3650
|
+
reducer: memoryReducer,
|
|
3651
|
+
effects: [
|
|
3652
|
+
bootstrapEffect,
|
|
3653
|
+
credentialsBootstrapEffect,
|
|
3654
|
+
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) => ({
|
|
3655
|
+
action,
|
|
3656
|
+
context
|
|
3657
|
+
})), (0, rxjs_operators.takeUntil)(actions$.pipe(ofType(memoryAdapterEvents.contextChanged, memoryAdapterEvents.stopped))), (0, rxjs_operators.switchMap)(({ action: currentAction, context }) => createMemoryFetchObservable(environment, context, currentAction.sessionId)))))),
|
|
3658
|
+
credentialsFetchEffect,
|
|
3659
|
+
createEffect((actions$, state$) => actions$.pipe(ofType(memoryAdapterEvents.addRequested, memoryAdapterEvents.updateRequested, memoryAdapterEvents.removeRequested), (0, rxjs_operators.withLatestFrom)(state$), (0, rxjs_operators.mergeMap)(([action, state]) => {
|
|
3660
|
+
const context = state.context;
|
|
3661
|
+
const sessionId = state.sessionId;
|
|
3662
|
+
if (!(context === null || context === void 0 ? void 0 : context.runtimeUrl)) return (0, rxjs.of)(memoryRestEvents.mutationFinished({ outcome: {
|
|
3663
|
+
requestId: action.requestId,
|
|
3664
|
+
sessionId,
|
|
3665
|
+
ok: false,
|
|
3666
|
+
error: /* @__PURE__ */ new Error("Runtime URL is not configured")
|
|
3667
|
+
} }));
|
|
3668
|
+
if (memoryAdapterEvents.addRequested.match(action)) return createMemoryMutationObservable(environment, context, {
|
|
3669
|
+
requestId: action.requestId,
|
|
3670
|
+
sessionId,
|
|
3671
|
+
kind: "add",
|
|
3672
|
+
body: toMutationBody(action.input)
|
|
3673
|
+
});
|
|
3674
|
+
if (memoryAdapterEvents.updateRequested.match(action)) return createMemoryMutationObservable(environment, context, {
|
|
3675
|
+
requestId: action.requestId,
|
|
3676
|
+
sessionId,
|
|
3677
|
+
kind: "update",
|
|
3678
|
+
id: action.id,
|
|
3679
|
+
body: toMutationBody(action.changes)
|
|
3680
|
+
});
|
|
3681
|
+
return createMemoryMutationObservable(environment, context, {
|
|
3682
|
+
requestId: action.requestId,
|
|
3683
|
+
sessionId,
|
|
3684
|
+
kind: "remove",
|
|
3685
|
+
id: action.id
|
|
3686
|
+
});
|
|
3687
|
+
}))),
|
|
3688
|
+
createEffect((actions$, state$) => actions$.pipe(ofType(memoryRestEvents.credentialsSucceeded), (0, rxjs_operators.withLatestFrom)(state$), (0, rxjs_operators.filter)(([action, state]) => {
|
|
3689
|
+
var _state$context;
|
|
3690
|
+
return action.sessionId === state.sessionId && Boolean((_state$context = state.context) === null || _state$context === void 0 ? void 0 : _state$context.wsUrl);
|
|
3691
|
+
}), (0, rxjs_operators.switchMap)(([action, state]) => {
|
|
3692
|
+
const context = state.context;
|
|
3693
|
+
const { joinToken, joinCode } = action;
|
|
3694
|
+
const sessionId = action.sessionId;
|
|
3695
|
+
const shutdown$ = actions$.pipe(ofType(memoryAdapterEvents.contextChanged, memoryAdapterEvents.stopped));
|
|
3696
|
+
return (0, rxjs.defer)(() => {
|
|
3697
|
+
const socket$ = ɵphoenixSocket$({
|
|
3698
|
+
url: context.wsUrl,
|
|
3699
|
+
options: {
|
|
3700
|
+
params: { join_token: joinToken },
|
|
3701
|
+
reconnectAfterMs: (0, _copilotkit_shared.phoenixExponentialBackoff)(100, 1e4),
|
|
3702
|
+
rejoinAfterMs: (0, _copilotkit_shared.phoenixExponentialBackoff)(1e3, 3e4)
|
|
3703
|
+
}
|
|
3704
|
+
}).pipe((0, rxjs_operators.shareReplay)({
|
|
3705
|
+
bufferSize: 1,
|
|
3706
|
+
refCount: true
|
|
3707
|
+
}));
|
|
3708
|
+
const channel$ = ɵphoenixChannel$({
|
|
3709
|
+
socket$,
|
|
3710
|
+
topic: `user_meta:memories:${joinCode}`
|
|
3711
|
+
}).pipe((0, rxjs_operators.shareReplay)({
|
|
3712
|
+
bufferSize: 1,
|
|
3713
|
+
refCount: true
|
|
3714
|
+
}));
|
|
3715
|
+
const fatalSocketShutdown$ = ɵobservePhoenixSocketHealth$(ɵobservePhoenixSocketSignals$(socket$).pipe((0, rxjs_operators.share)()), MAX_SOCKET_RETRIES$1).pipe((0, rxjs_operators.catchError)(() => {
|
|
3716
|
+
console.warn(`[memory] WebSocket failed after ${MAX_SOCKET_RETRIES$1} attempts, giving up`);
|
|
3717
|
+
return (0, rxjs.of)(void 0);
|
|
3718
|
+
}), (0, rxjs_operators.share)());
|
|
3719
|
+
const fatalStatus$ = fatalSocketShutdown$.pipe((0, rxjs_operators.map)(() => memoryDomainEvents.realtimeUnavailable({ sessionId })));
|
|
3720
|
+
const metadata$ = channel$.pipe((0, rxjs_operators.switchMap)(({ channel }) => ɵobservePhoenixEvent$(channel, MEMORY_METADATA_EVENT)), (0, rxjs_operators.map)((event) => mapMemoryMetadataEvent(event, action.sessionId)));
|
|
3721
|
+
const join$ = ɵjoinPhoenixChannel$(channel$).pipe((0, rxjs_operators.concatWith)((0, rxjs.of)(memoryDomainEvents.realtimeConnected({ sessionId }))), (0, rxjs_operators.catchError)((error) => {
|
|
3722
|
+
console.warn(`[memory] failed to join user_meta:memories:${joinCode}`, error);
|
|
3723
|
+
return (0, rxjs.of)(memoryDomainEvents.realtimeUnavailable({ sessionId }));
|
|
3724
|
+
}));
|
|
3725
|
+
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)(() => {}));
|
|
3726
|
+
});
|
|
3727
|
+
})))
|
|
3728
|
+
]
|
|
3729
|
+
});
|
|
3730
|
+
function trackMutation(dispatchAction, extract) {
|
|
3731
|
+
const { requestId } = dispatchAction;
|
|
3732
|
+
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)(() => ({
|
|
3733
|
+
requestId,
|
|
3734
|
+
sessionId: store.getState().sessionId,
|
|
3735
|
+
ok: false,
|
|
3736
|
+
error: /* @__PURE__ */ new Error("Memory store stopped before mutation completed")
|
|
3737
|
+
})))).pipe((0, rxjs_operators.take)(1))).then((outcome) => {
|
|
3738
|
+
if (!outcome.ok) throw outcome.error;
|
|
3739
|
+
return extract(outcome);
|
|
3740
|
+
});
|
|
3741
|
+
store.dispatch(dispatchAction);
|
|
3742
|
+
return resultPromise;
|
|
3743
|
+
}
|
|
3744
|
+
return {
|
|
3745
|
+
start() {
|
|
3746
|
+
store.init();
|
|
3747
|
+
store.dispatch(memoryAdapterEvents.started());
|
|
3748
|
+
},
|
|
3749
|
+
stop() {
|
|
3750
|
+
store.dispatch(memoryAdapterEvents.stopped());
|
|
3751
|
+
store.stop();
|
|
3752
|
+
},
|
|
3753
|
+
setContext(context) {
|
|
3754
|
+
store.dispatch(memoryAdapterEvents.contextChanged({ context }));
|
|
3755
|
+
},
|
|
3756
|
+
refresh() {
|
|
3757
|
+
const { sessionId, context } = store.getState();
|
|
3758
|
+
if (!context) return Promise.resolve();
|
|
3759
|
+
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) => {
|
|
3760
|
+
if (memoryRestEvents.listFailed.match(action)) throw action.error;
|
|
3761
|
+
if (memoryAdapterEvents.stopped.match(action)) throw new Error("Memory store stopped before refresh completed");
|
|
3762
|
+
if (memoryAdapterEvents.contextChanged.match(action)) return;
|
|
3763
|
+
});
|
|
3764
|
+
store.dispatch(memoryRestEvents.listRequested({ sessionId }));
|
|
3765
|
+
return done;
|
|
3766
|
+
},
|
|
3767
|
+
addMemory(input) {
|
|
3768
|
+
return trackMutation(memoryAdapterEvents.addRequested({
|
|
3769
|
+
requestId: createMemoryRequestId(),
|
|
3770
|
+
input
|
|
3771
|
+
}), (outcome) => {
|
|
3772
|
+
if (outcome.memory == null) throw new Error("add resolved without a memory");
|
|
3773
|
+
return outcome.memory;
|
|
3774
|
+
});
|
|
3775
|
+
},
|
|
3776
|
+
updateMemory(id, changes) {
|
|
3777
|
+
return trackMutation(memoryAdapterEvents.updateRequested({
|
|
3778
|
+
requestId: createMemoryRequestId(),
|
|
3779
|
+
id,
|
|
3780
|
+
changes
|
|
3781
|
+
}), (outcome) => {
|
|
3782
|
+
if (outcome.memory == null) throw new Error("update resolved without a memory");
|
|
3783
|
+
return outcome.memory;
|
|
3784
|
+
});
|
|
3785
|
+
},
|
|
3786
|
+
removeMemory(id) {
|
|
3787
|
+
return trackMutation(memoryAdapterEvents.removeRequested({
|
|
3788
|
+
requestId: createMemoryRequestId(),
|
|
3789
|
+
id
|
|
3790
|
+
}), () => void 0);
|
|
3791
|
+
},
|
|
3792
|
+
getState() {
|
|
3793
|
+
return store.getState();
|
|
3794
|
+
},
|
|
3795
|
+
getServerState() {
|
|
3796
|
+
return initialMemoryState;
|
|
3797
|
+
},
|
|
3798
|
+
select: store.select.bind(store)
|
|
3799
|
+
};
|
|
3800
|
+
}
|
|
3801
|
+
const ɵmemoryAdapterEvents = memoryAdapterEvents;
|
|
3802
|
+
const ɵmemoryRestEvents = memoryRestEvents;
|
|
3803
|
+
const ɵmemoryDomainEvents = memoryDomainEvents;
|
|
3804
|
+
const ɵmemoryReducer = memoryReducer;
|
|
3805
|
+
const ɵmapMemoryMetadataEvent = mapMemoryMetadataEvent;
|
|
3806
|
+
const ɵselectMemories = selectMemories;
|
|
3807
|
+
const ɵselectMemoriesIsLoading = selectMemoriesIsLoading;
|
|
3808
|
+
const ɵselectMemoriesError = selectMemoriesError;
|
|
3809
|
+
const ɵselectMemoriesIsMutating = selectMemoriesIsMutating;
|
|
3810
|
+
const ɵselectMemoriesAvailable = selectMemoriesAvailable;
|
|
3811
|
+
const ɵselectMemoriesRealtimeStatus = selectMemoriesRealtimeStatus;
|
|
3812
|
+
|
|
3813
|
+
//#endregion
|
|
3814
|
+
//#region src/core/core.ts
|
|
3815
|
+
let CopilotKitCoreErrorCode = /* @__PURE__ */ function(CopilotKitCoreErrorCode) {
|
|
3816
|
+
CopilotKitCoreErrorCode["RUNTIME_INFO_FETCH_FAILED"] = "runtime_info_fetch_failed";
|
|
3817
|
+
CopilotKitCoreErrorCode["AGENT_CONNECT_FAILED"] = "agent_connect_failed";
|
|
3818
|
+
CopilotKitCoreErrorCode["AGENT_RUN_FAILED"] = "agent_run_failed";
|
|
3819
|
+
CopilotKitCoreErrorCode["AGENT_RUN_FAILED_EVENT"] = "agent_run_failed_event";
|
|
3820
|
+
CopilotKitCoreErrorCode["AGENT_RUN_ERROR_EVENT"] = "agent_run_error_event";
|
|
3821
|
+
CopilotKitCoreErrorCode["TOOL_ARGUMENT_PARSE_FAILED"] = "tool_argument_parse_failed";
|
|
3822
|
+
CopilotKitCoreErrorCode["TOOL_HANDLER_FAILED"] = "tool_handler_failed";
|
|
3823
|
+
CopilotKitCoreErrorCode["TOOL_NOT_FOUND"] = "tool_not_found";
|
|
3824
|
+
CopilotKitCoreErrorCode["AGENT_NOT_FOUND"] = "agent_not_found";
|
|
3825
|
+
/**
|
|
3826
|
+
* Emitted when an agent run fails because the thread is already locked
|
|
3827
|
+
* by another active run.
|
|
3828
|
+
*
|
|
3829
|
+
* @example
|
|
3830
|
+
* ```tsx
|
|
3831
|
+
* <CopilotKitProvider
|
|
3832
|
+
* onError={({ code, error, context }) => {
|
|
3833
|
+
* if (code === "agent_thread_locked") {
|
|
3834
|
+
* // Show "Agent is busy, retry?" UI
|
|
3835
|
+
* }
|
|
3836
|
+
* }}
|
|
3837
|
+
* />
|
|
3838
|
+
* ```
|
|
3839
|
+
*/
|
|
3840
|
+
CopilotKitCoreErrorCode["AGENT_THREAD_LOCKED"] = "agent_thread_locked";
|
|
3841
|
+
CopilotKitCoreErrorCode["TRANSCRIPTION_FAILED"] = "transcription_failed";
|
|
3842
|
+
CopilotKitCoreErrorCode["TRANSCRIPTION_SERVICE_NOT_CONFIGURED"] = "transcription_service_not_configured";
|
|
3843
|
+
CopilotKitCoreErrorCode["TRANSCRIPTION_INVALID_AUDIO"] = "transcription_invalid_audio";
|
|
3844
|
+
CopilotKitCoreErrorCode["TRANSCRIPTION_RATE_LIMITED"] = "transcription_rate_limited";
|
|
3845
|
+
CopilotKitCoreErrorCode["TRANSCRIPTION_AUTH_FAILED"] = "transcription_auth_failed";
|
|
3846
|
+
CopilotKitCoreErrorCode["TRANSCRIPTION_NETWORK_ERROR"] = "transcription_network_error";
|
|
3847
|
+
CopilotKitCoreErrorCode["SUBSCRIBER_CALLBACK_FAILED"] = "subscriber_callback_failed";
|
|
3848
|
+
return CopilotKitCoreErrorCode;
|
|
3849
|
+
}({});
|
|
3850
|
+
/**
|
|
3851
|
+
* Runtime allowlist derived from {@link SUBSCRIBE_TO_AGENT_KEYS}. Hoisted
|
|
3852
|
+
* to module scope so the Set is allocated once, not per-subscription.
|
|
3853
|
+
*/
|
|
3854
|
+
const ALLOWED_KEYS = new Set([
|
|
3855
|
+
"onMessagesChanged",
|
|
3856
|
+
"onStateChanged",
|
|
3857
|
+
"onRunInitialized",
|
|
3858
|
+
"onRunFinalized",
|
|
3859
|
+
"onRunFailed",
|
|
3860
|
+
"onRunErrorEvent"
|
|
3861
|
+
]);
|
|
3862
|
+
let CopilotKitCoreRuntimeConnectionStatus = /* @__PURE__ */ function(CopilotKitCoreRuntimeConnectionStatus) {
|
|
3863
|
+
CopilotKitCoreRuntimeConnectionStatus["Disconnected"] = "disconnected";
|
|
3864
|
+
CopilotKitCoreRuntimeConnectionStatus["Connected"] = "connected";
|
|
3865
|
+
CopilotKitCoreRuntimeConnectionStatus["Connecting"] = "connecting";
|
|
3866
|
+
CopilotKitCoreRuntimeConnectionStatus["Error"] = "error";
|
|
3867
|
+
return CopilotKitCoreRuntimeConnectionStatus;
|
|
3868
|
+
}({});
|
|
3869
|
+
/**
|
|
3870
|
+
* Normalize a header map to the internal invariant: a `Record<string, string>`
|
|
3871
|
+
* with no `null`/`undefined` values. Entries whose value is `null`/`undefined`
|
|
3872
|
+
* are dropped (this is how a header is cleared). Shared by the constructor and
|
|
3873
|
+
* `setHeaders` so both write paths into `_headers` enforce the same invariant.
|
|
3874
|
+
*/
|
|
3875
|
+
function normalizeHeaders(headers) {
|
|
3876
|
+
return Object.fromEntries(Object.entries(headers).filter((entry) => entry[1] != null));
|
|
3877
|
+
}
|
|
3878
|
+
var CopilotKitCore = class {
|
|
3879
|
+
constructor({ runtimeUrl, runtimeTransport = "auto", headers = {}, credentials, properties = {}, agents__unsafe_dev_only = {}, tools = [], suggestionsConfig = [], debug }) {
|
|
3880
|
+
_defineProperty(this, "_headers", void 0);
|
|
3881
|
+
_defineProperty(this, "_credentials", void 0);
|
|
3882
|
+
_defineProperty(this, "_properties", void 0);
|
|
3883
|
+
_defineProperty(this, "_defaultThrottleMs", void 0);
|
|
3884
|
+
_defineProperty(this, "_debug", void 0);
|
|
3885
|
+
_defineProperty(this, "subscribers", /* @__PURE__ */ new Set());
|
|
3886
|
+
_defineProperty(this, "agentRegistry", void 0);
|
|
3887
|
+
_defineProperty(this, "contextStore", void 0);
|
|
3888
|
+
_defineProperty(this, "suggestionEngine", void 0);
|
|
3889
|
+
_defineProperty(this, "runHandler", void 0);
|
|
3890
|
+
_defineProperty(this, "stateManager", void 0);
|
|
3891
|
+
_defineProperty(this, "subagentRegistry", void 0);
|
|
3892
|
+
_defineProperty(this, "threadStoreRegistry", void 0);
|
|
3893
|
+
_defineProperty(this, "_memoryStore", void 0);
|
|
3894
|
+
_defineProperty(this, "previousAgentIds", /* @__PURE__ */ new Set());
|
|
3895
|
+
this._headers = normalizeHeaders(headers);
|
|
3896
|
+
this._credentials = credentials;
|
|
3897
|
+
this._properties = properties;
|
|
3898
|
+
this._debug = debug;
|
|
3899
|
+
this.agentRegistry = new AgentRegistry(this);
|
|
3900
|
+
this.contextStore = new ContextStore(this);
|
|
3901
|
+
this.suggestionEngine = new SuggestionEngine(this);
|
|
3902
|
+
this.runHandler = new RunHandler(this);
|
|
3903
|
+
this.stateManager = new StateManager(this);
|
|
3904
|
+
this.subagentRegistry = new SubagentRegistry(this);
|
|
3905
|
+
this.threadStoreRegistry = new ThreadStoreRegistry(this);
|
|
3906
|
+
this.agentRegistry.initialize(agents__unsafe_dev_only);
|
|
3907
|
+
this.runHandler.initialize(tools);
|
|
3908
|
+
this.suggestionEngine.initialize(suggestionsConfig);
|
|
3909
|
+
this.stateManager.initialize();
|
|
3910
|
+
this.agentRegistry.setRuntimeTransport(runtimeTransport);
|
|
3911
|
+
this.agentRegistry.setRuntimeUrl(runtimeUrl);
|
|
3912
|
+
this.previousAgentIds = new Set(Object.keys(agents__unsafe_dev_only));
|
|
3913
|
+
this.subscribe({
|
|
3914
|
+
onRuntimeConnectionStatusChanged: () => {
|
|
3915
|
+
if (this._memoryStore) this.syncMemoryContext();
|
|
3916
|
+
},
|
|
3917
|
+
onAgentsChanged: ({ agents }) => {
|
|
3918
|
+
Object.values(agents).forEach((agent) => {
|
|
3919
|
+
if (agent.agentId) {
|
|
3920
|
+
this.stateManager.subscribeToAgent(agent);
|
|
3921
|
+
this.subagentRegistry.subscribeToAgent(agent);
|
|
3922
|
+
}
|
|
3923
|
+
});
|
|
3924
|
+
const currentAgentIds = new Set(Object.keys(agents));
|
|
3925
|
+
for (const agentId of Object.keys(this.threadStoreRegistry.getAll())) if (this.previousAgentIds.has(agentId) && !currentAgentIds.has(agentId)) try {
|
|
3926
|
+
this.threadStoreRegistry.unregister(agentId);
|
|
3927
|
+
} catch (err) {
|
|
3928
|
+
console.error(`CopilotKitCore.onAgentsChanged: threadStoreRegistry.unregister failed for "${agentId}":`, err);
|
|
3929
|
+
}
|
|
3930
|
+
for (const agentId of this.previousAgentIds) if (!currentAgentIds.has(agentId)) {
|
|
3931
|
+
try {
|
|
3932
|
+
this.stateManager.unsubscribeFromAgent(agentId);
|
|
3933
|
+
} catch (err) {
|
|
3934
|
+
console.error(`CopilotKitCore.onAgentsChanged: stateManager.unsubscribeFromAgent failed for "${agentId}":`, err);
|
|
3935
|
+
}
|
|
3936
|
+
try {
|
|
3937
|
+
this.subagentRegistry.unsubscribeFromAgent(agentId);
|
|
3938
|
+
} catch (err) {
|
|
3939
|
+
console.error(`CopilotKitCore.onAgentsChanged: subagentRegistry.unsubscribeFromAgent failed for "${agentId}":`, err);
|
|
3940
|
+
}
|
|
3941
|
+
}
|
|
3942
|
+
this.previousAgentIds = currentAgentIds;
|
|
3943
|
+
}
|
|
3944
|
+
});
|
|
3945
|
+
}
|
|
3946
|
+
/**
|
|
3947
|
+
* Internal method used by delegate classes and subclasses to notify subscribers
|
|
3948
|
+
*/
|
|
3949
|
+
async notifySubscribers(handler, errorMessage) {
|
|
3950
|
+
await Promise.all(Array.from(this.subscribers).map(async (subscriber) => {
|
|
3951
|
+
try {
|
|
3952
|
+
await handler(subscriber);
|
|
3953
|
+
} catch (error) {
|
|
3954
|
+
console.error(errorMessage, error);
|
|
3955
|
+
}
|
|
3956
|
+
}));
|
|
3957
|
+
}
|
|
3958
|
+
/**
|
|
3959
|
+
* Internal method used by delegate classes to emit errors
|
|
3960
|
+
*/
|
|
3961
|
+
async emitError({ error, code, context = {} }) {
|
|
3962
|
+
await this.notifySubscribers((subscriber) => {
|
|
3963
|
+
var _subscriber$onError;
|
|
3964
|
+
return (_subscriber$onError = subscriber.onError) === null || _subscriber$onError === void 0 ? void 0 : _subscriber$onError.call(subscriber, {
|
|
3965
|
+
copilotkit: this,
|
|
3966
|
+
error,
|
|
3967
|
+
code,
|
|
3968
|
+
context
|
|
3969
|
+
});
|
|
3970
|
+
}, "Subscriber onError error:");
|
|
3971
|
+
}
|
|
3972
|
+
/**
|
|
3973
|
+
* Log a message to the console and emit an error to subscribers.
|
|
3974
|
+
* Catches failures from `emitError` itself to prevent unhandled rejections.
|
|
3975
|
+
*/
|
|
3976
|
+
logAndEmitError(message, params, logLevel = "error") {
|
|
3977
|
+
console[logLevel](message, params.error);
|
|
3978
|
+
this.emitError(params).catch((emitErr) => {
|
|
3979
|
+
console.error(message + " — emitError itself failed:", emitErr);
|
|
3980
|
+
});
|
|
3981
|
+
}
|
|
3982
|
+
/**
|
|
3983
|
+
* Snapshot accessors
|
|
3984
|
+
*/
|
|
3985
|
+
get context() {
|
|
3986
|
+
return this.contextStore.context;
|
|
3987
|
+
}
|
|
3988
|
+
get agents() {
|
|
3989
|
+
return this.agentRegistry.agents;
|
|
3990
|
+
}
|
|
3991
|
+
get tools() {
|
|
3992
|
+
return this.runHandler.tools;
|
|
3993
|
+
}
|
|
3994
|
+
get runtimeUrl() {
|
|
3995
|
+
return this.agentRegistry.runtimeUrl;
|
|
3996
|
+
}
|
|
3997
|
+
setRuntimeUrl(runtimeUrl) {
|
|
3998
|
+
this.agentRegistry.setRuntimeUrl(runtimeUrl);
|
|
3999
|
+
}
|
|
4000
|
+
get runtimeTransport() {
|
|
4001
|
+
return this.agentRegistry.runtimeTransport;
|
|
4002
|
+
}
|
|
4003
|
+
setRuntimeTransport(runtimeTransport) {
|
|
4004
|
+
this.agentRegistry.setRuntimeTransport(runtimeTransport);
|
|
4005
|
+
}
|
|
4006
|
+
get runtimeVersion() {
|
|
4007
|
+
return this.agentRegistry.runtimeVersion;
|
|
4008
|
+
}
|
|
4009
|
+
get headers() {
|
|
4010
|
+
return this._headers;
|
|
4011
|
+
}
|
|
4012
|
+
get credentials() {
|
|
4013
|
+
return this._credentials;
|
|
4014
|
+
}
|
|
4015
|
+
get properties() {
|
|
4016
|
+
return this._properties;
|
|
4017
|
+
}
|
|
4018
|
+
/**
|
|
4019
|
+
* Default throttle interval (ms) used by `subscribeToAgentWithOptions()`
|
|
4020
|
+
* when the caller does not specify an explicit `throttleMs`.
|
|
4021
|
+
* `undefined` means no default is configured; `0` means no throttling.
|
|
4022
|
+
*/
|
|
4023
|
+
get defaultThrottleMs() {
|
|
4024
|
+
return this._defaultThrottleMs;
|
|
4025
|
+
}
|
|
4026
|
+
/**
|
|
4027
|
+
* Set the default throttle interval (ms) for `subscribeToAgentWithOptions()`.
|
|
4028
|
+
*
|
|
4029
|
+
* Accepts a non-negative finite number or `undefined` (to clear the
|
|
4030
|
+
* default). Invalid values (NaN, Infinity, negative) are logged as
|
|
4031
|
+
* errors and ignored — the previous valid value is preserved.
|
|
2868
4032
|
*/
|
|
2869
4033
|
setDefaultThrottleMs(value) {
|
|
2870
4034
|
if (value !== void 0 && (!Number.isFinite(value) || value < 0)) {
|
|
@@ -2954,6 +4118,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
2954
4118
|
*/
|
|
2955
4119
|
setHeaders(headers) {
|
|
2956
4120
|
this._headers = normalizeHeaders(headers);
|
|
4121
|
+
if (this._memoryStore) this.syncMemoryContext();
|
|
2957
4122
|
this.agentRegistry.applyHeadersToAgents(this.agentRegistry.agents);
|
|
2958
4123
|
this.notifySubscribers((subscriber) => {
|
|
2959
4124
|
var _subscriber$onHeaders;
|
|
@@ -3065,6 +4230,47 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
3065
4230
|
return this.threadStoreRegistry.getAll();
|
|
3066
4231
|
}
|
|
3067
4232
|
/**
|
|
4233
|
+
* Returns the single core-owned, user-scoped memory store, creating and
|
|
4234
|
+
* starting it on first access. Unlike thread stores, memory is not scoped per
|
|
4235
|
+
* agent: there is exactly one store whose runtime context the core wires
|
|
4236
|
+
* itself (see `syncMemoryContext`), so consumers (e.g. a `useMemories`
|
|
4237
|
+
* binding) just read this store rather than registering one.
|
|
4238
|
+
*/
|
|
4239
|
+
getMemoryStore() {
|
|
4240
|
+
return this.ensureMemoryStore();
|
|
4241
|
+
}
|
|
4242
|
+
/**
|
|
4243
|
+
* Lazily creates, starts, and context-syncs the core-owned memory store on
|
|
4244
|
+
* first access, then returns it. Subsequent calls return the existing store.
|
|
4245
|
+
* The store is constructed with a bound `globalThis.fetch` and immediately
|
|
4246
|
+
* has its runtime context synced from the current connection state.
|
|
4247
|
+
*/
|
|
4248
|
+
ensureMemoryStore() {
|
|
4249
|
+
if (!this._memoryStore) {
|
|
4250
|
+
this._memoryStore = createMemoryStore({ fetch: globalThis.fetch.bind(globalThis) });
|
|
4251
|
+
this._memoryStore.start();
|
|
4252
|
+
this.syncMemoryContext();
|
|
4253
|
+
}
|
|
4254
|
+
return this._memoryStore;
|
|
4255
|
+
}
|
|
4256
|
+
/**
|
|
4257
|
+
* Pushes the current runtime wiring into the memory store. When the runtime
|
|
4258
|
+
* is connected and both the intelligence WebSocket URL and runtime URL are
|
|
4259
|
+
* available, the store receives a context (runtime URL, WebSocket URL, and a
|
|
4260
|
+
* copy of the current headers); otherwise its context is cleared. No-op when
|
|
4261
|
+
* the store has not been created yet.
|
|
4262
|
+
*/
|
|
4263
|
+
syncMemoryContext() {
|
|
4264
|
+
var _this$intelligence;
|
|
4265
|
+
if (!this._memoryStore) return;
|
|
4266
|
+
if (this.runtimeConnectionStatus === CopilotKitCoreRuntimeConnectionStatus.Connected && ((_this$intelligence = this.intelligence) === null || _this$intelligence === void 0 ? void 0 : _this$intelligence.wsUrl) && this.runtimeUrl) this._memoryStore.setContext({
|
|
4267
|
+
runtimeUrl: this.runtimeUrl,
|
|
4268
|
+
wsUrl: this.intelligence.wsUrl,
|
|
4269
|
+
headers: { ...this.headers }
|
|
4270
|
+
});
|
|
4271
|
+
else this._memoryStore.setContext(null);
|
|
4272
|
+
}
|
|
4273
|
+
/**
|
|
3068
4274
|
* Suggestions management (delegated to SuggestionEngine)
|
|
3069
4275
|
*/
|
|
3070
4276
|
addSuggestionsConfig(config) {
|
|
@@ -3083,6 +4289,16 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
3083
4289
|
return this.suggestionEngine.getSuggestions(agentId);
|
|
3084
4290
|
}
|
|
3085
4291
|
/**
|
|
4292
|
+
* Subagent registry (delegated to SubagentRegistry).
|
|
4293
|
+
*
|
|
4294
|
+
* Returns the subagents observed for an owning agent during its run(s),
|
|
4295
|
+
* keyed by `subagentId`, each carrying `name` / `description` / `status`.
|
|
4296
|
+
* Empty for runs that never emit SUBAGENT_* events.
|
|
4297
|
+
*/
|
|
4298
|
+
getSubagents(agentId) {
|
|
4299
|
+
return this.subagentRegistry.getSubagents(agentId);
|
|
4300
|
+
}
|
|
4301
|
+
/**
|
|
3086
4302
|
* Tool management (delegated to RunHandler)
|
|
3087
4303
|
*/
|
|
3088
4304
|
addTool(tool) {
|
|
@@ -3230,515 +4446,257 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
3230
4446
|
if (subscriber.onStateChanged) wrappedSubscriber.onStateChanged = (params) => {
|
|
3231
4447
|
latestStateParams = params;
|
|
3232
4448
|
throttler.maybeExecute();
|
|
3233
|
-
};
|
|
3234
|
-
const subscription = agent.subscribe(wrappedSubscriber);
|
|
3235
|
-
return { unsubscribe: () => {
|
|
3236
|
-
active = false;
|
|
3237
|
-
throttler.cancel();
|
|
3238
|
-
subscription.unsubscribe();
|
|
3239
|
-
} };
|
|
3240
|
-
}
|
|
3241
|
-
/**
|
|
3242
|
-
* Agent connectivity (delegated to RunHandler)
|
|
3243
|
-
*/
|
|
3244
|
-
async connectAgent(params) {
|
|
3245
|
-
return this.runHandler.connectAgent(params);
|
|
3246
|
-
}
|
|
3247
|
-
stopAgent(params) {
|
|
3248
|
-
this.runHandler.abortCurrentRun();
|
|
3249
|
-
params.agent.abortRun();
|
|
3250
|
-
}
|
|
3251
|
-
async runAgent(params) {
|
|
3252
|
-
return this.runHandler.runAgent(params);
|
|
3253
|
-
}
|
|
3254
|
-
/**
|
|
3255
|
-
* Programmatically execute a registered frontend tool without going through an LLM turn.
|
|
3256
|
-
* The handler runs, render components show up in the UI, and both the tool call and
|
|
3257
|
-
* result messages are added to `agent.messages`.
|
|
3258
|
-
*/
|
|
3259
|
-
async runTool(params) {
|
|
3260
|
-
return this.runHandler.runTool(params);
|
|
3261
|
-
}
|
|
3262
|
-
/**
|
|
3263
|
-
* State management (delegated to StateManager)
|
|
3264
|
-
*/
|
|
3265
|
-
getStateByRun(agentId, threadId, runId) {
|
|
3266
|
-
return this.stateManager.getStateByRun(agentId, threadId, runId);
|
|
3267
|
-
}
|
|
3268
|
-
getRunIdForMessage(agentId, threadId, messageId) {
|
|
3269
|
-
return this.stateManager.getRunIdForMessage(agentId, threadId, messageId);
|
|
3270
|
-
}
|
|
3271
|
-
getRunIdsForThread(agentId, threadId) {
|
|
3272
|
-
return this.stateManager.getRunIdsForThread(agentId, threadId);
|
|
3273
|
-
}
|
|
3274
|
-
/**
|
|
3275
|
-
* Internal method used by RunHandler to build frontend tools
|
|
3276
|
-
*/
|
|
3277
|
-
buildFrontendTools(agentId) {
|
|
3278
|
-
return this.runHandler.buildFrontendTools(agentId);
|
|
3279
|
-
}
|
|
3280
|
-
/**
|
|
3281
|
-
* Called before each follow-up agent run (after tool execution).
|
|
3282
|
-
*
|
|
3283
|
-
* When a frontend tool handler calls framework state setters (e.g. React's
|
|
3284
|
-
* setState), those updates are batched and deferred — they do not take effect
|
|
3285
|
-
* until the framework's scheduler runs (React uses MessageChannel).
|
|
3286
|
-
* useAgentContext registers context via useLayoutEffect, which runs
|
|
3287
|
-
* synchronously after React commits that deferred batch.
|
|
3288
|
-
*
|
|
3289
|
-
* Without yielding here, the follow-up runAgent reads the context store
|
|
3290
|
-
* synchronously while the deferred updates are still pending, producing stale
|
|
3291
|
-
* context for the next agent turn.
|
|
3292
|
-
*
|
|
3293
|
-
* Override in framework-specific subclasses to yield to the framework
|
|
3294
|
-
* scheduler before the follow-up run. The base implementation is a no-op
|
|
3295
|
-
* because non-React environments have no deferred state to flush.
|
|
3296
|
-
*/
|
|
3297
|
-
async waitForPendingFrameworkUpdates() {}
|
|
3298
|
-
};
|
|
3299
|
-
|
|
3300
|
-
//#endregion
|
|
3301
|
-
//#region src/types.ts
|
|
3302
|
-
/**
|
|
3303
|
-
* Status of a tool call execution
|
|
3304
|
-
*/
|
|
3305
|
-
let ToolCallStatus = /* @__PURE__ */ function(ToolCallStatus) {
|
|
3306
|
-
ToolCallStatus["InProgress"] = "inProgress";
|
|
3307
|
-
ToolCallStatus["Executing"] = "executing";
|
|
3308
|
-
ToolCallStatus["Complete"] = "complete";
|
|
3309
|
-
return ToolCallStatus;
|
|
3310
|
-
}({});
|
|
3311
|
-
|
|
3312
|
-
//#endregion
|
|
3313
|
-
//#region src/utils/markdown.ts
|
|
3314
|
-
function completePartialMarkdown(input) {
|
|
3315
|
-
let s = input;
|
|
3316
|
-
const fenceMatches = Array.from(s.matchAll(/^(\s*)(`{3,}|~{3,})/gm));
|
|
3317
|
-
if (fenceMatches.length % 2 === 1) {
|
|
3318
|
-
const [, indent, fence] = fenceMatches[0];
|
|
3319
|
-
s += `\n${indent}${fence}`;
|
|
3320
|
-
}
|
|
3321
|
-
if (s.match(/\[([^\]]*)\]\(([^)]*)$/)) s += ")";
|
|
3322
|
-
const openElements = [];
|
|
3323
|
-
const chars = Array.from(s);
|
|
3324
|
-
const codeBlockRanges = [];
|
|
3325
|
-
const inlineCodeRanges = [];
|
|
3326
|
-
let tempCodeFenceCount = 0;
|
|
3327
|
-
let currentCodeBlockStart = -1;
|
|
3328
|
-
for (let i = 0; i < chars.length; i++) if (i === 0 || chars[i - 1] === "\n") {
|
|
3329
|
-
const lineMatch = s.substring(i).match(/^(\s*)(`{3,}|~{3,})/);
|
|
3330
|
-
if (lineMatch) {
|
|
3331
|
-
tempCodeFenceCount++;
|
|
3332
|
-
if (tempCodeFenceCount % 2 === 1) currentCodeBlockStart = i;
|
|
3333
|
-
else if (currentCodeBlockStart !== -1) {
|
|
3334
|
-
codeBlockRanges.push({
|
|
3335
|
-
start: currentCodeBlockStart,
|
|
3336
|
-
end: i + lineMatch[0].length
|
|
3337
|
-
});
|
|
3338
|
-
currentCodeBlockStart = -1;
|
|
3339
|
-
}
|
|
3340
|
-
i += lineMatch[0].length - 1;
|
|
3341
|
-
}
|
|
3342
|
-
}
|
|
3343
|
-
for (let i = 0; i < chars.length; i++) if (chars[i] === "`") {
|
|
3344
|
-
let backslashCount = 0;
|
|
3345
|
-
for (let j = i - 1; j >= 0 && chars[j] === "\\"; j--) backslashCount++;
|
|
3346
|
-
if (backslashCount % 2 === 0) {
|
|
3347
|
-
for (let j = i + 1; j < chars.length; j++) if (chars[j] === "`") {
|
|
3348
|
-
let closingBackslashCount = 0;
|
|
3349
|
-
for (let k = j - 1; k >= 0 && chars[k] === "\\"; k--) closingBackslashCount++;
|
|
3350
|
-
if (closingBackslashCount % 2 === 0) {
|
|
3351
|
-
inlineCodeRanges.push({
|
|
3352
|
-
start: i,
|
|
3353
|
-
end: j + 1
|
|
3354
|
-
});
|
|
3355
|
-
i = j;
|
|
3356
|
-
break;
|
|
3357
|
-
}
|
|
3358
|
-
}
|
|
3359
|
-
}
|
|
3360
|
-
}
|
|
3361
|
-
const isInCode = (pos) => {
|
|
3362
|
-
return codeBlockRanges.some((range) => pos >= range.start && pos < range.end) || inlineCodeRanges.some((range) => pos >= range.start && pos < range.end);
|
|
3363
|
-
};
|
|
3364
|
-
for (let i = 0; i < chars.length; i++) {
|
|
3365
|
-
const char = chars[i];
|
|
3366
|
-
const nextChar = chars[i + 1];
|
|
3367
|
-
const prevChar = chars[i - 1];
|
|
3368
|
-
if (isInCode(i)) continue;
|
|
3369
|
-
if (char === "[") {
|
|
3370
|
-
let isCompleteLink = false;
|
|
3371
|
-
let bracketDepth = 1;
|
|
3372
|
-
let j = i + 1;
|
|
3373
|
-
while (j < chars.length && bracketDepth > 0) {
|
|
3374
|
-
if (chars[j] === "[" && !isInCode(j)) bracketDepth++;
|
|
3375
|
-
if (chars[j] === "]" && !isInCode(j)) bracketDepth--;
|
|
3376
|
-
j++;
|
|
3377
|
-
}
|
|
3378
|
-
if (bracketDepth === 0 && chars[j] === "(") {
|
|
3379
|
-
let parenDepth = 1;
|
|
3380
|
-
j++;
|
|
3381
|
-
while (j < chars.length && parenDepth > 0) {
|
|
3382
|
-
if (chars[j] === "(" && !isInCode(j)) parenDepth++;
|
|
3383
|
-
if (chars[j] === ")" && !isInCode(j)) parenDepth--;
|
|
3384
|
-
j++;
|
|
3385
|
-
}
|
|
3386
|
-
if (parenDepth === 0) {
|
|
3387
|
-
isCompleteLink = true;
|
|
3388
|
-
i = j - 1;
|
|
3389
|
-
continue;
|
|
3390
|
-
}
|
|
3391
|
-
}
|
|
3392
|
-
if (!isCompleteLink) {
|
|
3393
|
-
const existingIndex = openElements.findIndex((el) => el.type === "bracket");
|
|
3394
|
-
if (existingIndex !== -1) openElements.splice(existingIndex, 1);
|
|
3395
|
-
else openElements.push({
|
|
3396
|
-
type: "bracket",
|
|
3397
|
-
marker: "[",
|
|
3398
|
-
position: i
|
|
3399
|
-
});
|
|
3400
|
-
}
|
|
3401
|
-
} else if (char === "*" && nextChar === "*") {
|
|
3402
|
-
const existingIndex = openElements.findIndex((el) => el.type === "bold_star");
|
|
3403
|
-
if (existingIndex !== -1) openElements.splice(existingIndex, 1);
|
|
3404
|
-
else openElements.push({
|
|
3405
|
-
type: "bold_star",
|
|
3406
|
-
marker: "**",
|
|
3407
|
-
position: i
|
|
3408
|
-
});
|
|
3409
|
-
i++;
|
|
3410
|
-
} else if (char === "_" && nextChar === "_") {
|
|
3411
|
-
const existingIndex = openElements.findIndex((el) => el.type === "bold_underscore");
|
|
3412
|
-
if (existingIndex !== -1) openElements.splice(existingIndex, 1);
|
|
3413
|
-
else openElements.push({
|
|
3414
|
-
type: "bold_underscore",
|
|
3415
|
-
marker: "__",
|
|
3416
|
-
position: i
|
|
3417
|
-
});
|
|
3418
|
-
i++;
|
|
3419
|
-
} else if (char === "~" && nextChar === "~") {
|
|
3420
|
-
const existingIndex = openElements.findIndex((el) => el.type === "strike");
|
|
3421
|
-
if (existingIndex !== -1) openElements.splice(existingIndex, 1);
|
|
3422
|
-
else openElements.push({
|
|
3423
|
-
type: "strike",
|
|
3424
|
-
marker: "~~",
|
|
3425
|
-
position: i
|
|
3426
|
-
});
|
|
3427
|
-
i++;
|
|
3428
|
-
} else if (char === "*" && prevChar !== "*" && nextChar !== "*") {
|
|
3429
|
-
const existingIndex = openElements.findIndex((el) => el.type === "italic_star");
|
|
3430
|
-
if (existingIndex !== -1) openElements.splice(existingIndex, 1);
|
|
3431
|
-
else openElements.push({
|
|
3432
|
-
type: "italic_star",
|
|
3433
|
-
marker: "*",
|
|
3434
|
-
position: i
|
|
3435
|
-
});
|
|
3436
|
-
} else if (char === "_" && prevChar !== "_" && nextChar !== "_") {
|
|
3437
|
-
const existingIndex = openElements.findIndex((el) => el.type === "italic_underscore");
|
|
3438
|
-
if (existingIndex !== -1) openElements.splice(existingIndex, 1);
|
|
3439
|
-
else openElements.push({
|
|
3440
|
-
type: "italic_underscore",
|
|
3441
|
-
marker: "_",
|
|
3442
|
-
position: i
|
|
3443
|
-
});
|
|
3444
|
-
}
|
|
3445
|
-
}
|
|
3446
|
-
let backtickCount = 0;
|
|
3447
|
-
for (let i = 0; i < chars.length; i++) if (chars[i] === "`" && !isInCode(i)) backtickCount++;
|
|
3448
|
-
if (backtickCount % 2 === 1) s += "`";
|
|
3449
|
-
openElements.sort((a, b) => b.position - a.position);
|
|
3450
|
-
const closers = openElements.map((el) => {
|
|
3451
|
-
switch (el.type) {
|
|
3452
|
-
case "bracket": return "]";
|
|
3453
|
-
case "bold_star": return "**";
|
|
3454
|
-
case "bold_underscore": return "__";
|
|
3455
|
-
case "strike": return "~~";
|
|
3456
|
-
case "italic_star": return "*";
|
|
3457
|
-
case "italic_underscore": return "_";
|
|
3458
|
-
default: return "";
|
|
3459
|
-
}
|
|
3460
|
-
});
|
|
3461
|
-
let result = s + closers.join("");
|
|
3462
|
-
const finalFenceMatches = Array.from(result.matchAll(/^(\s*)(`{3,}|~{3,})/gm));
|
|
3463
|
-
const hasUnclosedBacktick = (result.match(/`/g) || []).length % 2 === 1;
|
|
3464
|
-
const hasUnclosedCodeFence = finalFenceMatches.length % 2 === 1;
|
|
3465
|
-
let shouldCloseParens = !hasUnclosedBacktick && !hasUnclosedCodeFence;
|
|
3466
|
-
if (shouldCloseParens) {
|
|
3467
|
-
const lastOpenParen = result.lastIndexOf("(");
|
|
3468
|
-
if (lastOpenParen !== -1) {
|
|
3469
|
-
if ((result.substring(0, lastOpenParen).match(/`/g) || []).length % 2 === 1) shouldCloseParens = false;
|
|
3470
|
-
}
|
|
4449
|
+
};
|
|
4450
|
+
const subscription = agent.subscribe(wrappedSubscriber);
|
|
4451
|
+
return { unsubscribe: () => {
|
|
4452
|
+
active = false;
|
|
4453
|
+
throttler.cancel();
|
|
4454
|
+
subscription.unsubscribe();
|
|
4455
|
+
} };
|
|
3471
4456
|
}
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
4457
|
+
/**
|
|
4458
|
+
* Agent connectivity (delegated to RunHandler)
|
|
4459
|
+
*/
|
|
4460
|
+
async connectAgent(params) {
|
|
4461
|
+
return this.runHandler.connectAgent(params);
|
|
3476
4462
|
}
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
//#endregion
|
|
3481
|
-
//#region src/utils/micro-redux.ts
|
|
3482
|
-
const INTERNAL_ACTION_TYPES = {
|
|
3483
|
-
boot: "@@micro-redux/boot",
|
|
3484
|
-
init: "@@micro-redux/init",
|
|
3485
|
-
stop: "@@micro-redux/stop"
|
|
3486
|
-
};
|
|
3487
|
-
const INTERNAL_BOOT_ACTION = { type: INTERNAL_ACTION_TYPES.boot };
|
|
3488
|
-
/**
|
|
3489
|
-
* Builds a typed action creator from a type string and payload factory.
|
|
3490
|
-
*/
|
|
3491
|
-
function createTypedActionCreator(type, factory) {
|
|
3492
|
-
const creator = ((...args) => ({
|
|
3493
|
-
...factory(...args),
|
|
3494
|
-
type
|
|
3495
|
-
}));
|
|
3496
|
-
creator.type = type;
|
|
3497
|
-
creator.match = (action) => action.type === type;
|
|
3498
|
-
return creator;
|
|
3499
|
-
}
|
|
3500
|
-
/**
|
|
3501
|
-
* Declares a payload-based action config for `createActionGroup`.
|
|
3502
|
-
*
|
|
3503
|
-
* @example
|
|
3504
|
-
* ```ts
|
|
3505
|
-
* const actions = createActionGroup("User", {
|
|
3506
|
-
* loaded: props<{ id: string }>(),
|
|
3507
|
-
* });
|
|
3508
|
-
* ```
|
|
3509
|
-
*/
|
|
3510
|
-
function props() {
|
|
3511
|
-
return { kind: "props" };
|
|
3512
|
-
}
|
|
3513
|
-
/**
|
|
3514
|
-
* Declares a no-payload action config for `createActionGroup`.
|
|
3515
|
-
*
|
|
3516
|
-
* @example
|
|
3517
|
-
* ```ts
|
|
3518
|
-
* const actions = createActionGroup("User", {
|
|
3519
|
-
* reset: empty(),
|
|
3520
|
-
* });
|
|
3521
|
-
* ```
|
|
3522
|
-
*/
|
|
3523
|
-
function empty() {
|
|
3524
|
-
return { kind: "empty" };
|
|
3525
|
-
}
|
|
3526
|
-
/**
|
|
3527
|
-
* Creates a namespaced group of typed action creators.
|
|
3528
|
-
*
|
|
3529
|
-
* Action types are formatted as: `[Source] actionName`.
|
|
3530
|
-
*/
|
|
3531
|
-
function createActionGroup(source, config) {
|
|
3532
|
-
const group = {};
|
|
3533
|
-
for (const eventName of Object.keys(config)) {
|
|
3534
|
-
const eventConfig = config[eventName];
|
|
3535
|
-
if (!eventConfig) continue;
|
|
3536
|
-
const actionType = `[${source}] ${eventName}`;
|
|
3537
|
-
if (eventConfig.kind === "props") {
|
|
3538
|
-
group[eventName] = createTypedActionCreator(actionType, (payload) => ({ ...payload }));
|
|
3539
|
-
continue;
|
|
3540
|
-
}
|
|
3541
|
-
group[eventName] = createTypedActionCreator(actionType, () => ({}));
|
|
4463
|
+
stopAgent(params) {
|
|
4464
|
+
this.runHandler.abortCurrentRun();
|
|
4465
|
+
params.agent.abortRun();
|
|
3542
4466
|
}
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
/**
|
|
3546
|
-
* Registers one reducer handler for one or more action creators.
|
|
3547
|
-
*
|
|
3548
|
-
* @throws Error when called without at least one action creator and reducer.
|
|
3549
|
-
*/
|
|
3550
|
-
function on(...args) {
|
|
3551
|
-
if (args.length < 2) throw new Error("on requires at least one action creator and one reducer");
|
|
3552
|
-
const reducer = args[args.length - 1];
|
|
3553
|
-
return {
|
|
3554
|
-
creators: args.slice(0, -1),
|
|
3555
|
-
reducer
|
|
3556
|
-
};
|
|
3557
|
-
}
|
|
3558
|
-
/**
|
|
3559
|
-
* Creates a reducer from an initial state and `on(...)` handler entries.
|
|
3560
|
-
*
|
|
3561
|
-
* Unknown action types return the current state unchanged.
|
|
3562
|
-
*/
|
|
3563
|
-
function createReducer(initialState, ...entries) {
|
|
3564
|
-
const reducerMap = /* @__PURE__ */ new Map();
|
|
3565
|
-
for (const entry of entries) for (const creator of entry.creators) {
|
|
3566
|
-
var _reducerMap$get;
|
|
3567
|
-
const handlers = (_reducerMap$get = reducerMap.get(creator.type)) !== null && _reducerMap$get !== void 0 ? _reducerMap$get : [];
|
|
3568
|
-
handlers.push(entry.reducer);
|
|
3569
|
-
reducerMap.set(creator.type, handlers);
|
|
4467
|
+
async runAgent(params) {
|
|
4468
|
+
return this.runHandler.runAgent(params);
|
|
3570
4469
|
}
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
return
|
|
3578
|
-
};
|
|
3579
|
-
}
|
|
3580
|
-
/**
|
|
3581
|
-
* Creates a selector that caches and reuses the last computed result
|
|
3582
|
-
* when all input references are unchanged.
|
|
3583
|
-
*/
|
|
3584
|
-
function createSelector(...args) {
|
|
3585
|
-
if (args.length === 1) {
|
|
3586
|
-
const projector = args[0];
|
|
3587
|
-
let hasCached = false;
|
|
3588
|
-
let lastState;
|
|
3589
|
-
let lastResult;
|
|
3590
|
-
return (state) => {
|
|
3591
|
-
if (hasCached && state === lastState) return lastResult;
|
|
3592
|
-
lastState = state;
|
|
3593
|
-
lastResult = projector(state);
|
|
3594
|
-
hasCached = true;
|
|
3595
|
-
return lastResult;
|
|
3596
|
-
};
|
|
4470
|
+
/**
|
|
4471
|
+
* Programmatically execute a registered frontend tool without going through an LLM turn.
|
|
4472
|
+
* The handler runs, render components show up in the UI, and both the tool call and
|
|
4473
|
+
* result messages are added to `agent.messages`.
|
|
4474
|
+
*/
|
|
4475
|
+
async runTool(params) {
|
|
4476
|
+
return this.runHandler.runTool(params);
|
|
3597
4477
|
}
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
}
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
const
|
|
3661
|
-
const
|
|
3662
|
-
let
|
|
3663
|
-
let
|
|
3664
|
-
let
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
};
|
|
3674
|
-
const failFast = (error) => {
|
|
3675
|
-
if (hasFatalError) return;
|
|
3676
|
-
hasFatalError = true;
|
|
3677
|
-
isRunning = false;
|
|
3678
|
-
effectSubscriptions.unsubscribe();
|
|
3679
|
-
effectSubscriptions = new rxjs.Subscription();
|
|
3680
|
-
actionsSubject.error(error);
|
|
3681
|
-
stateSubject.error(error);
|
|
3682
|
-
};
|
|
3683
|
-
const startEffects = () => {
|
|
3684
|
-
for (const effect of effects) {
|
|
3685
|
-
const scheduledActions$ = actionsSubject.asObservable().pipe((0, rxjs_operators.observeOn)(rxjs.asapScheduler));
|
|
3686
|
-
const state$ = stateSubject.asObservable();
|
|
3687
|
-
if (effect.dispatch) {
|
|
3688
|
-
const subscription = effect.run(scheduledActions$, state$).subscribe({
|
|
3689
|
-
next: (effectAction) => {
|
|
3690
|
-
if (hasFatalError) return;
|
|
3691
|
-
dispatchInternal(effectAction);
|
|
3692
|
-
},
|
|
3693
|
-
error: (error) => {
|
|
3694
|
-
failFast(error);
|
|
3695
|
-
}
|
|
4478
|
+
/**
|
|
4479
|
+
* State management (delegated to StateManager)
|
|
4480
|
+
*/
|
|
4481
|
+
getStateByRun(agentId, threadId, runId) {
|
|
4482
|
+
return this.stateManager.getStateByRun(agentId, threadId, runId);
|
|
4483
|
+
}
|
|
4484
|
+
getRunIdForMessage(agentId, threadId, messageId) {
|
|
4485
|
+
return this.stateManager.getRunIdForMessage(agentId, threadId, messageId);
|
|
4486
|
+
}
|
|
4487
|
+
getRunIdsForThread(agentId, threadId) {
|
|
4488
|
+
return this.stateManager.getRunIdsForThread(agentId, threadId);
|
|
4489
|
+
}
|
|
4490
|
+
/**
|
|
4491
|
+
* Internal method used by RunHandler to build frontend tools
|
|
4492
|
+
*/
|
|
4493
|
+
buildFrontendTools(agentId) {
|
|
4494
|
+
return this.runHandler.buildFrontendTools(agentId);
|
|
4495
|
+
}
|
|
4496
|
+
/**
|
|
4497
|
+
* Called before each follow-up agent run (after tool execution).
|
|
4498
|
+
*
|
|
4499
|
+
* When a frontend tool handler calls framework state setters (e.g. React's
|
|
4500
|
+
* setState), those updates are batched and deferred — they do not take effect
|
|
4501
|
+
* until the framework's scheduler runs (React uses MessageChannel).
|
|
4502
|
+
* useAgentContext registers context via useLayoutEffect, which runs
|
|
4503
|
+
* synchronously after React commits that deferred batch.
|
|
4504
|
+
*
|
|
4505
|
+
* Without yielding here, the follow-up runAgent reads the context store
|
|
4506
|
+
* synchronously while the deferred updates are still pending, producing stale
|
|
4507
|
+
* context for the next agent turn.
|
|
4508
|
+
*
|
|
4509
|
+
* Override in framework-specific subclasses to yield to the framework
|
|
4510
|
+
* scheduler before the follow-up run. The base implementation is a no-op
|
|
4511
|
+
* because non-React environments have no deferred state to flush.
|
|
4512
|
+
*/
|
|
4513
|
+
async waitForPendingFrameworkUpdates() {}
|
|
4514
|
+
};
|
|
4515
|
+
|
|
4516
|
+
//#endregion
|
|
4517
|
+
//#region src/types.ts
|
|
4518
|
+
/**
|
|
4519
|
+
* Status of a tool call execution
|
|
4520
|
+
*/
|
|
4521
|
+
let ToolCallStatus = /* @__PURE__ */ function(ToolCallStatus) {
|
|
4522
|
+
ToolCallStatus["InProgress"] = "inProgress";
|
|
4523
|
+
ToolCallStatus["Executing"] = "executing";
|
|
4524
|
+
ToolCallStatus["Complete"] = "complete";
|
|
4525
|
+
return ToolCallStatus;
|
|
4526
|
+
}({});
|
|
4527
|
+
|
|
4528
|
+
//#endregion
|
|
4529
|
+
//#region src/utils/markdown.ts
|
|
4530
|
+
function completePartialMarkdown(input) {
|
|
4531
|
+
let s = input;
|
|
4532
|
+
const fenceMatches = Array.from(s.matchAll(/^(\s*)(`{3,}|~{3,})/gm));
|
|
4533
|
+
if (fenceMatches.length % 2 === 1) {
|
|
4534
|
+
const [, indent, fence] = fenceMatches[0];
|
|
4535
|
+
s += `\n${indent}${fence}`;
|
|
4536
|
+
}
|
|
4537
|
+
if (s.match(/\[([^\]]*)\]\(([^)]*)$/)) s += ")";
|
|
4538
|
+
const openElements = [];
|
|
4539
|
+
const chars = Array.from(s);
|
|
4540
|
+
const codeBlockRanges = [];
|
|
4541
|
+
const inlineCodeRanges = [];
|
|
4542
|
+
let tempCodeFenceCount = 0;
|
|
4543
|
+
let currentCodeBlockStart = -1;
|
|
4544
|
+
for (let i = 0; i < chars.length; i++) if (i === 0 || chars[i - 1] === "\n") {
|
|
4545
|
+
const lineMatch = s.substring(i).match(/^(\s*)(`{3,}|~{3,})/);
|
|
4546
|
+
if (lineMatch) {
|
|
4547
|
+
tempCodeFenceCount++;
|
|
4548
|
+
if (tempCodeFenceCount % 2 === 1) currentCodeBlockStart = i;
|
|
4549
|
+
else if (currentCodeBlockStart !== -1) {
|
|
4550
|
+
codeBlockRanges.push({
|
|
4551
|
+
start: currentCodeBlockStart,
|
|
4552
|
+
end: i + lineMatch[0].length
|
|
3696
4553
|
});
|
|
3697
|
-
|
|
3698
|
-
continue;
|
|
4554
|
+
currentCodeBlockStart = -1;
|
|
3699
4555
|
}
|
|
3700
|
-
|
|
3701
|
-
failFast(error);
|
|
3702
|
-
} });
|
|
3703
|
-
effectSubscriptions.add(subscription);
|
|
4556
|
+
i += lineMatch[0].length - 1;
|
|
3704
4557
|
}
|
|
3705
|
-
}
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
init() {
|
|
3723
|
-
if (hasFatalError || isRunning) return;
|
|
3724
|
-
isRunning = true;
|
|
3725
|
-
startEffects();
|
|
3726
|
-
if (hasFatalError) return;
|
|
3727
|
-
dispatchInternal({ type: INTERNAL_ACTION_TYPES.init });
|
|
3728
|
-
},
|
|
3729
|
-
stop() {
|
|
3730
|
-
if (hasFatalError || !isRunning) return;
|
|
3731
|
-
dispatchInternal({ type: INTERNAL_ACTION_TYPES.stop });
|
|
3732
|
-
effectSubscriptions.unsubscribe();
|
|
3733
|
-
effectSubscriptions = new rxjs.Subscription();
|
|
3734
|
-
isRunning = false;
|
|
4558
|
+
}
|
|
4559
|
+
for (let i = 0; i < chars.length; i++) if (chars[i] === "`") {
|
|
4560
|
+
let backslashCount = 0;
|
|
4561
|
+
for (let j = i - 1; j >= 0 && chars[j] === "\\"; j--) backslashCount++;
|
|
4562
|
+
if (backslashCount % 2 === 0) {
|
|
4563
|
+
for (let j = i + 1; j < chars.length; j++) if (chars[j] === "`") {
|
|
4564
|
+
let closingBackslashCount = 0;
|
|
4565
|
+
for (let k = j - 1; k >= 0 && chars[k] === "\\"; k--) closingBackslashCount++;
|
|
4566
|
+
if (closingBackslashCount % 2 === 0) {
|
|
4567
|
+
inlineCodeRanges.push({
|
|
4568
|
+
start: i,
|
|
4569
|
+
end: j + 1
|
|
4570
|
+
});
|
|
4571
|
+
i = j;
|
|
4572
|
+
break;
|
|
4573
|
+
}
|
|
4574
|
+
}
|
|
3735
4575
|
}
|
|
4576
|
+
}
|
|
4577
|
+
const isInCode = (pos) => {
|
|
4578
|
+
return codeBlockRanges.some((range) => pos >= range.start && pos < range.end) || inlineCodeRanges.some((range) => pos >= range.start && pos < range.end);
|
|
3736
4579
|
};
|
|
4580
|
+
for (let i = 0; i < chars.length; i++) {
|
|
4581
|
+
const char = chars[i];
|
|
4582
|
+
const nextChar = chars[i + 1];
|
|
4583
|
+
const prevChar = chars[i - 1];
|
|
4584
|
+
if (isInCode(i)) continue;
|
|
4585
|
+
if (char === "[") {
|
|
4586
|
+
let isCompleteLink = false;
|
|
4587
|
+
let bracketDepth = 1;
|
|
4588
|
+
let j = i + 1;
|
|
4589
|
+
while (j < chars.length && bracketDepth > 0) {
|
|
4590
|
+
if (chars[j] === "[" && !isInCode(j)) bracketDepth++;
|
|
4591
|
+
if (chars[j] === "]" && !isInCode(j)) bracketDepth--;
|
|
4592
|
+
j++;
|
|
4593
|
+
}
|
|
4594
|
+
if (bracketDepth === 0 && chars[j] === "(") {
|
|
4595
|
+
let parenDepth = 1;
|
|
4596
|
+
j++;
|
|
4597
|
+
while (j < chars.length && parenDepth > 0) {
|
|
4598
|
+
if (chars[j] === "(" && !isInCode(j)) parenDepth++;
|
|
4599
|
+
if (chars[j] === ")" && !isInCode(j)) parenDepth--;
|
|
4600
|
+
j++;
|
|
4601
|
+
}
|
|
4602
|
+
if (parenDepth === 0) {
|
|
4603
|
+
isCompleteLink = true;
|
|
4604
|
+
i = j - 1;
|
|
4605
|
+
continue;
|
|
4606
|
+
}
|
|
4607
|
+
}
|
|
4608
|
+
if (!isCompleteLink) {
|
|
4609
|
+
const existingIndex = openElements.findIndex((el) => el.type === "bracket");
|
|
4610
|
+
if (existingIndex !== -1) openElements.splice(existingIndex, 1);
|
|
4611
|
+
else openElements.push({
|
|
4612
|
+
type: "bracket",
|
|
4613
|
+
marker: "[",
|
|
4614
|
+
position: i
|
|
4615
|
+
});
|
|
4616
|
+
}
|
|
4617
|
+
} else if (char === "*" && nextChar === "*") {
|
|
4618
|
+
const existingIndex = openElements.findIndex((el) => el.type === "bold_star");
|
|
4619
|
+
if (existingIndex !== -1) openElements.splice(existingIndex, 1);
|
|
4620
|
+
else openElements.push({
|
|
4621
|
+
type: "bold_star",
|
|
4622
|
+
marker: "**",
|
|
4623
|
+
position: i
|
|
4624
|
+
});
|
|
4625
|
+
i++;
|
|
4626
|
+
} else if (char === "_" && nextChar === "_") {
|
|
4627
|
+
const existingIndex = openElements.findIndex((el) => el.type === "bold_underscore");
|
|
4628
|
+
if (existingIndex !== -1) openElements.splice(existingIndex, 1);
|
|
4629
|
+
else openElements.push({
|
|
4630
|
+
type: "bold_underscore",
|
|
4631
|
+
marker: "__",
|
|
4632
|
+
position: i
|
|
4633
|
+
});
|
|
4634
|
+
i++;
|
|
4635
|
+
} else if (char === "~" && nextChar === "~") {
|
|
4636
|
+
const existingIndex = openElements.findIndex((el) => el.type === "strike");
|
|
4637
|
+
if (existingIndex !== -1) openElements.splice(existingIndex, 1);
|
|
4638
|
+
else openElements.push({
|
|
4639
|
+
type: "strike",
|
|
4640
|
+
marker: "~~",
|
|
4641
|
+
position: i
|
|
4642
|
+
});
|
|
4643
|
+
i++;
|
|
4644
|
+
} else if (char === "*" && prevChar !== "*" && nextChar !== "*") {
|
|
4645
|
+
const existingIndex = openElements.findIndex((el) => el.type === "italic_star");
|
|
4646
|
+
if (existingIndex !== -1) openElements.splice(existingIndex, 1);
|
|
4647
|
+
else openElements.push({
|
|
4648
|
+
type: "italic_star",
|
|
4649
|
+
marker: "*",
|
|
4650
|
+
position: i
|
|
4651
|
+
});
|
|
4652
|
+
} else if (char === "_" && prevChar !== "_" && nextChar !== "_") {
|
|
4653
|
+
const existingIndex = openElements.findIndex((el) => el.type === "italic_underscore");
|
|
4654
|
+
if (existingIndex !== -1) openElements.splice(existingIndex, 1);
|
|
4655
|
+
else openElements.push({
|
|
4656
|
+
type: "italic_underscore",
|
|
4657
|
+
marker: "_",
|
|
4658
|
+
position: i
|
|
4659
|
+
});
|
|
4660
|
+
}
|
|
4661
|
+
}
|
|
4662
|
+
let backtickCount = 0;
|
|
4663
|
+
for (let i = 0; i < chars.length; i++) if (chars[i] === "`" && !isInCode(i)) backtickCount++;
|
|
4664
|
+
if (backtickCount % 2 === 1) s += "`";
|
|
4665
|
+
openElements.sort((a, b) => b.position - a.position);
|
|
4666
|
+
const closers = openElements.map((el) => {
|
|
4667
|
+
switch (el.type) {
|
|
4668
|
+
case "bracket": return "]";
|
|
4669
|
+
case "bold_star": return "**";
|
|
4670
|
+
case "bold_underscore": return "__";
|
|
4671
|
+
case "strike": return "~~";
|
|
4672
|
+
case "italic_star": return "*";
|
|
4673
|
+
case "italic_underscore": return "_";
|
|
4674
|
+
default: return "";
|
|
4675
|
+
}
|
|
4676
|
+
});
|
|
4677
|
+
let result = s + closers.join("");
|
|
4678
|
+
const finalFenceMatches = Array.from(result.matchAll(/^(\s*)(`{3,}|~{3,})/gm));
|
|
4679
|
+
const hasUnclosedBacktick = (result.match(/`/g) || []).length % 2 === 1;
|
|
4680
|
+
const hasUnclosedCodeFence = finalFenceMatches.length % 2 === 1;
|
|
4681
|
+
let shouldCloseParens = !hasUnclosedBacktick && !hasUnclosedCodeFence;
|
|
4682
|
+
if (shouldCloseParens) {
|
|
4683
|
+
const lastOpenParen = result.lastIndexOf("(");
|
|
4684
|
+
if (lastOpenParen !== -1) {
|
|
4685
|
+
if ((result.substring(0, lastOpenParen).match(/`/g) || []).length % 2 === 1) shouldCloseParens = false;
|
|
4686
|
+
}
|
|
4687
|
+
}
|
|
4688
|
+
if (shouldCloseParens) {
|
|
4689
|
+
const openParens = (result.match(/\(/g) || []).length;
|
|
4690
|
+
const closeParens = (result.match(/\)/g) || []).length;
|
|
4691
|
+
if (openParens > closeParens) result += ")".repeat(openParens - closeParens);
|
|
4692
|
+
}
|
|
4693
|
+
return result;
|
|
3737
4694
|
}
|
|
3738
4695
|
|
|
3739
4696
|
//#endregion
|
|
3740
4697
|
//#region src/threads.ts
|
|
3741
4698
|
const THREADS_CHANNEL_EVENT = "thread_metadata";
|
|
4699
|
+
const THREAD_RUN_ACTIVITY_CHANNEL_EVENT = "thread_run_activity";
|
|
3742
4700
|
const THREAD_SUBSCRIBE_PATH = "/threads/subscribe";
|
|
3743
4701
|
const MAX_SOCKET_RETRIES = 5;
|
|
3744
4702
|
const REQUEST_TIMEOUT_MS = 15e3;
|
|
@@ -3747,6 +4705,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
3747
4705
|
isLoading: false,
|
|
3748
4706
|
isFetchingNextPage: false,
|
|
3749
4707
|
error: null,
|
|
4708
|
+
fetchMoreError: null,
|
|
3750
4709
|
context: null,
|
|
3751
4710
|
sessionId: 0,
|
|
3752
4711
|
metadataCredentialsRequested: false,
|
|
@@ -3782,7 +4741,8 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
3782
4741
|
errored: props(),
|
|
3783
4742
|
joinFailed: props(),
|
|
3784
4743
|
joinTimedOut: props(),
|
|
3785
|
-
metadataReceived: props()
|
|
4744
|
+
metadataReceived: props(),
|
|
4745
|
+
runActivityReceived: props()
|
|
3786
4746
|
});
|
|
3787
4747
|
const threadDomainEvents = createActionGroup("Thread Domain", {
|
|
3788
4748
|
threadUpserted: props(),
|
|
@@ -3802,6 +4762,29 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
3802
4762
|
next[existingIndex] = thread;
|
|
3803
4763
|
return sortThreadsByRecency(next);
|
|
3804
4764
|
}
|
|
4765
|
+
/**
|
|
4766
|
+
* Returns a non-empty string payload field or undefined for absent fields.
|
|
4767
|
+
*/
|
|
4768
|
+
function optionalString(value) {
|
|
4769
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
4770
|
+
}
|
|
4771
|
+
/**
|
|
4772
|
+
* Converts gateway run-activity payloads into the internal TypeScript shape.
|
|
4773
|
+
*/
|
|
4774
|
+
function normalizeThreadRunActivityNotification(payload) {
|
|
4775
|
+
var _payload$threadId, _payload$eventType, _payload$agentId, _payload$runId, _payload$latestEventI;
|
|
4776
|
+
const threadId = optionalString((_payload$threadId = payload.threadId) !== null && _payload$threadId !== void 0 ? _payload$threadId : payload.thread_id);
|
|
4777
|
+
const eventType = optionalString((_payload$eventType = payload.eventType) !== null && _payload$eventType !== void 0 ? _payload$eventType : payload.event_type);
|
|
4778
|
+
if (!threadId || !eventType) return null;
|
|
4779
|
+
return {
|
|
4780
|
+
type: "thread_run_activity",
|
|
4781
|
+
threadId,
|
|
4782
|
+
agentId: optionalString((_payload$agentId = payload.agentId) !== null && _payload$agentId !== void 0 ? _payload$agentId : payload.agent_id),
|
|
4783
|
+
runId: optionalString((_payload$runId = payload.runId) !== null && _payload$runId !== void 0 ? _payload$runId : payload.run_id),
|
|
4784
|
+
eventType,
|
|
4785
|
+
latestEventId: optionalString((_payload$latestEventI = payload.latestEventId) !== null && _payload$latestEventI !== void 0 ? _payload$latestEventI : payload.latest_event_id)
|
|
4786
|
+
};
|
|
4787
|
+
}
|
|
3805
4788
|
const threadReducer = createReducer(initialThreadState, on(threadAdapterEvents.contextChanged, (state, { context }) => ({
|
|
3806
4789
|
...state,
|
|
3807
4790
|
context,
|
|
@@ -3810,6 +4793,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
3810
4793
|
isLoading: Boolean(context),
|
|
3811
4794
|
isFetchingNextPage: false,
|
|
3812
4795
|
error: null,
|
|
4796
|
+
fetchMoreError: null,
|
|
3813
4797
|
metadataCredentialsRequested: false,
|
|
3814
4798
|
metadataJoinCode: null,
|
|
3815
4799
|
nextCursor: null,
|
|
@@ -3821,6 +4805,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
3821
4805
|
isLoading: false,
|
|
3822
4806
|
isFetchingNextPage: false,
|
|
3823
4807
|
error: null,
|
|
4808
|
+
fetchMoreError: null,
|
|
3824
4809
|
metadataCredentialsRequested: false,
|
|
3825
4810
|
metadataJoinCode: null,
|
|
3826
4811
|
nextCursor: null,
|
|
@@ -3831,16 +4816,20 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
3831
4816
|
return {
|
|
3832
4817
|
...state,
|
|
3833
4818
|
isLoading: true,
|
|
3834
|
-
error: null
|
|
4819
|
+
error: null,
|
|
4820
|
+
fetchMoreError: null
|
|
3835
4821
|
};
|
|
3836
4822
|
}), on(threadRestEvents.listSucceeded, (state, { sessionId, threads, joinCode, nextCursor }) => {
|
|
3837
4823
|
if (sessionId !== state.sessionId) return state;
|
|
4824
|
+
const joinCodeChanged = joinCode !== state.metadataJoinCode;
|
|
3838
4825
|
return {
|
|
3839
4826
|
...state,
|
|
3840
4827
|
threads: sortThreadsByRecency(threads),
|
|
3841
4828
|
isLoading: false,
|
|
3842
4829
|
error: null,
|
|
4830
|
+
fetchMoreError: null,
|
|
3843
4831
|
metadataJoinCode: joinCode,
|
|
4832
|
+
metadataCredentialsRequested: joinCodeChanged ? false : state.metadataCredentialsRequested,
|
|
3844
4833
|
nextCursor
|
|
3845
4834
|
};
|
|
3846
4835
|
}), on(threadRestEvents.listFailed, (state, { sessionId, error }) => {
|
|
@@ -3858,6 +4847,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
3858
4847
|
...state,
|
|
3859
4848
|
threads: merged,
|
|
3860
4849
|
isFetchingNextPage: false,
|
|
4850
|
+
fetchMoreError: null,
|
|
3861
4851
|
nextCursor
|
|
3862
4852
|
};
|
|
3863
4853
|
}), on(threadRestEvents.nextPageFailed, (state, { sessionId, error }) => {
|
|
@@ -3865,11 +4855,14 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
3865
4855
|
return {
|
|
3866
4856
|
...state,
|
|
3867
4857
|
isFetchingNextPage: false,
|
|
3868
|
-
error
|
|
4858
|
+
fetchMoreError: error
|
|
3869
4859
|
};
|
|
3870
4860
|
}), on(threadRestEvents.metadataCredentialsFailed, (state, { sessionId }) => {
|
|
3871
4861
|
if (sessionId !== state.sessionId) return state;
|
|
3872
|
-
return
|
|
4862
|
+
return {
|
|
4863
|
+
...state,
|
|
4864
|
+
metadataCredentialsRequested: false
|
|
4865
|
+
};
|
|
3873
4866
|
}), on(threadRestEvents.metadataCredentialsRequested, (state, { sessionId }) => {
|
|
3874
4867
|
if (sessionId !== state.sessionId) return state;
|
|
3875
4868
|
return {
|
|
@@ -3880,7 +4873,8 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
3880
4873
|
if (!state.nextCursor || state.isFetchingNextPage) return state;
|
|
3881
4874
|
return {
|
|
3882
4875
|
...state,
|
|
3883
|
-
isFetchingNextPage: true
|
|
4876
|
+
isFetchingNextPage: true,
|
|
4877
|
+
fetchMoreError: null
|
|
3884
4878
|
};
|
|
3885
4879
|
}), on(threadAdapterEvents.renameRequested, (state, { threadId, name }) => {
|
|
3886
4880
|
const existing = state.threads.find((thread) => thread.id === threadId);
|
|
@@ -4010,6 +5004,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
4010
5004
|
threads: createSelector((state) => state.threads),
|
|
4011
5005
|
isLoading: createSelector((state) => state.isLoading),
|
|
4012
5006
|
error: createSelector((state) => state.error),
|
|
5007
|
+
fetchMoreError: createSelector((state) => state.fetchMoreError),
|
|
4013
5008
|
hasNextPage: createSelector((state) => state.nextCursor != null),
|
|
4014
5009
|
isFetchingNextPage: createSelector((state) => state.isFetchingNextPage),
|
|
4015
5010
|
isMutating: createSelector((state) => state.inFlightMutationCount > 0)
|
|
@@ -4019,6 +5014,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
4019
5014
|
const selectThreads = standaloneSelectors.threads;
|
|
4020
5015
|
const selectThreadsIsLoading = standaloneSelectors.isLoading;
|
|
4021
5016
|
const selectThreadsError = standaloneSelectors.error;
|
|
5017
|
+
const selectFetchMoreError = standaloneSelectors.fetchMoreError;
|
|
4022
5018
|
const selectHasNextPage = standaloneSelectors.hasNextPage;
|
|
4023
5019
|
const selectIsFetchingNextPage = standaloneSelectors.isFetchingNextPage;
|
|
4024
5020
|
const selectIsMutating = standaloneSelectors.isMutating;
|
|
@@ -4028,7 +5024,27 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
4028
5024
|
return `thread-request-${threadRequestId}`;
|
|
4029
5025
|
}
|
|
4030
5026
|
function threadFromFetch(input, init) {
|
|
4031
|
-
return
|
|
5027
|
+
return new rxjs.Observable((subscriber) => {
|
|
5028
|
+
const { fetch: fetchImpl, selector, signal, ...requestInit } = init;
|
|
5029
|
+
const controller = new AbortController();
|
|
5030
|
+
const abortRequest = () => controller.abort();
|
|
5031
|
+
if (signal === null || signal === void 0 ? void 0 : signal.aborted) abortRequest();
|
|
5032
|
+
else signal === null || signal === void 0 || signal.addEventListener("abort", abortRequest, { once: true });
|
|
5033
|
+
fetchImpl(input, {
|
|
5034
|
+
...requestInit,
|
|
5035
|
+
signal: controller.signal
|
|
5036
|
+
}).then((response) => selector(response)).then((value) => {
|
|
5037
|
+
if (subscriber.closed) return;
|
|
5038
|
+
subscriber.next(value);
|
|
5039
|
+
subscriber.complete();
|
|
5040
|
+
}).catch((error) => {
|
|
5041
|
+
if (!subscriber.closed) subscriber.error(error);
|
|
5042
|
+
});
|
|
5043
|
+
return () => {
|
|
5044
|
+
signal === null || signal === void 0 || signal.removeEventListener("abort", abortRequest);
|
|
5045
|
+
abortRequest();
|
|
5046
|
+
};
|
|
5047
|
+
});
|
|
4032
5048
|
}
|
|
4033
5049
|
function createThreadFetchObservable(environment, context, sessionId) {
|
|
4034
5050
|
return (0, rxjs.defer)(() => {
|
|
@@ -4179,6 +5195,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
4179
5195
|
return (0, rxjs.merge)(socketSignals$.pipe((0, rxjs_operators.map)((signal) => signal.type === "open" ? threadSocketEvents.opened({ sessionId: action.sessionId }) : threadSocketEvents.errored({ sessionId: action.sessionId }))), channel$.pipe((0, rxjs_operators.switchMap)(({ channel }) => ɵobservePhoenixEvent$(channel, THREADS_CHANNEL_EVENT)), (0, rxjs_operators.map)((payload) => threadSocketEvents.metadataReceived({
|
|
4180
5196
|
sessionId: action.sessionId,
|
|
4181
5197
|
payload
|
|
5198
|
+
}))), channel$.pipe((0, rxjs_operators.switchMap)(({ channel }) => ɵobservePhoenixEvent$(channel, THREAD_RUN_ACTIVITY_CHANNEL_EVENT)), (0, rxjs_operators.map)((payload) => normalizeThreadRunActivityNotification(payload)), (0, rxjs_operators.filter)((notification) => notification !== null), (0, rxjs_operators.map)((notification) => threadSocketEvents.runActivityReceived({
|
|
5199
|
+
sessionId: action.sessionId,
|
|
5200
|
+
notification
|
|
4182
5201
|
}))), ɵobservePhoenixJoinOutcome$(channel$).pipe((0, rxjs_operators.filter)((outcome) => outcome.type !== "joined"), (0, rxjs_operators.map)((outcome) => outcome.type === "timeout" ? threadSocketEvents.joinTimedOut({ sessionId: action.sessionId }) : threadSocketEvents.joinFailed({ sessionId: action.sessionId })))).pipe((0, rxjs_operators.takeUntil)((0, rxjs.merge)(shutdown$, fatalSocketShutdown$)));
|
|
4183
5202
|
});
|
|
4184
5203
|
}))),
|
|
@@ -4363,6 +5382,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
4363
5382
|
threadId
|
|
4364
5383
|
}));
|
|
4365
5384
|
},
|
|
5385
|
+
subscribeToRunActivity(callback) {
|
|
5386
|
+
return store.actions$.pipe(ofType(threadSocketEvents.runActivityReceived), (0, rxjs_operators.filter)((action) => action.sessionId === store.getState().sessionId), (0, rxjs_operators.map)((action) => action.notification)).subscribe(callback);
|
|
5387
|
+
},
|
|
4366
5388
|
getState() {
|
|
4367
5389
|
return store.getState();
|
|
4368
5390
|
},
|
|
@@ -4378,6 +5400,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
4378
5400
|
const ɵselectThreads = selectThreads;
|
|
4379
5401
|
const ɵselectThreadsIsLoading = selectThreadsIsLoading;
|
|
4380
5402
|
const ɵselectThreadsError = selectThreadsError;
|
|
5403
|
+
const ɵselectFetchMoreError = selectFetchMoreError;
|
|
4381
5404
|
const ɵselectHasNextPage = selectHasNextPage;
|
|
4382
5405
|
const ɵselectIsFetchingNextPage = selectIsFetchingNextPage;
|
|
4383
5406
|
const ɵselectIsMutating = selectIsMutating;
|
|
@@ -4442,9 +5465,12 @@ exports.CopilotKitCore = CopilotKitCore;
|
|
|
4442
5465
|
exports.CopilotKitCoreErrorCode = CopilotKitCoreErrorCode;
|
|
4443
5466
|
exports.CopilotKitCoreRuntimeConnectionStatus = CopilotKitCoreRuntimeConnectionStatus;
|
|
4444
5467
|
exports.IntelligenceAgent = IntelligenceAgent;
|
|
5468
|
+
exports.MEMORY_ERROR_REGISTRY = MEMORY_ERROR_REGISTRY;
|
|
5469
|
+
exports.MemoryError = MemoryError;
|
|
4445
5470
|
exports.ProxiedCopilotRuntimeAgent = ProxiedCopilotRuntimeAgent;
|
|
4446
5471
|
exports.RunHandler = RunHandler;
|
|
4447
5472
|
exports.StateManager = StateManager;
|
|
5473
|
+
exports.SubagentRegistry = SubagentRegistry;
|
|
4448
5474
|
exports.SuggestionEngine = SuggestionEngine;
|
|
4449
5475
|
exports.ToolCallStatus = ToolCallStatus;
|
|
4450
5476
|
exports.completePartialMarkdown = completePartialMarkdown;
|
|
@@ -4463,19 +5489,33 @@ exports.props = props;
|
|
|
4463
5489
|
exports.select = select;
|
|
4464
5490
|
exports.ɵCOPILOTKIT_FEATURES = ɵCOPILOTKIT_FEATURES;
|
|
4465
5491
|
exports.ɵMAX_SOCKET_RETRIES = ɵMAX_SOCKET_RETRIES;
|
|
5492
|
+
exports.ɵcreateMemoryStore = createMemoryStore;
|
|
4466
5493
|
exports.ɵcreateThreadSelectors = ɵcreateThreadSelectors;
|
|
4467
5494
|
exports.ɵcreateThreadStore = createThreadStore;
|
|
4468
5495
|
exports.ɵisCopilotKitFeature = ɵisCopilotKitFeature;
|
|
5496
|
+
exports.ɵisRetryableMemoryStatus = isRetryableStatus;
|
|
4469
5497
|
exports.ɵjoinPhoenixChannel$ = ɵjoinPhoenixChannel$;
|
|
5498
|
+
exports.ɵmapMemoryMetadataEvent = ɵmapMemoryMetadataEvent;
|
|
5499
|
+
exports.ɵmemoryAdapterEvents = ɵmemoryAdapterEvents;
|
|
5500
|
+
exports.ɵmemoryDomainEvents = ɵmemoryDomainEvents;
|
|
5501
|
+
exports.ɵmemoryReducer = ɵmemoryReducer;
|
|
5502
|
+
exports.ɵmemoryRestEvents = ɵmemoryRestEvents;
|
|
4470
5503
|
exports.ɵobservePhoenixEvent$ = ɵobservePhoenixEvent$;
|
|
4471
5504
|
exports.ɵobservePhoenixJoinOutcome$ = ɵobservePhoenixJoinOutcome$;
|
|
4472
5505
|
exports.ɵobservePhoenixSocketHealth$ = ɵobservePhoenixSocketHealth$;
|
|
4473
5506
|
exports.ɵobservePhoenixSocketSignals$ = ɵobservePhoenixSocketSignals$;
|
|
4474
5507
|
exports.ɵphoenixChannel$ = ɵphoenixChannel$;
|
|
4475
5508
|
exports.ɵphoenixSocket$ = ɵphoenixSocket$;
|
|
5509
|
+
exports.ɵselectFetchMoreError = ɵselectFetchMoreError;
|
|
4476
5510
|
exports.ɵselectHasNextPage = ɵselectHasNextPage;
|
|
4477
5511
|
exports.ɵselectIsFetchingNextPage = ɵselectIsFetchingNextPage;
|
|
4478
5512
|
exports.ɵselectIsMutating = ɵselectIsMutating;
|
|
5513
|
+
exports.ɵselectMemories = ɵselectMemories;
|
|
5514
|
+
exports.ɵselectMemoriesAvailable = ɵselectMemoriesAvailable;
|
|
5515
|
+
exports.ɵselectMemoriesError = ɵselectMemoriesError;
|
|
5516
|
+
exports.ɵselectMemoriesIsLoading = ɵselectMemoriesIsLoading;
|
|
5517
|
+
exports.ɵselectMemoriesIsMutating = ɵselectMemoriesIsMutating;
|
|
5518
|
+
exports.ɵselectMemoriesRealtimeStatus = ɵselectMemoriesRealtimeStatus;
|
|
4479
5519
|
exports.ɵselectThreads = ɵselectThreads;
|
|
4480
5520
|
exports.ɵselectThreadsError = ɵselectThreadsError;
|
|
4481
5521
|
exports.ɵselectThreadsIsLoading = ɵselectThreadsIsLoading;
|