@ai-matrx/associations 0.6.2 → 0.7.1

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.
@@ -1,7 +1,7 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode, ComponentType } from 'react';
3
- import { j as AssociationsNotifier, W as WindowShellPort, k as CapturePort, P as PickerOverrideMap, E as EntityDoorsPort, l as AuthorDisplayPort, m as AssociationsStore, n as CategoryMutationResult, o as CategoryDimension, p as PlatformCategory, q as CategoriesEntry, r as EntityTypeToken, s as UniversalCandidate, t as CandidateRecord, u as PlatformComment, v as CommentsEntry, w as CommentMutationResult, e as AssociationPickerProps, x as EntityDoorProps, y as EntityRefProps, z as ContentRole } from '../CommentThread-CqZHMTsH.cjs';
4
- export { B as AssociationCaptureToolbar, A as AssociationCaptureToolbarProps, D as AssociationCard, F as AssociationCardGrid, b as AssociationCardGridProps, a as AssociationCardProps, G as AssociationEntitySelect, H as AssociationEntitySelectAdapter, I as AssociationEntitySelectItem, c as AssociationEntitySelectProps, J as AssociationList, d as AssociationListProps, K as AssociationWindow, f as AssociationWindowProps, L as AssociationWriteResult, M as AttachedItemsSheet, g as AttachedItemsSheetProps, N as CaptureAttach, O as CaptureAttachResult, Q as CaptureToolbarAction, R as CategorySelect, C as CategorySelectProps, S as CategoryTagPicker, h as CategoryTagPickerProps, T as CommentComposer, V as CommentComposerProps, X as CommentThread, i as CommentThreadProps, Y as ContainerLink, Z as ContainerResourceRow, _ as ContainerResourcesAdapter, $ as DefaultEntityIcon, a0 as PrimaryEntity, a1 as PrimaryEntityProvider, a2 as TagPickerIcon, a3 as UniversalAssociationPicker, U as UniversalAssociationPickerProps, a4 as UseAssociationEntitySelectAdapterArgs, a5 as UseAssociationsArgs, a6 as UseAssociationsReturn, a7 as UseContainerLinksArgs, a8 as UseContainerLinksReturn, a9 as attachedKey, aa as buildCommentTree, ab as useAssociationEntitySelectAdapter, ac as useAssociations, ad as useContainerLinks, ae as useContainerLinksAdapter, af as useEntityRelationships, ag as usePrimaryEntity } from '../CommentThread-CqZHMTsH.cjs';
3
+ import { j as AssociationsNotifier, W as WindowShellPort, k as CapturePort, P as PickerOverrideMap, E as EntityDoorsPort, l as AuthorDisplayPort, m as AssociationsStore, n as CategoryMutationResult, o as CategoryDimension, p as PlatformCategory, q as CategoriesEntry, r as EntityTypeToken, s as UniversalCandidate, t as CandidateRecord, u as PlatformComment, v as CommentsEntry, w as CommentMutationResult, e as AssociationPickerProps, x as EntityDoorProps, y as EntityRefProps, z as ContentRole } from '../CommentThread-HW4hLdsd.cjs';
4
+ export { B as AssociationCaptureToolbar, A as AssociationCaptureToolbarProps, D as AssociationCard, F as AssociationCardGrid, b as AssociationCardGridProps, a as AssociationCardProps, G as AssociationEntitySelect, H as AssociationEntitySelectAdapter, I as AssociationEntitySelectItem, c as AssociationEntitySelectProps, J as AssociationList, d as AssociationListProps, K as AssociationWindow, f as AssociationWindowProps, L as AssociationWriteResult, M as AttachedItemsSheet, g as AttachedItemsSheetProps, N as CaptureAttach, O as CaptureAttachResult, Q as CaptureToolbarAction, R as CategorySelect, C as CategorySelectProps, S as CategoryTagPicker, h as CategoryTagPickerProps, T as CommentComposer, V as CommentComposerProps, X as CommentThread, i as CommentThreadProps, Y as ContainerLink, Z as ContainerResourceRow, _ as ContainerResourcesAdapter, $ as DefaultEntityIcon, a0 as PrimaryEntity, a1 as PrimaryEntityProvider, a2 as TagPickerIcon, a3 as UniversalAssociationPicker, U as UniversalAssociationPickerProps, a4 as UseAssociationEntitySelectAdapterArgs, a5 as UseAssociationsArgs, a6 as UseAssociationsReturn, a7 as UseContainerLinksArgs, a8 as UseContainerLinksReturn, a9 as attachedKey, aa as buildCommentTree, ab as useAssociationEntitySelectAdapter, ac as useAssociations, ad as useContainerLinks, ae as useContainerLinksAdapter, af as useEntityRelationships, ag as usePrimaryEntity } from '../CommentThread-HW4hLdsd.cjs';
5
5
 
