@copilotkit/core 1.64.2-canary.1785346263 → 1.64.2-canary.1785366148

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 CHANGED
@@ -1772,6 +1772,24 @@ const MAX_FOLLOW_UP_DEPTH = 100;
1772
1772
  var RunHandler = class {
1773
1773
  _tools = [];
1774
1774
  /**
1775
+ * The full list of A2UI catalog components registered by the provider.
1776
+ * Order is preserved for display in the inspector.
1777
+ */
1778
+ _catalogComponents = [];
1779
+ /**
1780
+ * Names of catalog components the caller has explicitly disabled. A name
1781
+ * absent from this set is enabled (default). Survives re-registration so a
1782
+ * catalog identity change does not silently re-enable a disabled component.
1783
+ */
1784
+ _disabledCatalogComponents = /* @__PURE__ */ new Set();
1785
+ /**
1786
+ * Keys of frontend tools explicitly disabled at runtime via the Inspector's
1787
+ * Capabilities tool (`setToolEnabled`). Kept independently of each tool's own
1788
+ * `available` flag so a hook re-registering the tool (which resets
1789
+ * `available`) does not clobber the override. Key = `capabilityKey(name, agentId)`.
1790
+ */
1791
+ _disabledToolKeys = /* @__PURE__ */ new Set();
1792
+ /**
1775
1793
  * Tracks whether the current run (including in-flight tool execution)
1776
1794
  * has been aborted via `stopAgent()` or `agent.abortRun()`. Created
1777
1795
  * fresh in `runAgent()`, aborted by `abortCurrentRun()`.
@@ -1886,6 +1904,32 @@ var RunHandler = class {
1886
1904
  this._tools = [...tools];
1887
1905
  }
1888
1906
  /**
1907
+ * Return the registered A2UI catalog components (readonly).
1908
+ */
1909
+ get catalogComponents() {
1910
+ return this._catalogComponents;
1911
+ }
1912
+ /**
1913
+ * Replace the registered catalog component list. Preserves the disabled set
1914
+ * (by name) so re-registration does not re-enable disabled components.
1915
+ */
1916
+ setCatalogComponents(components) {
1917
+ this._catalogComponents = [...components];
1918
+ }
1919
+ /**
1920
+ * Enable or disable a catalog component by name.
1921
+ */
1922
+ setCatalogComponentEnabled(name, enabled) {
1923
+ if (enabled) this._disabledCatalogComponents.delete(name);
1924
+ else this._disabledCatalogComponents.add(name);
1925
+ }
1926
+ /**
1927
+ * Whether a catalog component is enabled. Unknown names default to enabled.
1928
+ */
1929
+ isCatalogComponentEnabled(name) {
1930
+ return !this._disabledCatalogComponents.has(name);
1931
+ }
1932
+ /**
1889
1933
  * Connect an agent (establish initial connection)
1890
1934
  */
1891
1935
  async connectAgent({ agent }) {
@@ -2350,11 +2394,30 @@ var RunHandler = class {
2350
2394
  error: handlerResult.error
2351
2395
  };
2352
2396
  }
2397
+ /** Stable identity for a tool override: agent-scope + name (NUL-separated). */
2398
+ capabilityKey(name, agentId) {
2399
+ return `${agentId ?? ""}\u0000${name}`;
2400
+ }
2401
+ /**
2402
+ * Enable/disable a registered frontend tool at runtime without unregistering
2403
+ * it. A disabled tool is omitted from {@link buildFrontendTools}, so the agent
2404
+ * never receives it. Unlike the per-tool `available` flag, this override
2405
+ * survives the tool being re-registered.
2406
+ */
2407
+ setToolEnabled(name, enabled, agentId) {
2408
+ const key = this.capabilityKey(name, agentId);
2409
+ if (enabled) this._disabledToolKeys.delete(key);
2410
+ else this._disabledToolKeys.add(key);
2411
+ }
2412
+ /** Whether a tool is currently enabled (not overridden off). Defaults true. */
2413
+ isToolEnabled(name, agentId) {
2414
+ return !this._disabledToolKeys.has(this.capabilityKey(name, agentId));
2415
+ }
2353
2416
  /**
2354
2417
  * Build frontend tools for an agent
2355
2418
  */
2356
2419
  buildFrontendTools(agentId) {
2357
- return this._tools.filter((tool) => tool.available !== false && tool.available !== "disabled" && (!tool.agentId || tool.agentId === agentId)).map((tool) => ({
2420
+ return this._tools.filter((tool) => tool.available !== false && tool.available !== "disabled" && (!tool.agentId || tool.agentId === agentId) && this.isToolEnabled(tool.name, tool.agentId)).map((tool) => ({
2358
2421
  name: tool.name,
2359
2422
  description: tool.description ?? "",
2360
2423
  parameters: createToolSchema(tool)
@@ -2995,6 +3058,13 @@ const MEMORY_ERROR_REGISTRY = Object.freeze({
2995
3058
  message: "Failed to fetch memories",
2996
3059
  docsPath: "docs/errors/memory.md#memory_list_failed"
2997
3060
  },
3061
+ MEMORY_RECALL_FAILED: {
3062
+ code: "MEMORY_RECALL_FAILED",
3063
+ category: "dependency",
3064
+ retryable: true,
3065
+ message: "Failed to recall memories",
3066
+ docsPath: "docs/errors/memory.md#memory_recall_failed"
3067
+ },
2998
3068
  MEMORY_CREDENTIALS_FAILED: {
2999
3069
  code: "MEMORY_CREDENTIALS_FAILED",
3000
3070
  category: "dependency",
@@ -3068,6 +3138,7 @@ function isRetryableStatus(status) {
3068
3138
  //#region src/memory.ts
3069
3139
  const MEMORIES_PATH = "/memories";
3070
3140
  const MEMORIES_SUBSCRIBE_PATH = "/memories/subscribe";
3141
+ const MEMORIES_RECALL_PATH = "/memories/recall";
3071
3142
  const REQUEST_TIMEOUT_MS$1 = 15e3;
3072
3143
  /** Consecutive socket errors tolerated before the realtime stream gives up. */
3073
3144
  const MAX_SOCKET_RETRIES$1 = 5;
@@ -3282,10 +3353,12 @@ function memoryFromFetch(input, init) {
3282
3353
  return (0, rxjs_fetch.fromFetch)(input, init);
3283
3354
  }
3284
3355
  /**
3285
- * Fetches the memory snapshot and maps it to a success/failure action. Keeps
3286
- * only user-scoped memories (v1 surfaces user scope only; the realtime stream
3287
- * is user-scoped too), so project-scoped rows visible to the caller are
3288
- * dropped from the store.
3356
+ * Fetches the memory snapshot and maps it to a success/failure action. Both
3357
+ * user- and project-scoped rows are kept: the store now opens a second
3358
+ * `project_meta:memories:<code>` realtime channel (when project credentials are
3359
+ * available) that keeps project rows in sync, so surfacing them in the snapshot
3360
+ * no longer risks a stale list. Rows are keyed by id across both channels, so
3361
+ * realtime deltas reconcile either scope idempotently.
3289
3362
  */
3290
3363
  function createMemoryFetchObservable(environment, context, sessionId) {
3291
3364
  return (0, rxjs.defer)(() => {
@@ -3311,7 +3384,7 @@ function createMemoryFetchObservable(environment, context, sessionId) {
3311
3384
  }
3312
3385
  }), (0, rxjs_operators.map)((data) => memoryRestEvents.listSucceeded({
3313
3386
  sessionId,
3314
- memories: data.memories.filter((memory) => memory.scope === "user")
3387
+ memories: data.memories
3315
3388
  })), (0, rxjs_operators.catchError)((error) => {
3316
3389
  if (error instanceof MemoryRouteUnavailableError) return (0, rxjs.of)(memoryRestEvents.listUnavailable({ sessionId }));
3317
3390
  return (0, rxjs.of)(memoryRestEvents.listFailed({
@@ -3354,10 +3427,15 @@ function createMemoryCredentialsFetchObservable(environment, context, sessionId)
3354
3427
  }), (0, rxjs_operators.map)((data) => {
3355
3428
  if (typeof data.joinToken !== "string" || data.joinToken.length === 0) throw new Error("missing joinToken");
3356
3429
  if (typeof data.joinCode !== "string" || data.joinCode.length === 0) throw new Error("missing joinCode");
3430
+ const hasProjectCreds = typeof data.projectJoinToken === "string" && data.projectJoinToken.length > 0 && typeof data.projectJoinCode === "string" && data.projectJoinCode.length > 0;
3357
3431
  return memoryRestEvents.credentialsSucceeded({
3358
3432
  sessionId,
3359
3433
  joinToken: data.joinToken,
3360
- joinCode: data.joinCode
3434
+ joinCode: data.joinCode,
3435
+ ...hasProjectCreds ? {
3436
+ projectJoinToken: data.projectJoinToken,
3437
+ projectJoinCode: data.projectJoinCode
3438
+ } : {}
3361
3439
  });
3362
3440
  }), (0, rxjs_operators.catchError)((error) => {
3363
3441
  if (error instanceof MemoryRouteUnavailableError) return (0, rxjs.of)(memoryRestEvents.credentialsUnavailable({ sessionId }));
@@ -3378,6 +3456,21 @@ function responseToMemory(data) {
3378
3456
  invalidatedAt: data.invalidatedAt
3379
3457
  };
3380
3458
  }
3459
+ /**
3460
+ * Projects a recall REST response memory (which carries a relevance `score`)
3461
+ * to the public {@link Memory} shape. `score` is copied through when supplied.
3462
+ */
3463
+ function recallResponseToMemory(data) {
3464
+ return {
3465
+ id: data.id,
3466
+ kind: data.kind,
3467
+ scope: data.scope,
3468
+ content: data.content,
3469
+ sourceThreadIds: data.sourceThreadIds,
3470
+ invalidatedAt: data.invalidatedAt,
3471
+ ...typeof data.score === "number" ? { score: data.score } : {}
3472
+ };
3473
+ }
3381
3474
  const MEMORY_KINDS = new Set([
3382
3475
  "topical",
3383
3476
  "episodic",
@@ -3566,9 +3659,32 @@ function createMemoryStore(environment) {
3566
3659
  return action.sessionId === state.sessionId && Boolean(state.context?.wsUrl);
3567
3660
  }), (0, rxjs_operators.switchMap)(([action, state]) => {
3568
3661
  const context = state.context;
3569
- const { joinToken, joinCode } = action;
3662
+ const { joinToken, joinCode, projectJoinToken, projectJoinCode } = action;
3570
3663
  const sessionId = action.sessionId;
3571
3664
  const shutdown$ = actions$.pipe(ofType(memoryAdapterEvents.contextChanged, memoryAdapterEvents.stopped));
3665
+ const channelMetadata$ = (channelJoinToken, topic) => {
3666
+ const channel$ = ɵphoenixChannel$({
3667
+ socket$: ɵphoenixSocket$({
3668
+ url: context.wsUrl,
3669
+ options: {
3670
+ params: { join_token: channelJoinToken },
3671
+ reconnectAfterMs: (0, _copilotkit_shared.phoenixExponentialBackoff)(100, 1e4),
3672
+ rejoinAfterMs: (0, _copilotkit_shared.phoenixExponentialBackoff)(1e3, 3e4)
3673
+ }
3674
+ }).pipe((0, rxjs_operators.shareReplay)({
3675
+ bufferSize: 1,
3676
+ refCount: true
3677
+ })),
3678
+ topic
3679
+ }).pipe((0, rxjs_operators.shareReplay)({
3680
+ bufferSize: 1,
3681
+ refCount: true
3682
+ }));
3683
+ return (0, rxjs.merge)(channel$.pipe((0, rxjs_operators.switchMap)(({ channel }) => ɵobservePhoenixEvent$(channel, MEMORY_METADATA_EVENT)), (0, rxjs_operators.map)((event) => mapMemoryMetadataEvent(event, sessionId))), ɵjoinPhoenixChannel$(channel$).pipe((0, rxjs_operators.catchError)((error) => {
3684
+ console.warn(`[memory] failed to join ${topic}`, error);
3685
+ return rxjs.EMPTY;
3686
+ })));
3687
+ };
3572
3688
  return (0, rxjs.defer)(() => {
3573
3689
  const socket$ = ɵphoenixSocket$({
3574
3690
  url: context.wsUrl,
@@ -3598,7 +3714,8 @@ function createMemoryStore(environment) {
3598
3714
  console.warn(`[memory] failed to join user_meta:memories:${joinCode}`, error);
3599
3715
  return (0, rxjs.of)(memoryDomainEvents.realtimeUnavailable({ sessionId }));
3600
3716
  }));
3601
- 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)(() => {}));
3717
+ const projectMetadata$ = projectJoinToken && projectJoinCode ? channelMetadata$(projectJoinToken, `project_meta:memories:${projectJoinCode}`) : rxjs.EMPTY;
3718
+ return (0, rxjs.merge)((0, rxjs.of)(memoryDomainEvents.realtimeConnecting({ sessionId })), metadata$, join$, projectMetadata$, fatalStatus$).pipe((0, rxjs_operators.takeUntil)((0, rxjs.merge)(shutdown$, fatalSocketShutdown$.pipe((0, rxjs.observeOn)(rxjs.asapScheduler)))), (0, rxjs_operators.finalize)(() => {}));
3602
3719
  });
3603
3720
  })))
3604
3721
  ]
@@ -3640,6 +3757,34 @@ function createMemoryStore(environment) {
3640
3757
  store.dispatch(memoryRestEvents.listRequested({ sessionId }));
3641
3758
  return done;
3642
3759
  },
3760
+ recall(query, opts) {
3761
+ const { context } = store.getState();
3762
+ if (!context?.runtimeUrl) return Promise.reject(/* @__PURE__ */ new Error("Runtime URL is not configured"));
3763
+ const body = { query };
3764
+ if (opts?.limit !== void 0) body.limit = opts.limit;
3765
+ if (opts?.scope !== void 0) body.scope = opts.scope;
3766
+ return (0, rxjs.firstValueFrom)(memoryFromFetch(`${context.runtimeUrl}${MEMORIES_RECALL_PATH}`, {
3767
+ selector: async (response) => {
3768
+ if (!response.ok) throw new MemoryError("MEMORY_RECALL_FAILED", {
3769
+ message: `Failed to recall memories: ${response.status}`,
3770
+ retryable: isRetryableStatus(response.status)
3771
+ });
3772
+ return await response.json();
3773
+ },
3774
+ fetch: environment.fetch,
3775
+ method: "POST",
3776
+ headers: {
3777
+ ...context.headers,
3778
+ "Content-Type": "application/json"
3779
+ },
3780
+ body: JSON.stringify(body)
3781
+ }).pipe((0, rxjs_operators.timeout)({
3782
+ first: REQUEST_TIMEOUT_MS$1,
3783
+ with: () => {
3784
+ throw new MemoryError("MEMORY_REQUEST_TIMEOUT");
3785
+ }
3786
+ }), (0, rxjs_operators.map)((data) => (data.memories ?? []).map((m) => recallResponseToMemory(m)))));
3787
+ },
3643
3788
  addMemory(input) {
3644
3789
  return trackMutation(memoryAdapterEvents.addRequested({
3645
3790
  requestId: createMemoryRequestId(),
@@ -3864,6 +4009,9 @@ var CopilotKitCore = class {
3864
4009
  get tools() {
3865
4010
  return this.runHandler.tools;
3866
4011
  }
4012
+ get catalogComponents() {
4013
+ return this.runHandler.catalogComponents;
4014
+ }
3867
4015
  get runtimeUrl() {
3868
4016
  return this.agentRegistry.runtimeUrl;
3869
4017
  }
@@ -4185,6 +4333,40 @@ var CopilotKitCore = class {
4185
4333
  this.runHandler.setTools(tools);
4186
4334
  }
4187
4335
  /**
4336
+ * Enable/disable a registered frontend tool at runtime without unregistering
4337
+ * it (Inspector "Capabilities" tool). A disabled tool is omitted from the
4338
+ * tool list sent to the agent on the next run. The override is keyed by name
4339
+ * (+ optional agentId) and survives the tool being re-registered.
4340
+ */
4341
+ setToolEnabled(name, enabled, agentId) {
4342
+ this.runHandler.setToolEnabled(name, enabled, agentId);
4343
+ }
4344
+ /** Whether a registered tool is currently enabled (defaults true). */
4345
+ isToolEnabled(name, agentId) {
4346
+ return this.runHandler.isToolEnabled(name, agentId);
4347
+ }
4348
+ /**
4349
+ * A2UI catalog component management (delegated to RunHandler).
4350
+ * Registers the full component list and controls per-component enablement.
4351
+ */
4352
+ setCatalogComponents(components) {
4353
+ this.runHandler.setCatalogComponents(components);
4354
+ this.notifySubscribers((subscriber) => subscriber.onCatalogComponentsChanged?.({
4355
+ copilotkit: this,
4356
+ catalogComponents: this.runHandler.catalogComponents
4357
+ }), "Subscriber onCatalogComponentsChanged error:");
4358
+ }
4359
+ setCatalogComponentEnabled(name, enabled) {
4360
+ this.runHandler.setCatalogComponentEnabled(name, enabled);
4361
+ this.notifySubscribers((subscriber) => subscriber.onCatalogComponentsChanged?.({
4362
+ copilotkit: this,
4363
+ catalogComponents: this.runHandler.catalogComponents
4364
+ }), "Subscriber onCatalogComponentsChanged error:");
4365
+ }
4366
+ isCatalogComponentEnabled(name) {
4367
+ return this.runHandler.isCatalogComponentEnabled(name);
4368
+ }
4369
+ /**
4188
4370
  * Subscription lifecycle
4189
4371
  */
4190
4372
  subscribe(subscriber) {