@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.
- package/CHANGELOG.md +24 -0
- package/README.md +13 -7
- package/dist/{CommentThread-CqZHMTsH.d.cts → CommentThread-HW4hLdsd.d.cts} +12 -2
- package/dist/{CommentThread-CqZHMTsH.d.ts → CommentThread-HW4hLdsd.d.ts} +12 -2
- package/dist/core/index.cjs +1 -1
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.js +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/react/index.cjs +132 -18
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +2 -2
- package/dist/react/index.d.ts +2 -2
- package/dist/react/index.js +132 -18
- package/dist/react/index.js.map +1 -1
- package/dist/react/lazy/index.d.cts +1 -1
- package/dist/react/lazy/index.d.ts +1 -1
- package/package.json +2 -2
package/dist/react/index.d.cts
CHANGED
|
@@ -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-
|
|
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-
|
|
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;
|
package/dist/react/index.d.ts
CHANGED
|
@@ -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-
|
|
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-
|
|
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;
|
package/dist/react/index.js
CHANGED
|
@@ -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.
|
|
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.
|
|
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 (
|
|
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
|
|
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 {
|
|
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.
|
|
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
|
-
|
|
3224
|
-
|
|
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(
|