6
6
  interface AssociationsUiPorts {
7
7
  notifier?: AssociationsNotifier;
@@ -1,7 +1,7 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode, ComponentType } from 'react';
3
- import { j as AssociationsNotifier, W as WindowShellPort, k as CapturePort, P as PickerOverrideMap, E as EntityDoorsPort, l as AuthorDisplayPort, m as AssociationsStore, n as CategoryMutationResult, o as CategoryDimension, p as PlatformCategory, q as CategoriesEntry, r as EntityTypeToken, s as UniversalCandidate, t as CandidateRecord, u as PlatformComment, v as CommentsEntry, w as CommentMutationResult, e as AssociationPickerProps, x as EntityDoorProps, y as EntityRefProps, z as ContentRole } from '../CommentThread-CqZHMTsH.js';
4
- export { B as AssociationCaptureToolbar, A as AssociationCaptureToolbarProps, D as AssociationCard, F as AssociationCardGrid, b as AssociationCardGridProps, a as AssociationCardProps, G as AssociationEntitySelect, H as AssociationEntitySelectAdapter, I as AssociationEntitySelectItem, c as AssociationEntitySelectProps, J as AssociationList, d as AssociationListProps, K as AssociationWindow, f as AssociationWindowProps, L as AssociationWriteResult, M as AttachedItemsSheet, g as AttachedItemsSheetProps, N as CaptureAttach, O as CaptureAttachResult, Q as CaptureToolbarAction, R as CategorySelect, C as CategorySelectProps, S as CategoryTagPicker, h as CategoryTagPickerProps, T as CommentComposer, V as CommentComposerProps, X as CommentThread, i as CommentThreadProps, Y as ContainerLink, Z as ContainerResourceRow, _ as ContainerResourcesAdapter, $ as DefaultEntityIcon, a0 as PrimaryEntity, a1 as PrimaryEntityProvider, a2 as TagPickerIcon, a3 as UniversalAssociationPicker, U as UniversalAssociationPickerProps, a4 as UseAssociationEntitySelectAdapterArgs, a5 as UseAssociationsArgs, a6 as UseAssociationsReturn, a7 as UseContainerLinksArgs, a8 as UseContainerLinksReturn, a9 as attachedKey, aa as buildCommentTree, ab as useAssociationEntitySelectAdapter, ac as useAssociations, ad as useContainerLinks, ae as useContainerLinksAdapter, af as useEntityRelationships, ag as usePrimaryEntity } from '../CommentThread-CqZHMTsH.js';
3
+ import { j as AssociationsNotifier, W as WindowShellPort, k as CapturePort, P as PickerOverrideMap, E as EntityDoorsPort, l as AuthorDisplayPort, m as AssociationsStore, n as CategoryMutationResult, o as CategoryDimension, p as PlatformCategory, q as CategoriesEntry, r as EntityTypeToken, s as UniversalCandidate, t as CandidateRecord, u as PlatformComment, v as CommentsEntry, w as CommentMutationResult, e as AssociationPickerProps, x as EntityDoorProps, y as EntityRefProps, z as ContentRole } from '../CommentThread-HW4hLdsd.js';
4
+ export { B as AssociationCaptureToolbar, A as AssociationCaptureToolbarProps, D as AssociationCard, F as AssociationCardGrid, b as AssociationCardGridProps, a as AssociationCardProps, G as AssociationEntitySelect, H as AssociationEntitySelectAdapter, I as AssociationEntitySelectItem, c as AssociationEntitySelectProps, J as AssociationList, d as AssociationListProps, K as AssociationWindow, f as AssociationWindowProps, L as AssociationWriteResult, M as AttachedItemsSheet, g as AttachedItemsSheetProps, N as CaptureAttach, O as CaptureAttachResult, Q as CaptureToolbarAction, R as CategorySelect, C as CategorySelectProps, S as CategoryTagPicker, h as CategoryTagPickerProps, T as CommentComposer, V as CommentComposerProps, X as CommentThread, i as CommentThreadProps, Y as ContainerLink, Z as ContainerResourceRow, _ as ContainerResourcesAdapter, $ as DefaultEntityIcon, a0 as PrimaryEntity, a1 as PrimaryEntityProvider, a2 as TagPickerIcon, a3 as UniversalAssociationPicker, U as UniversalAssociationPickerProps, a4 as UseAssociationEntitySelectAdapterArgs, a5 as UseAssociationsArgs, a6 as UseAssociationsReturn, a7 as UseContainerLinksArgs, a8 as UseContainerLinksReturn, a9 as attachedKey, aa as buildCommentTree, ab as useAssociationEntitySelectAdapter, ac as useAssociations, ad as useContainerLinks, ae as useContainerLinksAdapter, af as useEntityRelationships, ag as usePrimaryEntity } from '../CommentThread-HW4hLdsd.js';
5
5
 
