MCPcopy Index your code
hub / github.com/CopilotKit/CopilotKit / ThreadsStore

Class ThreadsStore

packages/angular/src/lib/threads.ts:210–530  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

208 * {@link DestroyRef}.
209 */
210export class ThreadsStore implements InjectThreadsResult {
211 readonly #copilotkit = inject(CopilotKit);
212 readonly #store: ɵThreadStore = ɵcreateThreadStore({
213 // Cast to `typeof fetch`: the wrapper preserves correct `this` binding for
214 // globalThis.fetch but does not re-expose static members (e.g. `preconnect`)
215 // that newer DOM libs add and that the store never calls.
216 fetch: ((...args: Parameters<typeof fetch>) =>
217 globalThis.fetch(...args)) as typeof fetch,
218 });
219 readonly #subscriptions: Subscription[] = [];
220
221 readonly #threads = signal<Thread[]>([]);
222 readonly #storeIsLoading = signal<boolean>(false);
223 readonly #storeError = signal<Error | null>(null);
224 readonly #hasMoreThreads = signal<boolean>(false);
225 readonly #isFetchingMoreThreads = signal<boolean>(false);
226 readonly #isMutating = signal<boolean>(false);
227
228 /**
229 * Tracks whether a real runtime context has been dispatched to the store
230 * yet. The store itself starts `isLoading: false`, so before the first
231 * dispatch consumers would otherwise see an empty, non-loading list (the
232 * empty-list flash). While a runtime URL is configured and the endpoints
233 * are available but no context has been dispatched, we synthesize loading.
234 */
235 readonly #hasDispatchedContext = signal<boolean>(false);
236
237 readonly threads = this.#threads.asReadonly();
238 readonly error: Signal<Error | null>;
239 readonly listError: Signal<Error | null>;
240 readonly isLoading: Signal<boolean>;
241 readonly hasMoreThreads = this.#hasMoreThreads.asReadonly();
242 readonly isFetchingMoreThreads = this.#isFetchingMoreThreads.asReadonly();
243 readonly isMutating = this.#isMutating.asReadonly();
244
245 constructor(input: InjectThreadsInput, destroyRef: DestroyRef) {
246 const agentId = toAccessor(input.agentId);
247 const includeArchived = toAccessor(input.includeArchived);
248 const limit = toAccessor(input.limit);
249 const enabled = toAccessor(input.enabled);
250 // `enabled` defaults to `true`; only an explicit `false` keeps the store
251 // inert. An unset/`undefined` input is treated as enabled.
252 const isEnabled = (): boolean => enabled() !== false;
253
254 this.#bridgeSelectors();
255 this.#store.start();
256
257 // Synthesized error/loading reconcile the core store's internal state with
258 // configuration-level conditions (no runtime URL, unavailable endpoints),
259 // mirroring react-core's useThreads.
260 const runtimeUrl = this.#copilotkit.runtimeUrl;
261 const runtimeStatus = this.#copilotkit.runtimeConnectionStatus;
262 // Read `threadEndpoints`/`intelligence.wsUrl` through the CopilotKit
263 // signals (not plain `core.*` getters) so the computeds/effect re-run when
264 // `/info` populates them — even if it lands without a connection-status
265 // transition. This mirrors react-core, which lists both in its effect deps.
266 const threadEndpoints = this.#copilotkit.threadEndpoints;
267 const threadListSupported = (): boolean =>

Callers

nothing calls this directly

Calls 3

refetchThreadsMethod · 0.80
fetchNextPageMethod · 0.65
startNewThreadMethod · 0.65

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…