6
6
  interface AssociationsUiPorts {
7
7
  notifier?: AssociationsNotifier;
@@ -1052,6 +1052,12 @@ import {
1052
1052
  useRef as useRef3,
1053
1053
  useState
1054
1054
  } from "react";
1055
+ function metadataRecord(metadata) {
1056
+ if (metadata === null || typeof metadata !== "object" || Array.isArray(metadata)) {
1057
+ return metadata == null ? {} : null;
1058
+ }
1059
+ return Object.fromEntries(Object.entries(metadata));
1060
+ }
1055
1061
  function useContainerLinks(args) {
1056
1062
  const { containerType, containerId, orgId } = args;
1057
1063
  const store = useAssociationsStore();
@@ -1173,6 +1179,31 @@ function useContainerLinks(args) {
1173
1179
  }
1174
1180
  return result;
1175
1181
  };
1182
+ const setPinned = async (token, resourceId, pinned, role) => {
1183
+ if (!containerId) return { ok: false, error: "Missing container id" };
1184
+ const exactRole = role ?? null;
1185
+ const link = incoming.find(
1186
+ (candidate) => candidate.token === token && candidate.resourceId === resourceId && candidate.role === exactRole
1187
+ );
1188
+ if (!link) return { ok: false, error: "Association edge not found" };
1189
+ const currentMetadata = metadataRecord(link.metadata);
1190
+ if (!currentMetadata) {
1191
+ return {
1192
+ ok: false,
1193
+ error: "Association metadata is not an object and cannot be updated safely"
1194
+ };
1195
+ }
1196
+ return store.add({
1197
+ sourceType: token,
1198
+ sourceId: resourceId,
1199
+ targetType: containerType,
1200
+ targetId: containerId,
1201
+ ...orgId != null ? { orgId } : {},
1202
+ ...link.label != null ? { label: link.label } : {},
1203
+ ...role !== void 0 ? { role } : {},
1204
+ metadata: { ...currentMetadata, pinned }
1205
+ });
1206
+ };
1176
1207
  const reload = async () => {
1177
1208
  await Promise.all([
1178
1209
  reloadGeneric(),
@@ -1190,7 +1221,8 @@ function useContainerLinks(args) {
1190
1221
  attachedIdsFor,
1191
1222
  linksFor,
1192
1223
  attach,
1193
- detach
1224
+ detach,
1225
+ setPinned
1194
1226
  };
1195
1227
  }
1196
1228
 
@@ -1357,7 +1389,7 @@ function useUniversalEntitySearch(args) {
1357
1389
  const timer = setTimeout(async () => {
1358
1390
  if (runRef.current !== run) return;
1359
1391
  setLoading(true);
1360
- const activeTokens = tokensKey ? tokensKey.split(",") : store.registry.curatedTokens();
1392
+ const activeTokens = tokensKey ? tokensKey.split(",") : store.registry.listableTokens();
1361
1393
  let next = [];
1362
1394
  if (trimmed || emptyQueryMode === "candidates") {
1363
1395
  next = await store.candidates.searchCandidatesAcrossTokens({
@@ -2401,7 +2433,7 @@ function UniversalAssociationPicker(props) {
2401
2433
  const store = useAssociationsStore();
2402
2434
  const { pickerOverrides } = useAssociationsUiPorts();
2403
2435
  const notifier = useNotifier();
2404
- const tokens = props.tokens ?? store.registry.curatedTokens();
2436
+ const tokens = props.tokens ?? store.registry.listableTokens();
2405
2437
  const [query, setQuery] = useState8("");
2406
2438
  const [browseToken, setBrowseToken] = useState8(null);
2407
2439
  const [busyKey, setBusyKey] = useState8(null);
@@ -2577,6 +2609,9 @@ function UniversalAssociationPicker(props) {
2577
2609
  import { useEffect as useEffect10, useState as useState9 } from "react";
2578
2610
  import { cn as cn5 } from "@ai-matrx/design-system";
2579
2611
  import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
2612
+ function metadataIsPinned(metadata) {
2613
+ return metadata !== null && typeof metadata === "object" && !Array.isArray(metadata) && Reflect.get(metadata, "pinned") === true;
2614
+ }
2580
2615
  function AttachedItemsSheet(props) {
2581
2616
  const store = useAssociationsStore();
2582
2617
  const info = store.registry.getEntityInfo(props.token);
@@ -2612,7 +2647,8 @@ function AttachedItemsSheet(props) {
2612
2647
  enabled: props.open,
2613
2648
  links: props.links,
2614
2649
  ...props.onAdd ? { onAdd: props.onAdd } : {},
2615
- onDetach: props.onDetach
2650
+ onDetach: props.onDetach,
2651
+ ...props.onSetPinned ? { onSetPinned: props.onSetPinned } : {}
2616
2652
  }
2617
2653
  )
2618
2654
  }
@@ -2623,7 +2659,8 @@ function AttachedItemsBody({
2623
2659
  enabled,
2624
2660
  links,
2625
2661
  onAdd,
2626
- onDetach
2662
+ onDetach,
2663
+ onSetPinned
2627
2664
  }) {
2628
2665
  const store = useAssociationsStore();
2629
2666
  const notifier = useNotifier();
@@ -2665,11 +2702,12 @@ function AttachedItemsBody({
2665
2702
  cancelled = true;
2666
2703
  };
2667
2704
  }, [token, idKey, enabled, store]);
2668
- const detach = async (resourceId) => {
2705
+ const detach = async (link) => {
2706
+ const resourceId = link.resourceId;
2669
2707
  if (busyId) return;
2670
2708
  setBusyId(resourceId);
2671
2709
  try {
2672
- const res = await onDetach(resourceId);
2710
+ const res = await onDetach(resourceId, link.role);
2673
2711
  if (!res.ok) {
2674
2712
  notifier.error(`Couldn't detach${res.error ? `: ${res.error}` : ""}`);
2675
2713
  }
@@ -2677,6 +2715,20 @@ function AttachedItemsBody({
2677
2715
  setBusyId(null);
2678
2716
  }
2679
2717
  };
2718
+ const setPinned = async (link, pinned) => {
2719
+ if (!onSetPinned || busyId) return;
2720
+ setBusyId(link.resourceId);
2721
+ try {
2722
+ const res = await onSetPinned(link.resourceId, pinned, link.role);
2723
+ if (!res.ok) {
2724
+ notifier.error(
2725
+ `Couldn't ${pinned ? "pin" : "unpin"}${res.error ? `: ${res.error}` : ""}`
2726
+ );
2727
+ }
2728
+ } finally {
2729
+ setBusyId(null);
2730
+ }
2731
+ };
2680
2732
  return /* @__PURE__ */ jsxs7(Fragment2, { children: [
2681
2733
  titleError ? /* @__PURE__ */ jsxs7("div", { className: "mb-2 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-[12px] text-destructive", children: [
2682
2734
  "Showing names recorded at attach time \u2014 they may be out of date.",
@@ -2691,6 +2743,7 @@ function AttachedItemsBody({
2691
2743
  const missing = !titles.has(link.resourceId);
2692
2744
  const name = resolved ?? link.label ?? (missing ? null : "Untitled");
2693
2745
  const busy = busyId === link.resourceId;
2746
+ const pinned = metadataIsPinned(link.metadata);
2694
2747
  return /* @__PURE__ */ jsxs7(
2695
2748
  "li",
2696
2749
  {
@@ -2710,12 +2763,35 @@ function AttachedItemsBody({
2710
2763
  className: "text-foreground"
2711
2764
  }
2712
2765
  ) }),
2766
+ onSetPinned ? /* @__PURE__ */ jsx9(
2767
+ "button",
2768
+ {
2769
+ type: "button",
2770
+ disabled: busy,
2771
+ onClick: () => void setPinned(link, !pinned),
2772
+ title: pinned ? "Unpin (stops staying in agent context)" : "Pin \u2014 always in agent context",
2773
+ "aria-label": pinned ? "Unpin" : "Pin",
2774
+ className: cn5(
2775
+ "flex h-6 w-6 shrink-0 items-center justify-center rounded-md transition-colors hover:bg-accent hover:text-foreground disabled:opacity-50",
2776
+ pinned ? "text-primary" : "text-muted-foreground"
2777
+ ),
2778
+ children: /* @__PURE__ */ jsx9(
2779
+ PinIcon,
2780
+ {
2781
+ className: cn5(
2782
+ "h-3.5 w-3.5",
2783
+ pinned && "fill-primary/20"
2784
+ )
2785
+ }
2786
+ )
2787
+ }
2788
+ ) : null,
2713
2789
  /* @__PURE__ */ jsx9(
2714
2790
  "button",
2715
2791
  {
2716
2792
  type: "button",
2717
2793
  disabled: busy,
2718
- onClick: () => void detach(link.resourceId),
2794
+ onClick: () => void detach(link),
2719
2795
  title: "Detach",
2720
2796
  className: cn5(
2721
2797
  "flex h-6 w-6 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors",
@@ -2811,7 +2887,15 @@ function AssociationCard({
2811
2887
  const role = getContentRoleMeta(info.contentRole);
2812
2888
  const Icon = info.Icon ?? DefaultEntityIcon;
2813
2889
  const [listOpen, setListOpen] = useState10(false);
2814
- const { status, countFor, attachedIdsFor, linksFor, attach, detach } = useContainerLinks({
2890
+ const {
2891
+ status,
2892
+ countFor,
2893
+ attachedIdsFor,
2894
+ linksFor,
2895
+ attach,
2896
+ detach,
2897
+ setPinned
2898
+ } = useContainerLinks({
2815
2899
  containerType: container?.type ?? "organization",
2816
2900
  containerId: container?.id ?? null,
2817
2901
  orgId: container?.orgId ?? null
@@ -2908,7 +2992,8 @@ function AssociationCard({
2908
2992
  setOpen(true);
2909
2993
  }
2910
2994
  } : {},
2911
- onDetach: (resourceId) => detach(token, resourceId)
2995
+ onDetach: (resourceId, role2) => detach(token, resourceId, role2 ?? void 0),
2996
+ onSetPinned: (resourceId, pinned, role2) => setPinned(token, resourceId, pinned, role2 ?? void 0)
2912
2997
  }
2913
2998
  ),
2914
2999
  canAttach && /* @__PURE__ */ jsx10(
@@ -2967,6 +3052,9 @@ function AssociationCardGrid({
2967
3052
  import { useState as useState11 } from "react";
2968
3053
  import { cn as cn8, Skeleton } from "@ai-matrx/design-system";
2969
3054
  import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
3055
+ function metadataIsPinned2(metadata) {
3056
+ return metadata !== null && typeof metadata === "object" && !Array.isArray(metadata) && Reflect.get(metadata, "pinned") === true;
3057
+ }
2970
3058
  function useContainerLinksAdapter(container, tokens) {
2971
3059
  const store = useAssociationsStore();
2972
3060
  const links = useContainerLinks({
@@ -2981,6 +3069,7 @@ function useContainerLinksAdapter(container, tokens) {
2981
3069
  resourceId: l.resourceId,
2982
3070
  label: l.label,
2983
3071
  role: l.role,
3072
+ pinned: metadataIsPinned2(l.metadata),
2984
3073
  removable: true
2985
3074
  }))
2986
3075
  ) : [];
@@ -2990,11 +3079,13 @@ function useContainerLinksAdapter(container, tokens) {
2990
3079
  reload: links.reload,
2991
3080
  rows,
2992
3081
  attach: async (token, id, title) => links.attach(token, id, title),
2993
- detach: async (token, id, role) => links.detach(token, id, role)
3082
+ detach: async (token, id, role) => links.detach(token, id, role),
3083
+ setPinned: async (token, id, pinned, role) => links.setPinned(token, id, pinned, role)
2994
3084
  };
2995
3085
  }
2996
3086
  function AssociationList(props) {
2997
3087
  const store = useAssociationsStore();
3088
+ const notifier = useNotifier();
2998
3089
  const ctxEntity = usePrimaryEntity();
2999
3090
  const container = props.container ?? ctxEntity ?? null;
3000
3091
  const defaultAdapter = useContainerLinksAdapter(
@@ -3007,6 +3098,7 @@ function AssociationList(props) {
3007
3098
  const [pickerToken, setPickerToken] = useState11(null);
3008
3099
  const [showUniversal, setShowUniversal] = useState11(false);
3009
3100
  const [removingKeys, setRemovingKeys] = useState11(/* @__PURE__ */ new Set());
3101
+ const [pinningKeys, setPinningKeys] = useState11(/* @__PURE__ */ new Set());
3010
3102
  const rows = tokenFilter ? adapter.rows.filter((r) => tokenFilter.includes(r.token)) : adapter.rows;
3011
3103
  const visibleRows = rows.filter((r) => !removingKeys.has(r.key));
3012
3104
  const { titleFor } = useEntityTitles(
@@ -3030,6 +3122,31 @@ function AssociationList(props) {
3030
3122
  });
3031
3123
  return res;
3032
3124
  };
3125
+ const handlePin = async (row, pinned) => {
3126
+ if (!adapter.setPinned) return;
3127
+ const info = store.registry.tryGetEntityInfo(row.token);
3128
+ if (!info) return;
3129
+ setPinningKeys((prev) => new Set(prev).add(row.key));
3130
+ try {
3131
+ const res = await adapter.setPinned(
3132
+ info.token,
3133
+ row.resourceId,
3134
+ pinned,
3135
+ row.role ?? void 0
3136
+ );
3137
+ if (!res.ok) {
3138
+ notifier.error(
3139
+ `Couldn't ${pinned ? "pin" : "unpin"} resource${res.error ? `: ${res.error}` : ""}`
3140
+ );
3141
+ }
3142
+ } finally {
3143
+ setPinningKeys((prev) => {
3144
+ const next = new Set(prev);
3145
+ next.delete(row.key);
3146
+ return next;
3147
+ });
3148
+ }
3149
+ };
3033
3150
  const openRow = (row) => {
3034
3151
  if (props.openEntity) {
3035
3152
  props.openEntity(row.token, row.resourceId);
@@ -3043,7 +3160,7 @@ function AssociationList(props) {
3043
3160
  };
3044
3161
  const grouped = groupRows(store, visibleRows);
3045
3162
  const isLoading = adapter.status === "loading" || adapter.status === "idle";
3046
- const attachableTokens = tokenFilter ?? store.registry.curatedTokens();
3163
+ const attachableTokens = tokenFilter ?? store.registry.listableTokens();
3047
3164
  return /* @__PURE__ */ jsxs10("div", { className: cn8("flex flex-col gap-2 text-foreground", props.className), children: [
3048
3165
  /* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between gap-2 px-1", children: [
3049
3166
  /* @__PURE__ */ jsxs10("h3", { className: "flex items-center gap-1.5 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: [
@@ -3220,18 +3337,15 @@ function AssociationList(props) {
3220
3337
  "button",
3221
3338
  {
3222
3339
  type: "button",
3223
- onClick: () => void adapter.setPinned?.(
3224
- info.token,
3225
- row.resourceId,
3226
- !(row.pinned ?? false)
3227
- ),
3340
+ disabled: pinningKeys.has(row.key),
3341
+ onClick: () => void handlePin(row, !(row.pinned ?? false)),
3228
3342
  title: row.pinned ? "Unpin (stops staying in agent context)" : "Pin \u2014 always in agent context",
3229
3343
  "aria-label": row.pinned ? "Unpin" : "Pin",
3230
3344
  className: cn8(
3231
3345
  "shrink-0 rounded p-0.5 transition-colors hover:!text-foreground",
3232
3346
  row.pinned ? "text-primary" : "text-muted-foreground/0 group-hover:text-muted-foreground"
3233
3347
  ),
3234
- children: /* @__PURE__ */ jsx12(
3348
+ children: pinningKeys.has(row.key) ? /* @__PURE__ */ jsx12(SpinnerIcon, { className: "h-3 w-3 animate-spin" }) : /* @__PURE__ */ jsx12(
3235
3349
  PinIcon,
3236
3350
  {
3237
3351
  className: cn8(