@ai-matrx/agents 0.6.1 → 0.7.0

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.
@@ -0,0 +1,2340 @@
1
+ "use client";
2
+ "use client";
3
+
4
+ // catalog/react/context.tsx
5
+ import {
6
+ createContext,
7
+ useCallback,
8
+ useContext,
9
+ useMemo,
10
+ useSyncExternalStore
11
+ } from "react";
12
+ import { jsx } from "react/jsx-runtime";
13
+ var AgentCatalogContext = createContext(null);
14
+ function AgentCatalogProvider({
15
+ catalog,
16
+ children,
17
+ ...ports
18
+ }) {
19
+ const value = useMemo(
20
+ () => ({ catalog, ...ports }),
21
+ // The ports are plain values a host declares once; re-binding on identity
22
+ // change is correct and cheap.
23
+ [
24
+ catalog,
25
+ ports.navigate,
26
+ ports.LinkComponent,
27
+ ports.renderModelRef,
28
+ ports.openPeek,
29
+ ports.popoverContainer
30
+ ]
31
+ );
32
+ return /* @__PURE__ */ jsx(AgentCatalogContext.Provider, { value, children });
33
+ }
34
+ function useBinding() {
35
+ const binding = useContext(AgentCatalogContext);
36
+ if (!binding) {
37
+ throw new Error(
38
+ "@ai-matrx/agents/catalog/react: no <AgentCatalogProvider> is mounted above this component. Create the catalog once with createAgentCatalog({ client, identity }) and mount <AgentCatalogProvider catalog={catalog}> at the top of your tree."
39
+ );
40
+ }
41
+ return binding;
42
+ }
43
+ function useAgentCatalog() {
44
+ return useBinding().catalog;
45
+ }
46
+ function useAgentCatalogUiPorts() {
47
+ const binding = useBinding();
48
+ const navigate = useCallback(
49
+ (href) => {
50
+ if (binding.navigate) {
51
+ binding.navigate(href);
52
+ return;
53
+ }
54
+ if (typeof window !== "undefined") window.location.assign(href);
55
+ },
56
+ [binding.navigate]
57
+ );
58
+ return {
59
+ navigate,
60
+ LinkComponent: binding.LinkComponent ?? DefaultLink,
61
+ renderModelRef: binding.renderModelRef ?? defaultRenderModelRef,
62
+ openPeek: binding.openPeek,
63
+ popoverContainer: binding.popoverContainer
64
+ };
65
+ }
66
+ var DefaultLink = ({ children, ...props }) => /* @__PURE__ */ jsx("a", { ...props, children });
67
+ var defaultRenderModelRef = ({
68
+ modelId,
69
+ className
70
+ }) => /* @__PURE__ */ jsx("span", { className, children: modelId });
71
+ function useAgentCatalogState(select) {
72
+ const catalog = useAgentCatalog();
73
+ const getSnapshot = useCallback(
74
+ () => select(catalog.getState()),
75
+ [catalog, select]
76
+ );
77
+ return useSyncExternalStore(catalog.subscribe, getSnapshot, getSnapshot);
78
+ }
79
+ function useAgentCatalogRows() {
80
+ return useAgentCatalogState(selectRows);
81
+ }
82
+ var selectRows = (state) => state.rows;
83
+
84
+ // catalog/react/useAgentConsumer.ts
85
+ import { useCallback as useCallback2, useEffect, useRef, useState } from "react";
86
+
87
+ // catalog/types.ts
88
+ function isMandateAgentId(id) {
89
+ return id.startsWith("mandate:");
90
+ }
91
+ var AGENT_NONE_SENTINEL = "__none__";
92
+ var DEFAULT_AGENT_CONSUMER_STATE = {
93
+ tab: "mine",
94
+ sortBy: "updated-desc",
95
+ searchTerm: "",
96
+ includedCats: [],
97
+ includedTags: [],
98
+ favFilter: "all",
99
+ archFilter: "active",
100
+ accessFilter: "any",
101
+ favoritesFirst: true,
102
+ listPage: 1,
103
+ sharedPage: 1,
104
+ serverMatchedIds: [],
105
+ isServerSearching: false,
106
+ deepSearch: false
107
+ };
108
+
109
+ // catalog/react/useAgentConsumer.ts
110
+ var DEBOUNCE_MS = 250;
111
+ var MIN_QUERY_LENGTH = 2;
112
+ function useAgentConsumer(consumerId, options) {
113
+ const catalog = useAgentCatalog();
114
+ const selectConsumer = useCallback2(
115
+ (state) => state.consumers[consumerId] ?? DEFAULT_AGENT_CONSUMER_STATE,
116
+ [consumerId]
117
+ );
118
+ const consumer = useAgentCatalogState(selectConsumer);
119
+ const optionsRef = useRef(options);
120
+ optionsRef.current = options;
121
+ useEffect(() => {
122
+ const opts = optionsRef.current;
123
+ catalog.registerConsumer(
124
+ consumerId,
125
+ opts?.initialTab ? { tab: opts.initialTab } : void 0
126
+ );
127
+ return () => {
128
+ if (optionsRef.current?.unregisterOnUnmount) {
129
+ catalog.unregisterConsumer(consumerId);
130
+ }
131
+ };
132
+ }, [consumerId, catalog]);
133
+ const setSearchTerm = useCallback2(
134
+ (value) => catalog.setConsumerFilter(consumerId, { searchTerm: value }),
135
+ [consumerId, catalog]
136
+ );
137
+ const setDeepSearch = useCallback2(
138
+ (value) => catalog.setConsumerFilter(consumerId, { deepSearch: value }),
139
+ [consumerId, catalog]
140
+ );
141
+ const setSortBy = useCallback2(
142
+ (value) => catalog.setConsumerFilter(consumerId, { sortBy: value }),
143
+ [consumerId, catalog]
144
+ );
145
+ const setTab = useCallback2(
146
+ (value) => catalog.setConsumerFilter(consumerId, { tab: value }),
147
+ [consumerId, catalog]
148
+ );
149
+ const setFavFilter = useCallback2(
150
+ (value) => catalog.setConsumerFilter(consumerId, { favFilter: value }),
151
+ [consumerId, catalog]
152
+ );
153
+ const setArchFilter = useCallback2(
154
+ (value) => catalog.setConsumerFilter(consumerId, { archFilter: value }),
155
+ [consumerId, catalog]
156
+ );
157
+ const setAccessFilter = useCallback2(
158
+ (value) => catalog.setConsumerFilter(consumerId, { accessFilter: value }),
159
+ [consumerId, catalog]
160
+ );
161
+ const toggleCategory = useCallback2(
162
+ (cat) => {
163
+ const current = catalog.getConsumer(consumerId).includedCats;
164
+ const next = current.includes(cat) ? current.filter((c) => c !== cat) : [...current, cat];
165
+ catalog.setConsumerFilter(consumerId, { includedCats: next });
166
+ },
167
+ [consumerId, catalog]
168
+ );
169
+ const toggleTag = useCallback2(
170
+ (tag) => {
171
+ const current = catalog.getConsumer(consumerId).includedTags;
172
+ const next = current.includes(tag) ? current.filter((t) => t !== tag) : [...current, tag];
173
+ catalog.setConsumerFilter(consumerId, { includedTags: next });
174
+ },
175
+ [consumerId, catalog]
176
+ );
177
+ const setIncludedCats = useCallback2(
178
+ (next) => catalog.setConsumerFilter(consumerId, { includedCats: next }),
179
+ [consumerId, catalog]
180
+ );
181
+ const setIncludedTags = useCallback2(
182
+ (next) => catalog.setConsumerFilter(consumerId, { includedTags: next }),
183
+ [consumerId, catalog]
184
+ );
185
+ const toggleFavoritesFirst = useCallback2(
186
+ () => catalog.setConsumerFilter(consumerId, {
187
+ favoritesFirst: !catalog.getConsumer(consumerId).favoritesFirst
188
+ }),
189
+ [consumerId, catalog]
190
+ );
191
+ const loadMoreList = useCallback2(
192
+ () => catalog.setConsumerPage(
193
+ consumerId,
194
+ "list",
195
+ catalog.getConsumer(consumerId).listPage + 1
196
+ ),
197
+ [consumerId, catalog]
198
+ );
199
+ const loadMoreShared = useCallback2(
200
+ () => catalog.setConsumerPage(
201
+ consumerId,
202
+ "shared",
203
+ catalog.getConsumer(consumerId).sharedPage + 1
204
+ ),
205
+ [consumerId, catalog]
206
+ );
207
+ const resetFilters = useCallback2(
208
+ () => catalog.resetConsumerFilters(consumerId),
209
+ [consumerId, catalog]
210
+ );
211
+ const [isSearching, setIsSearching] = useState(false);
212
+ const [matchedIds, setMatchedIds] = useState(null);
213
+ const requestSeq = useRef(0);
214
+ const query = consumer.searchTerm;
215
+ const deep = consumer.deepSearch;
216
+ useEffect(() => {
217
+ const q = query.trim();
218
+ if (q.length < MIN_QUERY_LENGTH) {
219
+ setIsSearching(false);
220
+ setMatchedIds(null);
221
+ return void 0;
222
+ }
223
+ const seq = ++requestSeq.current;
224
+ setIsSearching(true);
225
+ const timer = setTimeout(() => {
226
+ void catalog.searchServer(q, deep).then((ids) => {
227
+ if (seq !== requestSeq.current) return;
228
+ setMatchedIds(ids);
229
+ setIsSearching(false);
230
+ }).catch((e) => {
231
+ if (seq !== requestSeq.current) return;
232
+ catalog.errorSink({
233
+ code: "server_search_failed",
234
+ message: `agent search failed: ${e instanceof Error ? e.message : String(e)}`,
235
+ context: { query: q, deep }
236
+ });
237
+ setIsSearching(false);
238
+ });
239
+ }, DEBOUNCE_MS);
240
+ return () => clearTimeout(timer);
241
+ }, [query, deep, catalog]);
242
+ useEffect(() => {
243
+ catalog.setConsumerServerSearch(consumerId, {
244
+ matchedIds: matchedIds ?? [],
245
+ isSearching
246
+ });
247
+ }, [consumerId, catalog, matchedIds, isSearching]);
248
+ const hasActiveFilters = consumer.searchTerm !== "" || consumer.includedCats.length > 0 || consumer.includedTags.length > 0 || consumer.favFilter !== "all" || consumer.archFilter !== "active" || consumer.accessFilter !== "any" || !consumer.favoritesFirst;
249
+ return {
250
+ tab: consumer.tab,
251
+ sortBy: consumer.sortBy,
252
+ searchTerm: consumer.searchTerm,
253
+ includedCats: consumer.includedCats,
254
+ includedTags: consumer.includedTags,
255
+ favFilter: consumer.favFilter,
256
+ archFilter: consumer.archFilter,
257
+ accessFilter: consumer.accessFilter,
258
+ favoritesFirst: consumer.favoritesFirst,
259
+ listPage: consumer.listPage,
260
+ sharedPage: consumer.sharedPage,
261
+ state: consumer,
262
+ hasActiveFilters,
263
+ deepSearch: consumer.deepSearch,
264
+ isServerSearching: consumer.isServerSearching,
265
+ setSearchTerm,
266
+ setDeepSearch,
267
+ setSortBy,
268
+ setTab,
269
+ setFavFilter,
270
+ setArchFilter,
271
+ setAccessFilter,
272
+ toggleCategory,
273
+ toggleTag,
274
+ setIncludedCats,
275
+ setIncludedTags,
276
+ toggleFavoritesFirst,
277
+ loadMoreList,
278
+ loadMoreShared,
279
+ resetFilters
280
+ };
281
+ }
282
+
283
+ // catalog/react/useAgentListCore.ts
284
+ import {
285
+ useCallback as useCallback3,
286
+ useEffect as useEffect2,
287
+ useMemo as useMemo2,
288
+ useRef as useRef2,
289
+ useState as useState2
290
+ } from "react";
291
+
292
+ // catalog/labels.ts
293
+ function agentListEmptyLabel(tab, labels) {
294
+ switch (tab) {
295
+ case "system":
296
+ return labels.emptySystem;
297
+ case "shared":
298
+ return labels.emptyShared;
299
+ default:
300
+ return labels.emptyDefault;
301
+ }
302
+ }
303
+ function shouldDefaultAgentListToPublicTab(args) {
304
+ if (!args.userId) return true;
305
+ if (!args.agentsLoaded) return false;
306
+ return args.ownedCount === 0;
307
+ }
308
+
309
+ // catalog/score.ts
310
+ function computeAgentSearchScore(agent, query) {
311
+ const q = query.trim().toLowerCase();
312
+ if (!q) return 0;
313
+ let score = 0;
314
+ const name = (agent.name ?? "").toLowerCase();
315
+ const desc = (agent.description ?? "").toLowerCase();
316
+ if (name === q) score += 1e4;
317
+ else if (name.startsWith(q)) score += 5e3;
318
+ else if (matchesWholeWord(name, q)) score += 3e3;
319
+ else if (name.includes(q)) score += 2e3;
320
+ if (desc === q) score += 1e3;
321
+ else if (desc.includes(q)) score += 500;
322
+ if (agent.category?.toLowerCase().includes(q)) score += 300;
323
+ if (agent.tags?.some((t) => t.toLowerCase().includes(q))) score += 300;
324
+ if (agent.modelId?.toLowerCase().includes(q)) score += 100;
325
+ if (agent.agentType?.toLowerCase().includes(q)) score += 100;
326
+ if (agent.outputFormat?.toLowerCase().includes(q)) score += 100;
327
+ const id = agent.id.toLowerCase();
328
+ if (id === q) score += 1e5;
329
+ else if (id.includes(q)) score += 5e3;
330
+ if (agent.sharedByEmail?.toLowerCase().includes(q)) score += 200;
331
+ if (score === 0 && q.includes(" ")) {
332
+ const terms = q.split(/\s+/).filter(Boolean);
333
+ let hits = 0;
334
+ let termScore = 0;
335
+ for (const term of terms) {
336
+ const inName = name.includes(term);
337
+ const matched = inName || desc.includes(term) || (agent.category?.toLowerCase().includes(term) ?? false) || (agent.tags?.some((t) => t.toLowerCase().includes(term)) ?? false);
338
+ if (matched) {
339
+ hits += 1;
340
+ termScore += inName ? 400 : 100;
341
+ }
342
+ }
343
+ if (hits === terms.length) score += termScore;
344
+ }
345
+ return score;
346
+ }
347
+ function matchesWholeWord(haystack, q) {
348
+ const escaped = q.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
349
+ return new RegExp(`\\b${escaped}\\b`).test(haystack);
350
+ }
351
+ function agentMatchesSearch(agent, query) {
352
+ return computeAgentSearchScore(agent, query) > 0;
353
+ }
354
+
355
+ // catalog/selectors.ts
356
+ function memoize1(fn) {
357
+ let lastA;
358
+ let last;
359
+ let has = false;
360
+ return (a) => {
361
+ if (!has || lastA !== a) {
362
+ last = fn(a);
363
+ lastA = a;
364
+ has = true;
365
+ }
366
+ return last;
367
+ };
368
+ }
369
+ function memoize2(fn) {
370
+ let lastA;
371
+ let lastB;
372
+ let last;
373
+ let has = false;
374
+ return (a, b) => {
375
+ if (!has || lastA !== a || lastB !== b) {
376
+ last = fn(a, b);
377
+ lastA = a;
378
+ lastB = b;
379
+ has = true;
380
+ }
381
+ return last;
382
+ };
383
+ }
384
+ function applyAgentSortComparator(a, b, sortBy) {
385
+ switch (sortBy) {
386
+ case "name-asc":
387
+ return (a.name ?? "").localeCompare(b.name ?? "");
388
+ case "name-desc":
389
+ return (b.name ?? "").localeCompare(a.name ?? "");
390
+ case "created-desc":
391
+ return +new Date(b.createdAt ?? 0) - +new Date(a.createdAt ?? 0);
392
+ case "category-asc":
393
+ return (a.category ?? "").localeCompare(b.category ?? "");
394
+ case "updated-desc":
395
+ default:
396
+ return +new Date(b.updatedAt ?? 0) - +new Date(a.updatedAt ?? 0);
397
+ }
398
+ }
399
+ var selectAllAgentCategories = memoize1(
400
+ (agents) => {
401
+ const cats = /* @__PURE__ */ new Set();
402
+ for (const a of agents) {
403
+ if (a.agentType === "user" && a.category) cats.add(a.category);
404
+ }
405
+ return Array.from(cats).sort();
406
+ }
407
+ );
408
+ var selectAllSystemAgentCategories = memoize1(
409
+ (agents) => {
410
+ const cats = /* @__PURE__ */ new Set();
411
+ for (const a of agents) {
412
+ if (a.agentType === "builtin" && a.category) cats.add(a.category);
413
+ }
414
+ return Array.from(cats).sort();
415
+ }
416
+ );
417
+ var selectAllAgentTags = memoize1(
418
+ (agents) => {
419
+ const tags = /* @__PURE__ */ new Set();
420
+ for (const a of agents) {
421
+ if (a.agentType === "user") a.tags?.forEach((t) => tags.add(t));
422
+ }
423
+ return Array.from(tags).sort();
424
+ }
425
+ );
426
+ var selectAllSystemAgentTags = memoize1(
427
+ (agents) => {
428
+ const tags = /* @__PURE__ */ new Set();
429
+ for (const a of agents) {
430
+ if (a.agentType === "builtin") a.tags?.forEach((t) => tags.add(t));
431
+ }
432
+ return Array.from(tags).sort();
433
+ }
434
+ );
435
+ var selectUserTypeAgents = memoize1(
436
+ (agents) => agents.filter((a) => a.agentType === "user")
437
+ );
438
+ var selectBuiltinTypeAgents = memoize1(
439
+ (agents) => agents.filter((a) => a.agentType === "builtin")
440
+ );
441
+ function sortFilteredAgents(filtered, consumer) {
442
+ const { searchTerm, sortBy, favFilter, favoritesFirst } = consumer;
443
+ if (searchTerm) {
444
+ const scores = /* @__PURE__ */ new Map();
445
+ filtered.forEach((a) => {
446
+ scores.set(a.id, computeAgentSearchScore(a, searchTerm));
447
+ });
448
+ const serverRank = /* @__PURE__ */ new Map();
449
+ consumer.serverMatchedIds.forEach((id, i) => serverRank.set(id, i));
450
+ return [...filtered].sort((a, b) => {
451
+ const sa = scores.get(a.id) ?? 0;
452
+ const sb = scores.get(b.id) ?? 0;
453
+ if (sb !== sa) return sb - sa;
454
+ if (sa === 0) {
455
+ const ra = serverRank.get(a.id);
456
+ const rb = serverRank.get(b.id);
457
+ if (ra !== void 0 && rb !== void 0 && ra !== rb) return ra - rb;
458
+ }
459
+ return applyAgentSortComparator(a, b, sortBy);
460
+ });
461
+ }
462
+ return [...filtered].sort((a, b) => {
463
+ if (favoritesFirst && favFilter === "all") {
464
+ const aFav = a.isFavorite ? 1 : 0;
465
+ const bFav = b.isFavorite ? 1 : 0;
466
+ if (bFav !== aFav) return bFav - aFav;
467
+ }
468
+ return applyAgentSortComparator(a, b, sortBy);
469
+ });
470
+ }
471
+ function filterUserTypeAgents(agents, consumer) {
472
+ const {
473
+ searchTerm,
474
+ includedCats,
475
+ includedTags,
476
+ favFilter,
477
+ archFilter,
478
+ accessFilter,
479
+ tab
480
+ } = consumer;
481
+ const serverMatched = new Set(consumer.serverMatchedIds);
482
+ const filtered = agents.filter((agent) => {
483
+ if (tab === "mine" && agent.isOwner !== true) return false;
484
+ if (tab === "shared" && !(agent.isOwner === false && agent.accessLevel != null))
485
+ return false;
486
+ if (archFilter === "active" && agent.isArchived) return false;
487
+ if (archFilter === "archived" && !agent.isArchived) return false;
488
+ if (favFilter === "yes" && !agent.isFavorite) return false;
489
+ if (favFilter === "no" && agent.isFavorite) return false;
490
+ if (accessFilter === "owned" && agent.isOwner !== true) return false;
491
+ if (accessFilter === "shared" && agent.isOwner !== false) return false;
492
+ if (accessFilter === "editable" && agent.accessLevel !== "owner" && agent.accessLevel !== "admin" && agent.accessLevel !== "editor")
493
+ return false;
494
+ if (includedCats.length > 0) {
495
+ const category = agent.category;
496
+ if (!category) {
497
+ if (!includedCats.includes(AGENT_NONE_SENTINEL)) return false;
498
+ } else if (!includedCats.includes(category)) {
499
+ return false;
500
+ }
501
+ }
502
+ if (includedTags.length > 0) {
503
+ const isUntagged = !agent.tags?.length;
504
+ if (isUntagged) {
505
+ if (!includedTags.includes(AGENT_NONE_SENTINEL)) return false;
506
+ } else if (!agent.tags?.some((t) => includedTags.includes(t))) {
507
+ return false;
508
+ }
509
+ }
510
+ if (searchTerm && !agentMatchesSearch(agent, searchTerm) && !serverMatched.has(agent.id))
511
+ return false;
512
+ return true;
513
+ });
514
+ return sortFilteredAgents(filtered, consumer);
515
+ }
516
+ function filterBuiltinTypeAgents(agents, consumer) {
517
+ const { searchTerm, favFilter, includedCats, includedTags } = consumer;
518
+ const serverMatched = new Set(consumer.serverMatchedIds);
519
+ const filtered = agents.filter((agent) => {
520
+ if (favFilter === "yes" && !agent.isFavorite) return false;
521
+ if (favFilter === "no" && agent.isFavorite) return false;
522
+ if (includedCats.length > 0) {
523
+ const category = agent.category;
524
+ if (!category) {
525
+ if (!includedCats.includes(AGENT_NONE_SENTINEL)) return false;
526
+ } else if (!includedCats.includes(category)) {
527
+ return false;
528
+ }
529
+ }
530
+ if (includedTags.length > 0) {
531
+ const isUntagged = !agent.tags?.length;
532
+ if (isUntagged) {
533
+ if (!includedTags.includes(AGENT_NONE_SENTINEL)) return false;
534
+ } else if (!agent.tags?.some((t) => includedTags.includes(t))) {
535
+ return false;
536
+ }
537
+ }
538
+ if (searchTerm && !agentMatchesSearch(agent, searchTerm) && !serverMatched.has(agent.id))
539
+ return false;
540
+ return true;
541
+ });
542
+ return sortFilteredAgents(filtered, consumer);
543
+ }
544
+ var makeSelectFilteredAgents = (includeSystemInAll = false) => memoize2(
545
+ (agents, consumer) => {
546
+ const userAgents = selectUserTypeAgents(agents);
547
+ const builtinAgents = selectBuiltinTypeAgents(agents);
548
+ if (consumer.tab === "system") {
549
+ return filterBuiltinTypeAgents(builtinAgents, consumer);
550
+ }
551
+ if (includeSystemInAll && consumer.tab === "all") {
552
+ return [
553
+ ...filterUserTypeAgents(userAgents, consumer),
554
+ ...filterBuiltinTypeAgents(builtinAgents, consumer)
555
+ ];
556
+ }
557
+ return filterUserTypeAgents(userAgents, consumer);
558
+ }
559
+ );
560
+ var selectTotalUserAgentsCount = memoize1(
561
+ (agents) => selectUserTypeAgents(agents).length
562
+ );
563
+ var selectTotalOwnedAgentsCount = memoize1(
564
+ (agents) => selectUserTypeAgents(agents).filter((a) => a.isOwner === true).length
565
+ );
566
+ var selectTotalSharedAgentsCount = memoize1(
567
+ (agents) => selectUserTypeAgents(agents).filter(
568
+ (a) => a.isOwner === false && a.accessLevel != null
569
+ ).length
570
+ );
571
+ var selectTotalBuiltinAgentsCount = memoize1(
572
+ (agents) => selectBuiltinTypeAgents(agents).length
573
+ );
574
+ var selectTotalFavoriteAgentsCount = memoize1(
575
+ (agents) => selectUserTypeAgents(agents).filter((a) => a.isFavorite).length
576
+ );
577
+
578
+ // catalog/react/useAgentListCore.ts
579
+ var HOVER_GRACE_MS = 900;
580
+ function coerceVisibleTab(current, allowed, initialTab) {
581
+ if (allowed.length === 0) return null;
582
+ if (allowed.includes(current)) return null;
583
+ return initialTab && allowed.includes(initialTab) ? initialTab : allowed[0] ?? null;
584
+ }
585
+ var EMPTY_EXCLUDES = [];
586
+ function useAgentListCore({
587
+ consumerId,
588
+ onSelect,
589
+ navigateTo,
590
+ activeAgentIdOverride,
591
+ initialTab,
592
+ includeSystemInAll = false,
593
+ visibleTabs,
594
+ excludeAgentIds = EMPTY_EXCLUDES,
595
+ defaultMandateKey
596
+ }) {
597
+ const catalog = useAgentCatalog();
598
+ const { navigate } = useAgentCatalogUiPorts();
599
+ const hasFetchedRef = useRef2(false);
600
+ const [hoveredAgent, setHoveredAgent] = useState2(null);
601
+ const hoverLeaveTimerRef = useRef2(null);
602
+ const defaultTabAppliedRef = useRef2(false);
603
+ const consumer = useAgentConsumer(consumerId, { unregisterOnUnmount: true });
604
+ const rows = useAgentCatalogRows();
605
+ const userId = catalog.getUserIdOrNull();
606
+ const ownedCount = selectTotalOwnedAgentsCount(rows);
607
+ const selectFiltered = useMemo2(
608
+ () => makeSelectFilteredAgents(includeSystemInAll),
609
+ [includeSystemInAll]
610
+ );
611
+ const filteredAgents = selectFiltered(rows, consumer.state);
612
+ const excludedAgentIds = useMemo2(
613
+ () => new Set(excludeAgentIds),
614
+ [excludeAgentIds]
615
+ );
616
+ const agents = excludedAgentIds.size === 0 ? filteredAgents : filteredAgents.filter((agent) => !excludedAgentIds.has(agent.id));
617
+ const status = useAgentCatalogState(selectStatus);
618
+ const activeAgentId = activeAgentIdOverride ?? null;
619
+ const pinnedAgent = activeAgentId ? catalog.getAgent(activeAgentId) : void 0;
620
+ const onSystemTab = consumer.tab === "system";
621
+ const allCategories = onSystemTab ? selectAllSystemAgentCategories(rows) : selectAllAgentCategories(rows);
622
+ const allTags = onSystemTab ? selectAllSystemAgentTags(rows) : selectAllAgentTags(rows);
623
+ const tabCounts = {
624
+ mine: ownedCount,
625
+ shared: selectTotalSharedAgentsCount(rows),
626
+ all: selectTotalUserAgentsCount(rows),
627
+ system: selectTotalBuiltinAgentsCount(rows)
628
+ };
629
+ const isLoading = status === "loading";
630
+ const agentsLoaded = status === "succeeded" || status === "failed";
631
+ const ensureLoaded = useCallback3(() => {
632
+ if (!hasFetchedRef.current) {
633
+ hasFetchedRef.current = true;
634
+ void catalog.ensureLoaded().catch(() => {
635
+ });
636
+ }
637
+ }, [catalog]);
638
+ const selectDefaultRow = useCallback3(
639
+ (state) => defaultMandateKey ? state.defaultRows[defaultMandateKey] : void 0,
640
+ [defaultMandateKey]
641
+ );
642
+ const defaultRow = useAgentCatalogState(selectDefaultRow);
643
+ useEffect2(() => {
644
+ if (!defaultMandateKey) return;
645
+ catalog.ensureDefaultRow(defaultMandateKey);
646
+ }, [catalog, defaultMandateKey]);
647
+ useEffect2(() => {
648
+ if (defaultTabAppliedRef.current) return;
649
+ if (initialTab) {
650
+ defaultTabAppliedRef.current = true;
651
+ if (consumer.tab !== initialTab) consumer.setTab(initialTab);
652
+ return;
653
+ }
654
+ if (consumer.tab !== "mine") {
655
+ defaultTabAppliedRef.current = true;
656
+ return;
657
+ }
658
+ const wantsPublic = shouldDefaultAgentListToPublicTab({
659
+ userId,
660
+ ownedCount,
661
+ agentsLoaded
662
+ });
663
+ if (!wantsPublic) {
664
+ if (!userId || agentsLoaded) {
665
+ defaultTabAppliedRef.current = true;
666
+ }
667
+ return;
668
+ }
669
+ consumer.setTab("system");
670
+ defaultTabAppliedRef.current = true;
671
+ }, [
672
+ userId,
673
+ ownedCount,
674
+ agentsLoaded,
675
+ initialTab,
676
+ consumer.tab,
677
+ consumer.setTab
678
+ ]);
679
+ const allowedTabsKey = visibleTabs ? visibleTabs.join(",") : "";
680
+ useEffect2(() => {
681
+ if (!allowedTabsKey) return;
682
+ const next = coerceVisibleTab(
683
+ consumer.tab,
684
+ allowedTabsKey.split(","),
685
+ initialTab
686
+ );
687
+ if (next) consumer.setTab(next);
688
+ }, [allowedTabsKey, initialTab, consumer.tab, consumer.setTab]);
689
+ useEffect2(() => {
690
+ ensureLoaded();
691
+ }, [ensureLoaded]);
692
+ const handleSelectAgent = useCallback3(
693
+ (agent) => {
694
+ if (onSelect) {
695
+ onSelect(agent.id);
696
+ } else if (navigateTo) {
697
+ navigate(navigateTo.replace("{id}", agent.id));
698
+ } else {
699
+ catalog.errorSink({
700
+ code: "select_has_nowhere_to_go",
701
+ message: "an agent was chosen but this picker was given neither onSelect nor navigateTo, so the choice went nowhere.",
702
+ context: { consumerId, agentId: agent.id }
703
+ });
704
+ }
705
+ },
706
+ [onSelect, navigateTo, navigate, catalog, consumerId]
707
+ );
708
+ const activeFilterCount = (consumer.sortBy !== "updated-desc" ? 1 : 0) + (consumer.includedCats.length > 0 ? 1 : 0) + (consumer.includedTags.length > 0 ? 1 : 0) + (consumer.favFilter !== "all" ? 1 : 0);
709
+ const handleAgentHover = useCallback3(
710
+ (agent, panelOpen) => {
711
+ if (panelOpen) return;
712
+ if (hoverLeaveTimerRef.current) {
713
+ clearTimeout(hoverLeaveTimerRef.current);
714
+ hoverLeaveTimerRef.current = null;
715
+ }
716
+ setHoveredAgent(agent);
717
+ },
718
+ []
719
+ );
720
+ const handleAgentHoverEnd = useCallback3(
721
+ (agent, onClear) => {
722
+ if (hoveredAgent?.id === agent.id) {
723
+ hoverLeaveTimerRef.current = setTimeout(() => {
724
+ setHoveredAgent(null);
725
+ onClear();
726
+ }, HOVER_GRACE_MS);
727
+ }
728
+ },
729
+ [hoveredAgent]
730
+ );
731
+ const handleDetailPanelMouseEnter = useCallback3(() => {
732
+ if (hoverLeaveTimerRef.current) {
733
+ clearTimeout(hoverLeaveTimerRef.current);
734
+ hoverLeaveTimerRef.current = null;
735
+ }
736
+ }, []);
737
+ const handleDetailPanelMouseLeave = useCallback3((onClear) => {
738
+ hoverLeaveTimerRef.current = setTimeout(() => {
739
+ setHoveredAgent(null);
740
+ onClear();
741
+ }, HOVER_GRACE_MS);
742
+ }, []);
743
+ useEffect2(
744
+ () => () => {
745
+ if (hoverLeaveTimerRef.current) clearTimeout(hoverLeaveTimerRef.current);
746
+ },
747
+ []
748
+ );
749
+ return {
750
+ agents,
751
+ isLoading,
752
+ activeAgentId,
753
+ pinnedAgent: pinnedAgent ?? null,
754
+ defaultRow: defaultRow ?? null,
755
+ allCategories,
756
+ allTags,
757
+ consumer,
758
+ tabCounts,
759
+ activeFilterCount,
760
+ hoveredAgent,
761
+ setHoveredAgent,
762
+ ensureLoaded,
763
+ handleSelectAgent,
764
+ handleAgentHover,
765
+ handleAgentHoverEnd,
766
+ handleDetailPanelMouseEnter,
767
+ handleDetailPanelMouseLeave
768
+ };
769
+ }
770
+ var selectStatus = (state) => state.status;
771
+
772
+ // catalog/react/AgentListDropdown.tsx
773
+ import {
774
+ cn as cn6,
775
+ Drawer,
776
+ DrawerContent,
777
+ DrawerTitle,
778
+ DrawerTrigger,
779
+ Popover,
780
+ PopoverContent,
781
+ PopoverTrigger,
782
+ Tooltip,
783
+ TooltipContent,
784
+ TooltipTrigger,
785
+ useIsMobile
786
+ } from "@ai-matrx/design-system";
787
+ import { useCallback as useCallback5, useMemo as useMemo3, useRef as useRef4, useState as useState3 } from "react";
788
+
789
+ // catalog/react/primitives.tsx
790
+ import { cn } from "@ai-matrx/design-system";
791
+
792
+ // catalog/react/icons.tsx
793
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
794
+ function Svg({ children, ...props }) {
795
+ return /* @__PURE__ */ jsx2(
796
+ "svg",
797
+ {
798
+ xmlns: "http://www.w3.org/2000/svg",
799
+ viewBox: "0 0 24 24",
800
+ fill: "none",
801
+ stroke: "currentColor",
802
+ strokeWidth: 2,
803
+ strokeLinecap: "round",
804
+ strokeLinejoin: "round",
805
+ "aria-hidden": "true",
806
+ ...props,
807
+ children
808
+ }
809
+ );
810
+ }
811
+ function StarIcon({
812
+ filled = false,
813
+ ...props
814
+ }) {
815
+ return /* @__PURE__ */ jsx2(Svg, { ...props, fill: filled ? "currentColor" : "none", children: /* @__PURE__ */ jsx2("path", { d: "M11.5 3.2a.6.6 0 0 1 1 0l2.3 4.7 5.2.8a.6.6 0 0 1 .3 1l-3.8 3.7.9 5.2a.6.6 0 0 1-.9.6L12 16.8l-4.6 2.4a.6.6 0 0 1-.9-.6l.9-5.2-3.8-3.7a.6.6 0 0 1 .3-1l5.2-.8Z" }) });
816
+ }
817
+ function ChevronRightIcon(props) {
818
+ return /* @__PURE__ */ jsx2(Svg, { ...props, children: /* @__PURE__ */ jsx2("path", { d: "m9 18 6-6-6-6" }) });
819
+ }
820
+ function ChevronDownIcon(props) {
821
+ return /* @__PURE__ */ jsx2(Svg, { ...props, children: /* @__PURE__ */ jsx2("path", { d: "m6 9 6 6 6-6" }) });
822
+ }
823
+ function SearchIcon(props) {
824
+ return /* @__PURE__ */ jsxs(Svg, { ...props, children: [
825
+ /* @__PURE__ */ jsx2("circle", { cx: "11", cy: "11", r: "8" }),
826
+ /* @__PURE__ */ jsx2("path", { d: "m21 21-4.3-4.3" })
827
+ ] });
828
+ }
829
+ function XIcon(props) {
830
+ return /* @__PURE__ */ jsxs(Svg, { ...props, children: [
831
+ /* @__PURE__ */ jsx2("path", { d: "M18 6 6 18" }),
832
+ /* @__PURE__ */ jsx2("path", { d: "m6 6 12 12" })
833
+ ] });
834
+ }
835
+ function CheckIcon(props) {
836
+ return /* @__PURE__ */ jsx2(Svg, { ...props, children: /* @__PURE__ */ jsx2("path", { d: "M20 6 9 17l-5-5" }) });
837
+ }
838
+ function ArrowUpDownIcon(props) {
839
+ return /* @__PURE__ */ jsxs(Svg, { ...props, children: [
840
+ /* @__PURE__ */ jsx2("path", { d: "m21 16-4 4-4-4" }),
841
+ /* @__PURE__ */ jsx2("path", { d: "M17 20V4" }),
842
+ /* @__PURE__ */ jsx2("path", { d: "m3 8 4-4 4 4" }),
843
+ /* @__PURE__ */ jsx2("path", { d: "M7 4v16" })
844
+ ] });
845
+ }
846
+ function FolderIcon(props) {
847
+ return /* @__PURE__ */ jsx2(Svg, { ...props, children: /* @__PURE__ */ jsx2("path", { d: "M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z" }) });
848
+ }
849
+ function TagIcon(props) {
850
+ return /* @__PURE__ */ jsxs(Svg, { ...props, children: [
851
+ /* @__PURE__ */ jsx2("path", { d: "M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z" }),
852
+ /* @__PURE__ */ jsx2("circle", { cx: "7.5", cy: "7.5", r: ".5", fill: "currentColor" })
853
+ ] });
854
+ }
855
+ function RotateCcwIcon(props) {
856
+ return /* @__PURE__ */ jsxs(Svg, { ...props, children: [
857
+ /* @__PURE__ */ jsx2("path", { d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" }),
858
+ /* @__PURE__ */ jsx2("path", { d: "M3 3v5h5" })
859
+ ] });
860
+ }
861
+ function LoaderIcon(props) {
862
+ return /* @__PURE__ */ jsx2(Svg, { ...props, children: /* @__PURE__ */ jsx2("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" }) });
863
+ }
864
+ function MousePointerClickIcon(props) {
865
+ return /* @__PURE__ */ jsxs(Svg, { ...props, children: [
866
+ /* @__PURE__ */ jsx2("path", { d: "M14 4.1 12 6" }),
867
+ /* @__PURE__ */ jsx2("path", { d: "m5.1 8-2.9-.8" }),
868
+ /* @__PURE__ */ jsx2("path", { d: "m6 12-1.9 2" }),
869
+ /* @__PURE__ */ jsx2("path", { d: "M7.2 2.2 8 5.1" }),
870
+ /* @__PURE__ */ jsx2("path", { d: "M9.037 9.69a.498.498 0 0 1 .653-.653l11 4.5a.5.5 0 0 1-.074.949l-4.349 1.041a1 1 0 0 0-.74.739l-1.04 4.35a.5.5 0 0 1-.95.074z" })
871
+ ] });
872
+ }
873
+ function UsersIcon(props) {
874
+ return /* @__PURE__ */ jsxs(Svg, { ...props, children: [
875
+ /* @__PURE__ */ jsx2("path", { d: "M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2" }),
876
+ /* @__PURE__ */ jsx2("circle", { cx: "9", cy: "7", r: "4" }),
877
+ /* @__PURE__ */ jsx2("path", { d: "M22 21v-2a4 4 0 0 0-3-3.87" }),
878
+ /* @__PURE__ */ jsx2("path", { d: "M16 3.13a4 4 0 0 1 0 7.75" })
879
+ ] });
880
+ }
881
+ function ClockIcon(props) {
882
+ return /* @__PURE__ */ jsxs(Svg, { ...props, children: [
883
+ /* @__PURE__ */ jsx2("circle", { cx: "12", cy: "12", r: "10" }),
884
+ /* @__PURE__ */ jsx2("path", { d: "M12 6v6l4 2" })
885
+ ] });
886
+ }
887
+ function GlobeIcon(props) {
888
+ return /* @__PURE__ */ jsxs(Svg, { ...props, children: [
889
+ /* @__PURE__ */ jsx2("circle", { cx: "12", cy: "12", r: "10" }),
890
+ /* @__PURE__ */ jsx2("path", { d: "M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20" }),
891
+ /* @__PURE__ */ jsx2("path", { d: "M2 12h20" })
892
+ ] });
893
+ }
894
+ function ExternalLinkIcon(props) {
895
+ return /* @__PURE__ */ jsxs(Svg, { ...props, children: [
896
+ /* @__PURE__ */ jsx2("path", { d: "M15 3h6v6" }),
897
+ /* @__PURE__ */ jsx2("path", { d: "M10 14 21 3" }),
898
+ /* @__PURE__ */ jsx2("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" })
899
+ ] });
900
+ }
901
+ function MessageCircleIcon(props) {
902
+ return /* @__PURE__ */ jsx2(Svg, { ...props, children: /* @__PURE__ */ jsx2("path", { d: "M7.9 20A9 9 0 1 0 4 16.1L2 22Z" }) });
903
+ }
904
+ function RocketIcon(props) {
905
+ return /* @__PURE__ */ jsxs(Svg, { ...props, children: [
906
+ /* @__PURE__ */ jsx2("path", { d: "M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91 0" }),
907
+ /* @__PURE__ */ jsx2("path", { d: "m12 15-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2" }),
908
+ /* @__PURE__ */ jsx2("path", { d: "M9 12H4s.55-3.03 2-4c1.62-1.08 5 0 5 0" }),
909
+ /* @__PURE__ */ jsx2("path", { d: "M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5" })
910
+ ] });
911
+ }
912
+ function AlertTriangleIcon(props) {
913
+ return /* @__PURE__ */ jsxs(Svg, { ...props, children: [
914
+ /* @__PURE__ */ jsx2("path", { d: "m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" }),
915
+ /* @__PURE__ */ jsx2("path", { d: "M12 9v4" }),
916
+ /* @__PURE__ */ jsx2("path", { d: "M12 17h.01" })
917
+ ] });
918
+ }
919
+
920
+ // catalog/react/primitives.tsx
921
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
922
+ var SearchInput = ({
923
+ ref,
924
+ value,
925
+ onChange,
926
+ placeholder
927
+ }) => /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-1.5 h-7 px-2 rounded-md bg-muted/40 border border-border/50", children: [
928
+ /* @__PURE__ */ jsx3(SearchIcon, { className: "w-3 h-3 text-muted-foreground shrink-0" }),
929
+ /* @__PURE__ */ jsx3(
930
+ "input",
931
+ {
932
+ ref,
933
+ type: "text",
934
+ value,
935
+ onChange: (e) => onChange(e.target.value),
936
+ placeholder,
937
+ className: "flex-1 bg-transparent text-xs text-foreground placeholder:text-muted-foreground/50 outline-none min-w-0",
938
+ style: { fontSize: "16px" }
939
+ }
940
+ ),
941
+ value && /* @__PURE__ */ jsx3(
942
+ "button",
943
+ {
944
+ type: "button",
945
+ onClick: () => onChange(""),
946
+ className: "text-muted-foreground hover:text-foreground",
947
+ "aria-label": "Clear search",
948
+ children: /* @__PURE__ */ jsx3(XIcon, { className: "w-3 h-3" })
949
+ }
950
+ )
951
+ ] });
952
+ function FilterChip({
953
+ icon: Icon,
954
+ label,
955
+ active,
956
+ focused,
957
+ onClick
958
+ }) {
959
+ return /* @__PURE__ */ jsxs2(
960
+ "button",
961
+ {
962
+ type: "button",
963
+ onClick,
964
+ className: cn(
965
+ "inline-flex items-center gap-1 h-6 px-1.5 rounded text-[11px] font-medium shrink-0 transition-colors",
966
+ focused ? "bg-primary/15 text-primary border border-primary/30 ring-1 ring-primary/20" : active ? "bg-primary/10 text-primary border border-primary/20" : "text-muted-foreground hover:text-foreground hover:bg-muted/50 border border-transparent"
967
+ ),
968
+ children: [
969
+ /* @__PURE__ */ jsx3(Icon, { className: "w-3 h-3" }),
970
+ /* @__PURE__ */ jsx3("span", { children: label })
971
+ ]
972
+ }
973
+ );
974
+ }
975
+ function OptionRow({
976
+ label,
977
+ selected,
978
+ onClick
979
+ }) {
980
+ return /* @__PURE__ */ jsxs2(
981
+ "button",
982
+ {
983
+ type: "button",
984
+ onClick,
985
+ className: cn(
986
+ "flex items-center w-full px-3 py-2 text-xs transition-colors",
987
+ "hover:bg-muted/50 active:bg-muted/70",
988
+ selected && "text-primary font-medium"
989
+ ),
990
+ children: [
991
+ /* @__PURE__ */ jsx3("span", { className: "flex-1 text-left", children: label }),
992
+ selected && /* @__PURE__ */ jsx3(CheckIcon, { className: "w-3.5 h-3.5 text-primary shrink-0" })
993
+ ]
994
+ }
995
+ );
996
+ }
997
+ function CheckRow({
998
+ label,
999
+ checked,
1000
+ onClick
1001
+ }) {
1002
+ return /* @__PURE__ */ jsxs2(
1003
+ "button",
1004
+ {
1005
+ type: "button",
1006
+ onClick,
1007
+ className: "flex items-center gap-2 w-full px-3 py-1.5 text-xs hover:bg-muted/50 active:bg-muted/70 transition-colors",
1008
+ children: [
1009
+ /* @__PURE__ */ jsx3(
1010
+ "div",
1011
+ {
1012
+ className: cn(
1013
+ "w-3.5 h-3.5 rounded-sm border flex items-center justify-center shrink-0 transition-colors",
1014
+ checked ? "bg-primary border-primary" : "border-muted-foreground/30"
1015
+ ),
1016
+ children: checked && /* @__PURE__ */ jsx3(CheckIcon, { className: "w-2.5 h-2.5 text-primary-foreground" })
1017
+ }
1018
+ ),
1019
+ /* @__PURE__ */ jsx3("span", { className: "flex-1 text-left truncate", children: label })
1020
+ ]
1021
+ }
1022
+ );
1023
+ }
1024
+ function SidePanelHeader({
1025
+ title,
1026
+ onClose
1027
+ }) {
1028
+ return /* @__PURE__ */ jsxs2("div", { className: "flex items-center justify-between px-3 py-2 border-b border-border shrink-0", children: [
1029
+ /* @__PURE__ */ jsx3("span", { className: "text-xs font-semibold text-foreground", children: title }),
1030
+ /* @__PURE__ */ jsx3(
1031
+ "button",
1032
+ {
1033
+ type: "button",
1034
+ onClick: onClose,
1035
+ className: "w-5 h-5 rounded flex items-center justify-center text-muted-foreground hover:text-foreground hover:bg-muted/50 transition-colors",
1036
+ "aria-label": "Close",
1037
+ children: /* @__PURE__ */ jsx3(XIcon, { className: "w-3.5 h-3.5" })
1038
+ }
1039
+ )
1040
+ ] });
1041
+ }
1042
+
1043
+ // catalog/react/AgentCategoriesPanel.tsx
1044
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
1045
+ function AgentCategoriesPanel({
1046
+ consumer,
1047
+ allCategories,
1048
+ search,
1049
+ setSearch,
1050
+ onClose
1051
+ }) {
1052
+ const filtered = allCategories.filter(
1053
+ (c) => !search || c.toLowerCase().includes(search.toLowerCase())
1054
+ );
1055
+ return /* @__PURE__ */ jsxs3("div", { className: "flex flex-col h-full", children: [
1056
+ /* @__PURE__ */ jsx4(SidePanelHeader, { title: "Categories", onClose }),
1057
+ /* @__PURE__ */ jsx4("div", { className: "px-2 pt-2 pb-1 shrink-0", children: /* @__PURE__ */ jsx4(
1058
+ SearchInput,
1059
+ {
1060
+ value: search,
1061
+ onChange: setSearch,
1062
+ placeholder: "Filter categories..."
1063
+ }
1064
+ ) }),
1065
+ consumer.includedCats.length > 0 && /* @__PURE__ */ jsxs3(
1066
+ "button",
1067
+ {
1068
+ type: "button",
1069
+ onClick: () => consumer.setIncludedCats([]),
1070
+ className: "mx-2 mb-1 h-6 rounded text-[11px] font-medium text-primary hover:bg-muted/50 transition-colors text-left shrink-0",
1071
+ children: [
1072
+ "Clear (",
1073
+ consumer.includedCats.length,
1074
+ ")"
1075
+ ]
1076
+ }
1077
+ ),
1078
+ /* @__PURE__ */ jsx4("div", { className: "overflow-y-auto flex-1", children: filtered.length === 0 ? /* @__PURE__ */ jsx4("p", { className: "text-xs text-muted-foreground text-center py-6", children: "No categories" }) : filtered.map((cat) => /* @__PURE__ */ jsx4(
1079
+ CheckRow,
1080
+ {
1081
+ label: cat,
1082
+ checked: consumer.includedCats.includes(cat),
1083
+ onClick: () => consumer.toggleCategory(cat)
1084
+ },
1085
+ cat
1086
+ )) })
1087
+ ] });
1088
+ }
1089
+
1090
+ // catalog/react/AgentDetailCard.tsx
1091
+ import { cn as cn3 } from "@ai-matrx/design-system";
1092
+
1093
+ // catalog/react/FavoriteAgentButton.tsx
1094
+ import { cn as cn2 } from "@ai-matrx/design-system";
1095
+ import { useCallback as useCallback4 } from "react";
1096
+ import { jsx as jsx5 } from "react/jsx-runtime";
1097
+ function FavoriteAgentButton({
1098
+ id,
1099
+ variant = "card",
1100
+ disabled
1101
+ }) {
1102
+ const catalog = useAgentCatalog();
1103
+ const select = useCallback4(
1104
+ (state) => state.byId[id],
1105
+ [id]
1106
+ );
1107
+ const record = useAgentCatalogState(select);
1108
+ const isFavorite = record?.isFavorite ?? false;
1109
+ const isOwner = record?.isOwner ?? true;
1110
+ const handleClick = (e) => {
1111
+ e.stopPropagation();
1112
+ if (disabled || !isOwner) return;
1113
+ void catalog.setFavorite(id, !isFavorite).catch(() => {
1114
+ });
1115
+ };
1116
+ const title = isOwner ? isFavorite ? "Remove from favorites" : "Add to favorites" : "Shared \u2014 cannot favorite";
1117
+ if (variant === "list") {
1118
+ return /* @__PURE__ */ jsx5(
1119
+ "button",
1120
+ {
1121
+ type: "button",
1122
+ className: cn2(
1123
+ "flex-shrink-0 p-0.5 rounded transition-all duration-150",
1124
+ "focus:outline-none focus-visible:ring-2 focus-visible:ring-primary",
1125
+ disabled || !isOwner ? "cursor-not-allowed" : "hover:scale-110 cursor-pointer"
1126
+ ),
1127
+ onClick: handleClick,
1128
+ disabled: disabled || !isOwner,
1129
+ title,
1130
+ "aria-label": isFavorite ? "Remove from favorites" : "Add to favorites",
1131
+ children: /* @__PURE__ */ jsx5(
1132
+ StarIcon,
1133
+ {
1134
+ filled: isFavorite,
1135
+ className: cn2(
1136
+ "h-3.5 w-3.5 transition-all duration-150",
1137
+ isFavorite ? "matrx-agent-star-on" : "text-muted-foreground/40 hover:matrx-agent-star-on"
1138
+ )
1139
+ }
1140
+ )
1141
+ }
1142
+ );
1143
+ }
1144
+ return /* @__PURE__ */ jsx5(
1145
+ "button",
1146
+ {
1147
+ type: "button",
1148
+ className: cn2(
1149
+ "absolute top-2.5 right-2.5 z-10 p-0.5 rounded transition-all duration-150",
1150
+ "focus:outline-none focus-visible:ring-2 focus-visible:ring-primary",
1151
+ disabled || !isOwner ? "cursor-not-allowed" : "hover:scale-110 cursor-pointer",
1152
+ isFavorite ? "matrx-agent-star-on" : "text-muted-foreground/40 hover:matrx-agent-star-on"
1153
+ ),
1154
+ onClick: handleClick,
1155
+ disabled: disabled || !isOwner,
1156
+ title,
1157
+ "aria-label": isFavorite ? "Remove from favorites" : "Add to favorites",
1158
+ children: /* @__PURE__ */ jsx5(StarIcon, { filled: isFavorite, className: "w-4 h-4 transition-all duration-150" })
1159
+ }
1160
+ );
1161
+ }
1162
+
1163
+ // catalog/react/AgentDetailCard.tsx
1164
+ import { Fragment, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
1165
+ function AgentDetailCard({ agent, onSelect }) {
1166
+ const { LinkComponent, renderModelRef, openPeek } = useAgentCatalogUiPorts();
1167
+ const updatedDate = agent.updatedAt ? new Date(agent.updatedAt) : null;
1168
+ const createdDate = agent.createdAt ? new Date(agent.createdAt) : null;
1169
+ const isDefaultRow = isMandateAgentId(agent.id);
1170
+ const formatDate = (d) => {
1171
+ if (!d) return null;
1172
+ return d.toLocaleDateString(void 0, {
1173
+ month: "short",
1174
+ day: "numeric",
1175
+ year: "numeric"
1176
+ });
1177
+ };
1178
+ return /* @__PURE__ */ jsxs4("div", { className: "flex flex-col h-full", children: [
1179
+ /* @__PURE__ */ jsx6("div", { className: "px-4 pt-4 pb-3", children: /* @__PURE__ */ jsxs4("div", { className: "flex items-start gap-3", children: [
1180
+ /* @__PURE__ */ jsx6("div", { className: "w-9 h-9 rounded-lg bg-primary/10 flex items-center justify-center shrink-0" }),
1181
+ /* @__PURE__ */ jsxs4("div", { className: "flex-1 min-w-0", children: [
1182
+ /* @__PURE__ */ jsx6("h3", { className: "text-sm font-semibold text-foreground leading-tight truncate", children: agent.name || "Untitled" }),
1183
+ agent.isFavorite && /* @__PURE__ */ jsx6("div", { className: "flex items-center gap-1 mt-0.5", children: /* @__PURE__ */ jsx6("span", { className: "text-[11px] matrx-agent-star-on", children: "Pinned to favorites" }) })
1184
+ ] }),
1185
+ !isDefaultRow && /* @__PURE__ */ jsx6(FavoriteAgentButton, { id: agent.id, variant: "list" })
1186
+ ] }) }),
1187
+ /* @__PURE__ */ jsx6("div", { className: "h-px bg-border mx-3" }),
1188
+ /* @__PURE__ */ jsxs4("div", { className: "flex-1 overflow-y-auto px-4 py-3 space-y-3", children: [
1189
+ agent.description && /* @__PURE__ */ jsxs4("div", { children: [
1190
+ /* @__PURE__ */ jsx6("p", { className: "text-[11px] font-medium text-muted-foreground uppercase tracking-wider mb-1", children: "Description" }),
1191
+ /* @__PURE__ */ jsx6("p", { className: "text-xs text-foreground/80 leading-relaxed", children: agent.description })
1192
+ ] }),
1193
+ agent.category && /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2", children: [
1194
+ /* @__PURE__ */ jsx6(FolderIcon, { className: "w-3.5 h-3.5 text-muted-foreground shrink-0" }),
1195
+ /* @__PURE__ */ jsx6("span", { className: "text-xs text-foreground/80", children: agent.category })
1196
+ ] }),
1197
+ agent.tags && agent.tags.length > 0 && /* @__PURE__ */ jsxs4("div", { children: [
1198
+ /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-1.5 mb-1.5", children: [
1199
+ /* @__PURE__ */ jsx6(TagIcon, { className: "w-3.5 h-3.5 text-muted-foreground shrink-0" }),
1200
+ /* @__PURE__ */ jsx6("span", { className: "text-[11px] font-medium text-muted-foreground", children: "Tags" })
1201
+ ] }),
1202
+ /* @__PURE__ */ jsx6("div", { className: "flex flex-wrap gap-1", children: agent.tags.map((tag) => /* @__PURE__ */ jsx6(
1203
+ "span",
1204
+ {
1205
+ className: "inline-flex items-center h-5 px-1.5 rounded text-[10px] font-medium bg-muted text-muted-foreground",
1206
+ children: tag
1207
+ },
1208
+ tag
1209
+ )) })
1210
+ ] }),
1211
+ agent.accessLevel && /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2", children: [
1212
+ agent.isOwner === false ? /* @__PURE__ */ jsx6(UsersIcon, { className: "w-3.5 h-3.5 text-muted-foreground shrink-0" }) : /* @__PURE__ */ jsx6(GlobeIcon, { className: "w-3.5 h-3.5 text-muted-foreground shrink-0" }),
1213
+ /* @__PURE__ */ jsxs4("div", { className: "flex flex-col", children: [
1214
+ /* @__PURE__ */ jsx6("span", { className: "text-xs text-foreground/80 capitalize", children: agent.accessLevel === "owner" ? "You own this" : `Shared \u2014 ${agent.accessLevel}` }),
1215
+ agent.sharedByEmail && /* @__PURE__ */ jsxs4("span", { className: "text-[10px] text-muted-foreground", children: [
1216
+ "by ",
1217
+ agent.sharedByEmail
1218
+ ] })
1219
+ ] })
1220
+ ] }),
1221
+ agent.modelId && /* @__PURE__ */ jsx6("div", { className: "flex items-center gap-2", children: renderModelRef({
1222
+ modelId: agent.modelId,
1223
+ className: "max-w-full text-xs text-foreground/80"
1224
+ }) }),
1225
+ (updatedDate || createdDate) && /* @__PURE__ */ jsxs4("div", { className: "pt-1 space-y-1", children: [
1226
+ updatedDate && /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2", children: [
1227
+ /* @__PURE__ */ jsx6(ClockIcon, { className: "w-3.5 h-3.5 text-muted-foreground shrink-0" }),
1228
+ /* @__PURE__ */ jsxs4("span", { className: "text-[11px] text-muted-foreground", children: [
1229
+ "Updated ",
1230
+ formatDate(updatedDate)
1231
+ ] })
1232
+ ] }),
1233
+ createdDate && /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2", children: [
1234
+ /* @__PURE__ */ jsx6(ClockIcon, { className: "w-3.5 h-3.5 text-muted-foreground/50 shrink-0" }),
1235
+ /* @__PURE__ */ jsxs4("span", { className: "text-[11px] text-muted-foreground/70", children: [
1236
+ "Created ",
1237
+ formatDate(createdDate)
1238
+ ] })
1239
+ ] })
1240
+ ] })
1241
+ ] }),
1242
+ /* @__PURE__ */ jsx6("div", { className: "h-px bg-border mx-3 mt-auto" }),
1243
+ /* @__PURE__ */ jsxs4("div", { className: "px-3 py-2 shrink-0 flex items-center gap-1.5", children: [
1244
+ /* @__PURE__ */ jsx6(
1245
+ "button",
1246
+ {
1247
+ type: "button",
1248
+ onClick: onSelect,
1249
+ className: "flex-1 h-7 rounded-md bg-primary text-primary-foreground text-[11px] font-medium hover:bg-primary/90 active:bg-primary/80 transition-colors",
1250
+ children: "Select"
1251
+ }
1252
+ ),
1253
+ openPeek && /* @__PURE__ */ jsx6(
1254
+ "button",
1255
+ {
1256
+ type: "button",
1257
+ onClick: (e) => {
1258
+ e.stopPropagation();
1259
+ openPeek(agent);
1260
+ },
1261
+ title: "Sneak Peek",
1262
+ "aria-label": "Sneak Peek",
1263
+ className: iconButtonClass,
1264
+ children: /* @__PURE__ */ jsx6(RocketIcon, { className: "w-3.5 h-3.5" })
1265
+ }
1266
+ ),
1267
+ !isDefaultRow && /* @__PURE__ */ jsxs4(Fragment, { children: [
1268
+ /* @__PURE__ */ jsx6(
1269
+ LinkComponent,
1270
+ {
1271
+ href: `/chat/a/${agent.id}`,
1272
+ onClick: (e) => e.stopPropagation(),
1273
+ title: "Open in chat",
1274
+ "aria-label": "Open in chat",
1275
+ className: iconButtonClass,
1276
+ children: /* @__PURE__ */ jsx6(MessageCircleIcon, { className: "w-3.5 h-3.5" })
1277
+ }
1278
+ ),
1279
+ /* @__PURE__ */ jsx6(
1280
+ LinkComponent,
1281
+ {
1282
+ href: `/agents/go/${agent.id}`,
1283
+ target: "_blank",
1284
+ rel: "noopener noreferrer",
1285
+ onClick: (e) => e.stopPropagation(),
1286
+ title: "Open in new tab",
1287
+ "aria-label": "Open in new tab",
1288
+ className: cn3(
1289
+ iconButtonClass,
1290
+ "hover:text-foreground"
1291
+ ),
1292
+ children: /* @__PURE__ */ jsx6(ExternalLinkIcon, { className: "w-3.5 h-3.5" })
1293
+ }
1294
+ )
1295
+ ] })
1296
+ ] })
1297
+ ] });
1298
+ }
1299
+ var iconButtonClass = "flex items-center justify-center h-7 w-7 rounded-md border border-border bg-background text-muted-foreground hover:text-primary hover:bg-muted/50 transition-colors shrink-0";
1300
+
1301
+ // catalog/react/AgentListContent.tsx
1302
+ import { useEffect as useEffect3, useRef as useRef3 } from "react";
1303
+
1304
+ // catalog/react/types.ts
1305
+ var SORT_OPTIONS = [
1306
+ { value: "updated-desc", label: "Recent" },
1307
+ { value: "created-desc", label: "Created" },
1308
+ { value: "name-asc", label: "A \u2192 Z" },
1309
+ { value: "name-desc", label: "Z \u2192 A" },
1310
+ { value: "category-asc", label: "Category" }
1311
+ ];
1312
+ var PANEL_HEIGHT = "528px";
1313
+ var LIST_MAX_HEIGHT = "min(528px, var(--radix-popper-available-height, 528px))";
1314
+
1315
+ // catalog/react/AgentFilterBar.tsx
1316
+ import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
1317
+ function AgentFilterBar({
1318
+ consumer,
1319
+ allCategories,
1320
+ allTags,
1321
+ activeFilterCount,
1322
+ isMobile,
1323
+ rightPanel,
1324
+ onFilterChipClick,
1325
+ onReset
1326
+ }) {
1327
+ return /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-1 px-2 pb-1.5 overflow-x-auto matrx-agent-scrollbar-none shrink-0", children: [
1328
+ /* @__PURE__ */ jsx7(
1329
+ FilterChip,
1330
+ {
1331
+ icon: ArrowUpDownIcon,
1332
+ label: SORT_OPTIONS.find((o) => o.value === consumer.sortBy)?.label ?? "Sort",
1333
+ active: consumer.sortBy !== "updated-desc",
1334
+ focused: !isMobile && rightPanel === "sort",
1335
+ onClick: () => onFilterChipClick("sort")
1336
+ }
1337
+ ),
1338
+ /* @__PURE__ */ jsx7(
1339
+ FilterChip,
1340
+ {
1341
+ icon: StarIcon,
1342
+ label: consumer.favFilter === "no" ? "No Favs" : "Favs",
1343
+ active: consumer.favFilter !== "all",
1344
+ onClick: () => {
1345
+ const next = consumer.favFilter === "all" ? "yes" : consumer.favFilter === "yes" ? "no" : "all";
1346
+ consumer.setFavFilter(next);
1347
+ }
1348
+ }
1349
+ ),
1350
+ allCategories.length > 0 && /* @__PURE__ */ jsx7(
1351
+ FilterChip,
1352
+ {
1353
+ icon: FolderIcon,
1354
+ label: consumer.includedCats.length > 0 ? `${consumer.includedCats.length}` : "Category",
1355
+ active: consumer.includedCats.length > 0,
1356
+ focused: !isMobile && rightPanel === "categories",
1357
+ onClick: () => onFilterChipClick("categories")
1358
+ }
1359
+ ),
1360
+ allTags.length > 0 && /* @__PURE__ */ jsx7(
1361
+ FilterChip,
1362
+ {
1363
+ icon: TagIcon,
1364
+ label: consumer.includedTags.length > 0 ? `${consumer.includedTags.length}` : "Tags",
1365
+ active: consumer.includedTags.length > 0,
1366
+ focused: !isMobile && rightPanel === "tags",
1367
+ onClick: () => onFilterChipClick("tags")
1368
+ }
1369
+ ),
1370
+ activeFilterCount > 0 && /* @__PURE__ */ jsx7(
1371
+ "button",
1372
+ {
1373
+ type: "button",
1374
+ onClick: onReset,
1375
+ "aria-label": "Reset filters",
1376
+ className: "flex items-center gap-0.5 h-6 px-1.5 rounded text-[11px] text-muted-foreground hover:text-foreground hover:bg-muted/50 transition-colors shrink-0",
1377
+ children: /* @__PURE__ */ jsx7(RotateCcwIcon, { className: "w-3 h-3" })
1378
+ }
1379
+ )
1380
+ ] });
1381
+ }
1382
+
1383
+ // catalog/react/AgentListTabs.tsx
1384
+ import { cn as cn4 } from "@ai-matrx/design-system";
1385
+ import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
1386
+ function AgentListTabs({
1387
+ consumer,
1388
+ tabCounts,
1389
+ systemTabLabel,
1390
+ visibleTabs
1391
+ }) {
1392
+ const { labels } = useAgentCatalog();
1393
+ const tabs = [
1394
+ { value: "mine", label: "Mine", countKey: "mine" },
1395
+ { value: "shared", label: "Shared", countKey: "shared" },
1396
+ { value: "all", label: "All", countKey: "all" },
1397
+ { value: "system", label: labels.publicTab, countKey: "system" }
1398
+ ];
1399
+ return /* @__PURE__ */ jsx8(
1400
+ "div",
1401
+ {
1402
+ className: "flex items-center gap-0.5 px-2 pb-1 overflow-x-auto matrx-agent-scrollbar-none shrink-0",
1403
+ role: "tablist",
1404
+ "aria-label": "Agent ownership",
1405
+ children: tabs.filter(({ value }) => !visibleTabs || visibleTabs.includes(value)).map(({ value, label: baseLabel, countKey }) => {
1406
+ const label = value === "system" ? systemTabLabel ?? baseLabel : baseLabel;
1407
+ const active = consumer.tab === value;
1408
+ const count = tabCounts[countKey];
1409
+ return /* @__PURE__ */ jsxs6(
1410
+ "button",
1411
+ {
1412
+ type: "button",
1413
+ role: "tab",
1414
+ "aria-selected": active,
1415
+ onClick: () => consumer.setTab(value),
1416
+ className: cn4(
1417
+ "inline-flex items-center gap-1 rounded-md px-2 py-1 text-[10px] font-medium transition-colors shrink-0",
1418
+ active ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:text-foreground hover:bg-muted/50"
1419
+ ),
1420
+ children: [
1421
+ /* @__PURE__ */ jsx8("span", { children: label }),
1422
+ /* @__PURE__ */ jsx8(
1423
+ "span",
1424
+ {
1425
+ className: cn4("tabular-nums opacity-70", active && "opacity-90"),
1426
+ children: count
1427
+ }
1428
+ )
1429
+ ]
1430
+ },
1431
+ value
1432
+ );
1433
+ })
1434
+ }
1435
+ );
1436
+ }
1437
+
1438
+ // catalog/react/AgentRow.tsx
1439
+ import { cn as cn5 } from "@ai-matrx/design-system";
1440
+ import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
1441
+ function AgentRow({
1442
+ agent,
1443
+ isActive,
1444
+ isHovered,
1445
+ isMobile,
1446
+ href,
1447
+ onClick,
1448
+ onHover,
1449
+ onHoverEnd,
1450
+ onDetailPress
1451
+ }) {
1452
+ const { LinkComponent } = useAgentCatalogUiPorts();
1453
+ const { labels } = useAgentCatalog();
1454
+ const rowHref = href ?? `/agents/go/${agent.id}`;
1455
+ return /* @__PURE__ */ jsxs7(
1456
+ "div",
1457
+ {
1458
+ className: cn5(
1459
+ "flex items-center w-full text-left transition-colors group",
1460
+ "hover:bg-muted/50 active:bg-muted/70",
1461
+ isActive && "bg-primary/5",
1462
+ !isMobile && isHovered && "bg-muted/40"
1463
+ ),
1464
+ onMouseEnter: isMobile ? void 0 : onHover,
1465
+ onMouseLeave: isMobile ? void 0 : onHoverEnd,
1466
+ children: [
1467
+ /* @__PURE__ */ jsxs7(
1468
+ LinkComponent,
1469
+ {
1470
+ href: rowHref,
1471
+ onClick: (e) => {
1472
+ if (e.metaKey || e.ctrlKey) return;
1473
+ e.preventDefault();
1474
+ onClick();
1475
+ },
1476
+ className: "flex items-center gap-2 flex-1 min-w-0 px-3 py-2",
1477
+ children: [
1478
+ agent.isFavorite && /* @__PURE__ */ jsx9(StarIcon, { filled: true, className: "w-3 h-3 matrx-agent-star-on shrink-0" }),
1479
+ /* @__PURE__ */ jsx9(
1480
+ "span",
1481
+ {
1482
+ className: cn5(
1483
+ "text-[13px] font-medium truncate",
1484
+ isActive ? "text-primary" : "text-foreground"
1485
+ ),
1486
+ children: agent.name || "Untitled"
1487
+ }
1488
+ ),
1489
+ agent.agentType === "builtin" ? /* @__PURE__ */ jsx9("span", { className: "text-[9px] font-medium text-primary bg-primary/10 px-1 py-px rounded shrink-0 ml-auto", children: labels.systemBadge }) : agent.isOwner === false ? /* @__PURE__ */ jsx9("span", { className: "text-[9px] text-muted-foreground bg-muted px-1 py-px rounded shrink-0 ml-auto", children: "shared" }) : null
1490
+ ]
1491
+ }
1492
+ ),
1493
+ isMobile && /* @__PURE__ */ jsx9(
1494
+ "button",
1495
+ {
1496
+ type: "button",
1497
+ "aria-label": "Show details",
1498
+ onClick: (e) => {
1499
+ e.stopPropagation();
1500
+ onDetailPress();
1501
+ },
1502
+ className: "flex items-center justify-center w-10 h-full shrink-0 text-muted-foreground/40 active:text-muted-foreground",
1503
+ children: /* @__PURE__ */ jsx9(ChevronRightIcon, { className: "w-4 h-4" })
1504
+ }
1505
+ )
1506
+ ]
1507
+ }
1508
+ );
1509
+ }
1510
+
1511
+ // catalog/react/AgentListContent.tsx
1512
+ import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
1513
+ function AgentListContent({
1514
+ agents,
1515
+ isLoading,
1516
+ consumer,
1517
+ activeAgentId,
1518
+ allCategories,
1519
+ allTags,
1520
+ inputRef,
1521
+ onSelectAgent,
1522
+ resolveAgentHref,
1523
+ onReset,
1524
+ activeFilterCount,
1525
+ isMobile,
1526
+ hoveredAgent,
1527
+ onAgentHover,
1528
+ onAgentHoverEnd,
1529
+ onDetailPress,
1530
+ onFilterChipClick,
1531
+ rightPanel,
1532
+ tabCounts,
1533
+ visibleTabs,
1534
+ systemTabLabel,
1535
+ pinnedAgent = null,
1536
+ defaultRow = null,
1537
+ listOpen = false
1538
+ }) {
1539
+ const catalog = useAgentCatalog();
1540
+ const listScrollRef = useRef3(null);
1541
+ useEffect3(() => {
1542
+ if (listOpen && pinnedAgent) {
1543
+ listScrollRef.current?.scrollTo({ top: 0 });
1544
+ }
1545
+ }, [listOpen, pinnedAgent?.id]);
1546
+ const { labels } = catalog;
1547
+ const emptyLabel = agentListEmptyLabel(consumer.tab, labels);
1548
+ const defaultAgent = defaultRow?.row ?? null;
1549
+ return /* @__PURE__ */ jsxs8("div", { className: "flex flex-col h-full", children: [
1550
+ /* @__PURE__ */ jsx10("div", { className: "px-2 pt-2 pb-1 shrink-0", children: /* @__PURE__ */ jsx10(
1551
+ SearchInput,
1552
+ {
1553
+ ref: inputRef,
1554
+ value: consumer.searchTerm,
1555
+ onChange: consumer.setSearchTerm,
1556
+ placeholder: labels.searchPlaceholder
1557
+ }
1558
+ ) }),
1559
+ /* @__PURE__ */ jsx10(
1560
+ AgentListTabs,
1561
+ {
1562
+ consumer,
1563
+ tabCounts,
1564
+ systemTabLabel,
1565
+ visibleTabs
1566
+ }
1567
+ ),
1568
+ /* @__PURE__ */ jsx10(
1569
+ AgentFilterBar,
1570
+ {
1571
+ consumer,
1572
+ allCategories,
1573
+ allTags,
1574
+ activeFilterCount,
1575
+ isMobile,
1576
+ rightPanel,
1577
+ onFilterChipClick,
1578
+ onReset
1579
+ }
1580
+ ),
1581
+ defaultRow?.drift && /* @__PURE__ */ jsxs8(
1582
+ "div",
1583
+ {
1584
+ role: "status",
1585
+ className: "matrx-agent-drift-banner mx-2 mb-1.5 flex items-start gap-2 rounded-md px-2 py-1.5 shrink-0",
1586
+ children: [
1587
+ /* @__PURE__ */ jsx10(AlertTriangleIcon, { className: "w-3.5 h-3.5 shrink-0 mt-px" }),
1588
+ /* @__PURE__ */ jsx10("span", { className: "text-[11px] leading-snug flex-1", children: defaultRow.drift }),
1589
+ /* @__PURE__ */ jsx10(
1590
+ "button",
1591
+ {
1592
+ type: "button",
1593
+ "aria-label": "Dismiss",
1594
+ onClick: () => catalog.dismissDefaultRowDrift(defaultRow.mandateKey),
1595
+ className: "shrink-0 opacity-70 hover:opacity-100",
1596
+ children: /* @__PURE__ */ jsx10(XIcon, { className: "w-3 h-3" })
1597
+ }
1598
+ )
1599
+ ]
1600
+ }
1601
+ ),
1602
+ defaultRow?.error && /* @__PURE__ */ jsxs8(
1603
+ "div",
1604
+ {
1605
+ role: "alert",
1606
+ className: "matrx-agent-drift-banner mx-2 mb-1.5 flex items-start gap-2 rounded-md px-2 py-1.5 shrink-0",
1607
+ children: [
1608
+ /* @__PURE__ */ jsx10(AlertTriangleIcon, { className: "w-3.5 h-3.5 shrink-0 mt-px" }),
1609
+ /* @__PURE__ */ jsx10("span", { className: "text-[11px] leading-snug flex-1", children: defaultRow.error })
1610
+ ]
1611
+ }
1612
+ ),
1613
+ /* @__PURE__ */ jsx10("div", { className: "h-px bg-border shrink-0" }),
1614
+ /* @__PURE__ */ jsx10("div", { ref: listScrollRef, className: "overflow-y-auto flex-1 min-h-0", children: isLoading ? /* @__PURE__ */ jsxs8("div", { className: "flex items-center justify-center py-8 gap-2 text-muted-foreground", children: [
1615
+ /* @__PURE__ */ jsx10(LoaderIcon, { className: "w-4 h-4 matrx-agent-spin" }),
1616
+ /* @__PURE__ */ jsx10("span", { className: "text-xs", children: labels.loading })
1617
+ ] }) : agents.length === 0 && !pinnedAgent && !defaultAgent ? /* @__PURE__ */ jsx10("div", { className: "flex flex-col items-center py-8 text-muted-foreground", children: /* @__PURE__ */ jsx10("span", { className: "text-xs", children: emptyLabel }) }) : /* @__PURE__ */ jsxs8("div", { className: "py-0.5", children: [
1618
+ defaultAgent && /* @__PURE__ */ jsxs8(Fragment2, { children: [
1619
+ /* @__PURE__ */ jsx10("div", { className: "px-3 pt-1.5 pb-0.5", children: /* @__PURE__ */ jsx10("span", { className: "text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: "Default" }) }),
1620
+ /* @__PURE__ */ jsx10(
1621
+ AgentRow,
1622
+ {
1623
+ agent: defaultAgent,
1624
+ isActive: defaultAgent.id === activeAgentId,
1625
+ isHovered: hoveredAgent?.id === defaultAgent.id,
1626
+ isMobile,
1627
+ onClick: () => onSelectAgent(defaultAgent),
1628
+ href: resolveAgentHref?.(defaultAgent),
1629
+ onHover: () => onAgentHover(defaultAgent),
1630
+ onHoverEnd: () => onAgentHoverEnd(defaultAgent),
1631
+ onDetailPress: () => onDetailPress(defaultAgent)
1632
+ },
1633
+ `default-${defaultAgent.id}`
1634
+ ),
1635
+ /* @__PURE__ */ jsx10("div", { className: "mx-2 my-0.5 h-px bg-border" })
1636
+ ] }),
1637
+ pinnedAgent && /* @__PURE__ */ jsxs8(Fragment2, { children: [
1638
+ /* @__PURE__ */ jsx10("div", { className: "px-3 pt-1.5 pb-0.5", children: /* @__PURE__ */ jsx10("span", { className: "text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: labels.currentAgentHeading }) }),
1639
+ /* @__PURE__ */ jsx10(
1640
+ AgentRow,
1641
+ {
1642
+ agent: pinnedAgent,
1643
+ isActive: true,
1644
+ isHovered: hoveredAgent?.id === pinnedAgent.id,
1645
+ isMobile,
1646
+ onClick: () => onSelectAgent(pinnedAgent),
1647
+ href: resolveAgentHref?.(pinnedAgent),
1648
+ onHover: () => onAgentHover(pinnedAgent),
1649
+ onHoverEnd: () => onAgentHoverEnd(pinnedAgent),
1650
+ onDetailPress: () => onDetailPress(pinnedAgent)
1651
+ },
1652
+ `pinned-${pinnedAgent.id}`
1653
+ ),
1654
+ /* @__PURE__ */ jsx10("div", { className: "mx-2 my-0.5 h-px bg-border" })
1655
+ ] }),
1656
+ agents.map((agent) => /* @__PURE__ */ jsx10(
1657
+ AgentRow,
1658
+ {
1659
+ agent,
1660
+ isActive: agent.id === activeAgentId,
1661
+ isHovered: hoveredAgent?.id === agent.id,
1662
+ isMobile,
1663
+ onClick: () => onSelectAgent(agent),
1664
+ href: resolveAgentHref?.(agent),
1665
+ onHover: () => onAgentHover(agent),
1666
+ onHoverEnd: () => onAgentHoverEnd(agent),
1667
+ onDetailPress: () => onDetailPress(agent)
1668
+ },
1669
+ agent.id
1670
+ )),
1671
+ agents.length === 0 && (pinnedAgent || defaultAgent) && /* @__PURE__ */ jsx10("div", { className: "flex flex-col items-center py-4 text-muted-foreground", children: /* @__PURE__ */ jsx10("span", { className: "text-xs", children: emptyLabel }) })
1672
+ ] }) }),
1673
+ /* @__PURE__ */ jsx10("div", { className: "h-px bg-border shrink-0" }),
1674
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center justify-between px-2.5 py-1.5 shrink-0", children: [
1675
+ /* @__PURE__ */ jsxs8("span", { className: "text-[10px] text-muted-foreground tabular-nums", children: [
1676
+ agents.length,
1677
+ " agent",
1678
+ agents.length !== 1 ? "s" : ""
1679
+ ] }),
1680
+ consumer.searchTerm && /* @__PURE__ */ jsx10(
1681
+ "button",
1682
+ {
1683
+ type: "button",
1684
+ onClick: () => consumer.setSearchTerm(""),
1685
+ className: "text-[10px] text-muted-foreground hover:text-foreground transition-colors",
1686
+ children: "Clear search"
1687
+ }
1688
+ )
1689
+ ] })
1690
+ ] });
1691
+ }
1692
+
1693
+ // catalog/react/AgentMobileSubView.tsx
1694
+ import { Fragment as Fragment3, jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
1695
+ function AgentMobileSubView({
1696
+ view,
1697
+ consumer,
1698
+ allCategories,
1699
+ allTags,
1700
+ catSearch,
1701
+ setCatSearch,
1702
+ tagSearch,
1703
+ setTagSearch,
1704
+ onBack
1705
+ }) {
1706
+ const title = view === "sort" ? "Sort" : view === "categories" ? "Categories" : "Tags";
1707
+ return /* @__PURE__ */ jsxs9("div", { className: "flex flex-col", children: [
1708
+ /* @__PURE__ */ jsxs9(
1709
+ "button",
1710
+ {
1711
+ type: "button",
1712
+ onClick: onBack,
1713
+ className: "flex items-center gap-1.5 px-3 py-2.5 text-sm font-medium text-primary hover:bg-muted/30 transition-colors border-b border-border shrink-0",
1714
+ children: [
1715
+ /* @__PURE__ */ jsx11(ChevronRightIcon, { className: "w-4 h-4 rotate-180" }),
1716
+ title
1717
+ ]
1718
+ }
1719
+ ),
1720
+ view === "sort" && SORT_OPTIONS.map((opt) => /* @__PURE__ */ jsx11(
1721
+ OptionRow,
1722
+ {
1723
+ label: opt.label,
1724
+ selected: consumer.sortBy === opt.value,
1725
+ onClick: () => {
1726
+ consumer.setSortBy(opt.value);
1727
+ onBack();
1728
+ }
1729
+ },
1730
+ opt.value
1731
+ )),
1732
+ view === "categories" && /* @__PURE__ */ jsxs9(Fragment3, { children: [
1733
+ /* @__PURE__ */ jsx11("div", { className: "px-2 pt-2 pb-1", children: /* @__PURE__ */ jsx11(
1734
+ SearchInput,
1735
+ {
1736
+ value: catSearch,
1737
+ onChange: setCatSearch,
1738
+ placeholder: "Filter categories..."
1739
+ }
1740
+ ) }),
1741
+ consumer.includedCats.length > 0 && /* @__PURE__ */ jsxs9(
1742
+ "button",
1743
+ {
1744
+ type: "button",
1745
+ onClick: () => consumer.setIncludedCats([]),
1746
+ className: "mx-2 mb-1 h-6 rounded text-[11px] font-medium text-primary hover:bg-muted/50 transition-colors text-left",
1747
+ children: [
1748
+ "Clear (",
1749
+ consumer.includedCats.length,
1750
+ ")"
1751
+ ]
1752
+ }
1753
+ ),
1754
+ /* @__PURE__ */ jsx11("div", { className: "overflow-y-auto max-h-[300px]", children: allCategories.filter(
1755
+ (c) => !catSearch || c.toLowerCase().includes(catSearch.toLowerCase())
1756
+ ).map((cat) => /* @__PURE__ */ jsx11(
1757
+ CheckRow,
1758
+ {
1759
+ label: cat,
1760
+ checked: consumer.includedCats.includes(cat),
1761
+ onClick: () => consumer.toggleCategory(cat)
1762
+ },
1763
+ cat
1764
+ )) })
1765
+ ] }),
1766
+ view === "tags" && /* @__PURE__ */ jsxs9(Fragment3, { children: [
1767
+ /* @__PURE__ */ jsx11("div", { className: "px-2 pt-2 pb-1", children: /* @__PURE__ */ jsx11(
1768
+ SearchInput,
1769
+ {
1770
+ value: tagSearch,
1771
+ onChange: setTagSearch,
1772
+ placeholder: "Filter tags..."
1773
+ }
1774
+ ) }),
1775
+ consumer.includedTags.length > 0 && /* @__PURE__ */ jsxs9(
1776
+ "button",
1777
+ {
1778
+ type: "button",
1779
+ onClick: () => consumer.setIncludedTags([]),
1780
+ className: "mx-2 mb-1 h-6 rounded text-[11px] font-medium text-primary hover:bg-muted/50 transition-colors text-left",
1781
+ children: [
1782
+ "Clear (",
1783
+ consumer.includedTags.length,
1784
+ ")"
1785
+ ]
1786
+ }
1787
+ ),
1788
+ /* @__PURE__ */ jsx11("div", { className: "overflow-y-auto max-h-[300px]", children: allTags.filter(
1789
+ (t) => !tagSearch || t.toLowerCase().includes(tagSearch.toLowerCase())
1790
+ ).map((tag) => /* @__PURE__ */ jsx11(
1791
+ CheckRow,
1792
+ {
1793
+ label: tag,
1794
+ checked: consumer.includedTags.includes(tag),
1795
+ onClick: () => consumer.toggleTag(tag)
1796
+ },
1797
+ tag
1798
+ )) })
1799
+ ] })
1800
+ ] });
1801
+ }
1802
+
1803
+ // catalog/react/AgentSortPanel.tsx
1804
+ import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
1805
+ function AgentSortPanel({ consumer, onClose }) {
1806
+ return /* @__PURE__ */ jsxs10("div", { className: "flex flex-col h-full", children: [
1807
+ /* @__PURE__ */ jsx12(SidePanelHeader, { title: "Sort By", onClose }),
1808
+ /* @__PURE__ */ jsx12("div", { className: "overflow-y-auto flex-1", children: SORT_OPTIONS.map((opt) => /* @__PURE__ */ jsx12(
1809
+ OptionRow,
1810
+ {
1811
+ label: opt.label,
1812
+ selected: consumer.sortBy === opt.value,
1813
+ onClick: () => consumer.setSortBy(opt.value)
1814
+ },
1815
+ opt.value
1816
+ )) })
1817
+ ] });
1818
+ }
1819
+
1820
+ // catalog/react/AgentTagsPanel.tsx
1821
+ import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
1822
+ function AgentTagsPanel({
1823
+ consumer,
1824
+ allTags,
1825
+ search,
1826
+ setSearch,
1827
+ onClose
1828
+ }) {
1829
+ const filtered = allTags.filter(
1830
+ (t) => !search || t.toLowerCase().includes(search.toLowerCase())
1831
+ );
1832
+ return /* @__PURE__ */ jsxs11("div", { className: "flex flex-col h-full", children: [
1833
+ /* @__PURE__ */ jsx13(SidePanelHeader, { title: "Tags", onClose }),
1834
+ /* @__PURE__ */ jsx13("div", { className: "px-2 pt-2 pb-1 shrink-0", children: /* @__PURE__ */ jsx13(
1835
+ SearchInput,
1836
+ {
1837
+ value: search,
1838
+ onChange: setSearch,
1839
+ placeholder: "Filter tags..."
1840
+ }
1841
+ ) }),
1842
+ consumer.includedTags.length > 0 && /* @__PURE__ */ jsxs11(
1843
+ "button",
1844
+ {
1845
+ type: "button",
1846
+ onClick: () => consumer.setIncludedTags([]),
1847
+ className: "mx-2 mb-1 h-6 rounded text-[11px] font-medium text-primary hover:bg-muted/50 transition-colors text-left shrink-0",
1848
+ children: [
1849
+ "Clear (",
1850
+ consumer.includedTags.length,
1851
+ ")"
1852
+ ]
1853
+ }
1854
+ ),
1855
+ /* @__PURE__ */ jsx13("div", { className: "overflow-y-auto flex-1", children: filtered.length === 0 ? /* @__PURE__ */ jsx13("p", { className: "text-xs text-muted-foreground text-center py-6", children: "No tags" }) : filtered.map((tag) => /* @__PURE__ */ jsx13(
1856
+ CheckRow,
1857
+ {
1858
+ label: tag,
1859
+ checked: consumer.includedTags.includes(tag),
1860
+ onClick: () => consumer.toggleTag(tag)
1861
+ },
1862
+ tag
1863
+ )) })
1864
+ ] });
1865
+ }
1866
+
1867
+ // catalog/react/AgentListDropdown.tsx
1868
+ import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
1869
+ var CONSUMER_ID = "agent-list-dropdown";
1870
+ function AgentListDropdown({
1871
+ onSelect,
1872
+ navigateTo,
1873
+ className,
1874
+ label,
1875
+ triggerSlot,
1876
+ noBorder = false,
1877
+ compact = false,
1878
+ activeAgentId: activeAgentIdProp,
1879
+ contentSide,
1880
+ consumerId = CONSUMER_ID,
1881
+ initialTab,
1882
+ includeSystemInAll = false,
1883
+ visibleTabs,
1884
+ systemTabLabel,
1885
+ resolveAgentHref: resolveAgentHrefProp,
1886
+ showPinnedAgent = true,
1887
+ excludeAgentIds,
1888
+ defaultMandateKey
1889
+ }) {
1890
+ const isMobile = useIsMobile();
1891
+ const { labels } = useAgentCatalog();
1892
+ const { popoverContainer } = useAgentCatalogUiPorts();
1893
+ const [open, setOpen] = useState3(false);
1894
+ const [rightPanel, setRightPanel] = useState3(null);
1895
+ const [catSearch, setCatSearch] = useState3("");
1896
+ const [tagSearch, setTagSearch] = useState3("");
1897
+ const [mobileDetailAgent, setMobileDetailAgent] = useState3(null);
1898
+ const [mobileSubView, setMobileSubView] = useState3(null);
1899
+ const inputRef = useRef4(null);
1900
+ const {
1901
+ agents,
1902
+ isLoading,
1903
+ activeAgentId,
1904
+ pinnedAgent,
1905
+ defaultRow,
1906
+ allCategories,
1907
+ allTags,
1908
+ consumer,
1909
+ tabCounts,
1910
+ activeFilterCount,
1911
+ hoveredAgent,
1912
+ setHoveredAgent,
1913
+ ensureLoaded,
1914
+ handleSelectAgent: coreSelectAgent,
1915
+ handleAgentHover: coreAgentHover,
1916
+ handleAgentHoverEnd: coreAgentHoverEnd,
1917
+ handleDetailPanelMouseEnter,
1918
+ handleDetailPanelMouseLeave: coreDetailMouseLeave
1919
+ } = useAgentListCore({
1920
+ consumerId,
1921
+ ...onSelect ? { onSelect } : {},
1922
+ ...navigateTo ? { navigateTo } : {},
1923
+ ...activeAgentIdProp !== void 0 ? { activeAgentIdOverride: activeAgentIdProp } : {},
1924
+ ...initialTab ? { initialTab } : {},
1925
+ includeSystemInAll,
1926
+ // The restriction has to reach the CORE, not just the tab strip — see
1927
+ // `AgentListCoreOptions.visibleTabs`.
1928
+ ...visibleTabs ? { visibleTabs } : {},
1929
+ ...excludeAgentIds ? { excludeAgentIds } : {},
1930
+ ...defaultMandateKey ? { defaultMandateKey } : {}
1931
+ });
1932
+ const displayLabel = label ?? pinnedAgent?.name ?? (activeAgentId ? isLoading ? labels.triggerResolving : labels.triggerUnnameable : labels.triggerFallback);
1933
+ const showAssignedTooltip = Boolean(activeAgentId) && displayLabel.trim().length > 0 && displayLabel !== "Select an agent" && displayLabel !== labels.triggerFallback;
1934
+ const handleOpen = (nextOpen) => {
1935
+ setOpen(nextOpen);
1936
+ if (nextOpen) {
1937
+ ensureLoaded();
1938
+ if (pinnedAgent && !isMobile) {
1939
+ setHoveredAgent(pinnedAgent);
1940
+ setRightPanel("detail");
1941
+ }
1942
+ setTimeout(() => inputRef.current?.focus(), 50);
1943
+ } else {
1944
+ setRightPanel(null);
1945
+ setCatSearch("");
1946
+ setTagSearch("");
1947
+ setMobileDetailAgent(null);
1948
+ setMobileSubView(null);
1949
+ }
1950
+ };
1951
+ const handleSelectAgent = (agent) => {
1952
+ coreSelectAgent(agent);
1953
+ setOpen(false);
1954
+ };
1955
+ const handleFilterChipClick = (panel) => {
1956
+ if (isMobile) {
1957
+ setMobileSubView(panel);
1958
+ } else {
1959
+ setRightPanel(rightPanel === panel ? null : panel);
1960
+ }
1961
+ };
1962
+ const handleAgentHover = useCallback5(
1963
+ (agent) => {
1964
+ if (isMobile) return;
1965
+ const filterPanelOpen = rightPanel === "sort" || rightPanel === "categories" || rightPanel === "tags";
1966
+ coreAgentHover(agent, filterPanelOpen);
1967
+ if (!filterPanelOpen) setRightPanel("detail");
1968
+ },
1969
+ [isMobile, rightPanel, coreAgentHover]
1970
+ );
1971
+ const handleAgentHoverEnd = useCallback5(
1972
+ (agent) => {
1973
+ if (isMobile) return;
1974
+ if (rightPanel !== "detail") return;
1975
+ coreAgentHoverEnd(agent, () => setRightPanel(null));
1976
+ },
1977
+ [isMobile, rightPanel, coreAgentHoverEnd]
1978
+ );
1979
+ const handleDetailPanelMouseLeave = useCallback5(() => {
1980
+ coreDetailMouseLeave(() => setRightPanel(null));
1981
+ }, [coreDetailMouseLeave]);
1982
+ const resolveAgentHref = useMemo3(() => {
1983
+ if (resolveAgentHrefProp) return resolveAgentHrefProp;
1984
+ if (!navigateTo) return void 0;
1985
+ return (agent) => navigateTo.replace("{id}", agent.id);
1986
+ }, [navigateTo, resolveAgentHrefProp]);
1987
+ const hasRightPanel = rightPanel !== null;
1988
+ const triggerButton = triggerSlot ?? /* @__PURE__ */ jsxs12(
1989
+ "button",
1990
+ {
1991
+ type: "button",
1992
+ className: cn6(
1993
+ "inline-flex items-center rounded-md text-xs font-medium transition-colors",
1994
+ "bg-background hover:bg-muted/50 text-foreground/80 hover:text-foreground",
1995
+ compact ? "h-5 gap-1 px-1.5" : "h-7 gap-1.5 px-2.5",
1996
+ !noBorder && "border border-border",
1997
+ className
1998
+ ),
1999
+ children: [
2000
+ /* @__PURE__ */ jsx14("span", { className: "min-w-0 max-w-[200px] flex-1 truncate text-left", children: displayLabel }),
2001
+ activeFilterCount > 0 && /* @__PURE__ */ jsx14("span", { className: "flex items-center justify-center w-4 h-4 rounded-md bg-primary text-primary-foreground text-[10px]", children: activeFilterCount }),
2002
+ /* @__PURE__ */ jsx14(ChevronDownIcon, { className: "w-3 h-3 text-muted-foreground/60" })
2003
+ ]
2004
+ }
2005
+ );
2006
+ const wrapTrigger = (Trigger) => {
2007
+ if (!showAssignedTooltip) {
2008
+ return /* @__PURE__ */ jsx14(Trigger, { asChild: true, children: triggerButton });
2009
+ }
2010
+ return /* @__PURE__ */ jsxs12(Tooltip, { ...open ? { open: false } : {}, children: [
2011
+ /* @__PURE__ */ jsx14(Trigger, { asChild: true, children: /* @__PURE__ */ jsx14(TooltipTrigger, { asChild: true, children: triggerButton }) }),
2012
+ /* @__PURE__ */ jsx14(TooltipContent, { side: "bottom", className: "max-w-xs", children: displayLabel })
2013
+ ] });
2014
+ };
2015
+ const listPanel = /* @__PURE__ */ jsx14(
2016
+ AgentListContent,
2017
+ {
2018
+ agents,
2019
+ isLoading,
2020
+ consumer,
2021
+ activeAgentId,
2022
+ allCategories,
2023
+ allTags,
2024
+ inputRef,
2025
+ onSelectAgent: handleSelectAgent,
2026
+ ...resolveAgentHref ? { resolveAgentHref } : {},
2027
+ onReset: consumer.resetFilters,
2028
+ activeFilterCount,
2029
+ isMobile,
2030
+ hoveredAgent,
2031
+ onAgentHover: handleAgentHover,
2032
+ onAgentHoverEnd: handleAgentHoverEnd,
2033
+ onDetailPress: setMobileDetailAgent,
2034
+ onFilterChipClick: handleFilterChipClick,
2035
+ rightPanel,
2036
+ tabCounts,
2037
+ ...visibleTabs ? { visibleTabs } : {},
2038
+ ...systemTabLabel ?? (includeSystemInAll ? "System" : void 0) ? {
2039
+ systemTabLabel: systemTabLabel ?? (includeSystemInAll ? "System" : void 0)
2040
+ } : {},
2041
+ pinnedAgent: showPinnedAgent ? pinnedAgent : null,
2042
+ defaultRow,
2043
+ listOpen: open
2044
+ }
2045
+ );
2046
+ if (isMobile) {
2047
+ return /* @__PURE__ */ jsxs12(Drawer, { open, onOpenChange: handleOpen, children: [
2048
+ wrapTrigger(DrawerTrigger),
2049
+ /* @__PURE__ */ jsxs12(DrawerContent, { className: "h-[85dvh]", children: [
2050
+ /* @__PURE__ */ jsx14(DrawerTitle, { className: "sr-only", children: "Select Agent" }),
2051
+ /* @__PURE__ */ jsx14("div", { className: "flex flex-col overflow-hidden flex-1 min-h-0", children: mobileDetailAgent ? /* @__PURE__ */ jsxs12("div", { className: "flex flex-col overflow-hidden", children: [
2052
+ /* @__PURE__ */ jsxs12(
2053
+ "button",
2054
+ {
2055
+ type: "button",
2056
+ onClick: () => setMobileDetailAgent(null),
2057
+ className: "flex items-center gap-1.5 px-3 py-2.5 text-sm font-medium text-primary hover:bg-muted/30 transition-colors border-b border-border shrink-0",
2058
+ children: [
2059
+ /* @__PURE__ */ jsx14(ChevronRightIcon, { className: "w-4 h-4 rotate-180" }),
2060
+ "Back"
2061
+ ]
2062
+ }
2063
+ ),
2064
+ /* @__PURE__ */ jsx14("div", { className: "overflow-y-auto", children: /* @__PURE__ */ jsx14(
2065
+ AgentDetailCard,
2066
+ {
2067
+ agent: mobileDetailAgent,
2068
+ onSelect: () => handleSelectAgent(mobileDetailAgent)
2069
+ }
2070
+ ) })
2071
+ ] }) : mobileSubView ? /* @__PURE__ */ jsx14(
2072
+ AgentMobileSubView,
2073
+ {
2074
+ view: mobileSubView,
2075
+ consumer,
2076
+ allCategories,
2077
+ allTags,
2078
+ catSearch,
2079
+ setCatSearch,
2080
+ tagSearch,
2081
+ setTagSearch,
2082
+ onBack: () => {
2083
+ setMobileSubView(null);
2084
+ setCatSearch("");
2085
+ setTagSearch("");
2086
+ }
2087
+ }
2088
+ ) : listPanel })
2089
+ ] })
2090
+ ] });
2091
+ }
2092
+ return /* @__PURE__ */ jsxs12(Popover, { open, onOpenChange: handleOpen, modal: false, children: [
2093
+ wrapTrigger(PopoverTrigger),
2094
+ /* @__PURE__ */ jsx14(
2095
+ PopoverContent,
2096
+ {
2097
+ ...contentSide ? { side: contentSide } : {},
2098
+ align: "start",
2099
+ sideOffset: 4,
2100
+ collisionPadding: 12,
2101
+ sticky: "always",
2102
+ ...popoverContainer ? { container: popoverContainer } : {},
2103
+ className: "p-0 overflow-hidden w-[680px]",
2104
+ style: { height: PANEL_HEIGHT, maxHeight: LIST_MAX_HEIGHT },
2105
+ children: /* @__PURE__ */ jsxs12("div", { className: "flex h-full", children: [
2106
+ /* @__PURE__ */ jsx14("div", { className: "flex flex-col min-w-0 w-[340px] shrink-0 border-r border-border", children: listPanel }),
2107
+ /* @__PURE__ */ jsxs12(
2108
+ "div",
2109
+ {
2110
+ className: "h-full w-[340px] shrink-0 overflow-hidden flex flex-col",
2111
+ onMouseEnter: rightPanel === "detail" ? handleDetailPanelMouseEnter : void 0,
2112
+ onMouseLeave: rightPanel === "detail" ? handleDetailPanelMouseLeave : void 0,
2113
+ children: [
2114
+ rightPanel === "detail" && hoveredAgent && /* @__PURE__ */ jsx14("div", { className: "h-full matrx-agent-fade-in", children: /* @__PURE__ */ jsx14(
2115
+ AgentDetailCard,
2116
+ {
2117
+ agent: hoveredAgent,
2118
+ onSelect: () => handleSelectAgent(hoveredAgent)
2119
+ }
2120
+ ) }, hoveredAgent.id),
2121
+ rightPanel === "sort" && /* @__PURE__ */ jsx14(
2122
+ AgentSortPanel,
2123
+ {
2124
+ consumer,
2125
+ onClose: () => setRightPanel(null)
2126
+ }
2127
+ ),
2128
+ rightPanel === "categories" && /* @__PURE__ */ jsx14(
2129
+ AgentCategoriesPanel,
2130
+ {
2131
+ consumer,
2132
+ allCategories,
2133
+ search: catSearch,
2134
+ setSearch: setCatSearch,
2135
+ onClose: () => {
2136
+ setRightPanel(null);
2137
+ setCatSearch("");
2138
+ }
2139
+ }
2140
+ ),
2141
+ rightPanel === "tags" && /* @__PURE__ */ jsx14(
2142
+ AgentTagsPanel,
2143
+ {
2144
+ consumer,
2145
+ allTags,
2146
+ search: tagSearch,
2147
+ setSearch: setTagSearch,
2148
+ onClose: () => {
2149
+ setRightPanel(null);
2150
+ setTagSearch("");
2151
+ }
2152
+ }
2153
+ ),
2154
+ !hasRightPanel && /* @__PURE__ */ jsxs12("div", { className: "flex flex-1 flex-col items-center justify-center gap-2 px-6 text-center", children: [
2155
+ /* @__PURE__ */ jsx14(MousePointerClickIcon, { className: "h-6 w-6 text-muted-foreground/40" }),
2156
+ /* @__PURE__ */ jsx14("p", { className: "text-xs text-muted-foreground/70 leading-relaxed", children: labels.hoverHint })
2157
+ ] })
2158
+ ]
2159
+ }
2160
+ )
2161
+ ] })
2162
+ }
2163
+ )
2164
+ ] });
2165
+ }
2166
+
2167
+ // catalog/react/AgentListInlinePicker.tsx
2168
+ import { cn as cn7 } from "@ai-matrx/design-system";
2169
+ import { useEffect as useEffect4, useRef as useRef5, useState as useState4 } from "react";
2170
+ import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
2171
+ function AgentListInlinePicker({
2172
+ consumerId,
2173
+ onSelect,
2174
+ activeAgentId = null,
2175
+ className,
2176
+ autoFocusSearch = true,
2177
+ initialTab,
2178
+ includeSystemInAll = false,
2179
+ visibleTabs,
2180
+ systemTabLabel,
2181
+ resolveAgentHref,
2182
+ showPinnedAgent = true,
2183
+ excludeAgentIds,
2184
+ defaultMandateKey
2185
+ }) {
2186
+ const inputRef = useRef5(null);
2187
+ const [catSearch, setCatSearch] = useState4("");
2188
+ const [tagSearch, setTagSearch] = useState4("");
2189
+ const [mobileDetailAgent, setMobileDetailAgent] = useState4(null);
2190
+ const [mobileSubView, setMobileSubView] = useState4(null);
2191
+ const {
2192
+ agents,
2193
+ isLoading,
2194
+ allCategories,
2195
+ allTags,
2196
+ consumer,
2197
+ tabCounts,
2198
+ activeFilterCount,
2199
+ hoveredAgent,
2200
+ pinnedAgent,
2201
+ defaultRow,
2202
+ ensureLoaded,
2203
+ handleSelectAgent: coreSelectAgent,
2204
+ handleAgentHover,
2205
+ handleAgentHoverEnd
2206
+ } = useAgentListCore({
2207
+ consumerId,
2208
+ onSelect,
2209
+ activeAgentIdOverride: activeAgentId,
2210
+ ...initialTab ? { initialTab } : {},
2211
+ includeSystemInAll,
2212
+ // The restriction has to reach the CORE, not just the tab strip — see
2213
+ // `AgentListCoreOptions.visibleTabs`.
2214
+ ...visibleTabs ? { visibleTabs } : {},
2215
+ ...excludeAgentIds ? { excludeAgentIds } : {},
2216
+ ...defaultMandateKey ? { defaultMandateKey } : {}
2217
+ });
2218
+ useEffect4(() => {
2219
+ ensureLoaded();
2220
+ if (!autoFocusSearch) return void 0;
2221
+ const timer = setTimeout(() => inputRef.current?.focus(), 50);
2222
+ return () => clearTimeout(timer);
2223
+ }, [ensureLoaded, autoFocusSearch]);
2224
+ const handleSelectAgent = (agent) => {
2225
+ coreSelectAgent(agent);
2226
+ setMobileDetailAgent(null);
2227
+ setMobileSubView(null);
2228
+ };
2229
+ const handleFilterChipClick = (panel) => {
2230
+ setMobileSubView(panel);
2231
+ };
2232
+ const isMobile = true;
2233
+ if (mobileDetailAgent) {
2234
+ return /* @__PURE__ */ jsxs13("div", { className: cn7("flex h-full min-h-0 flex-col", className), children: [
2235
+ /* @__PURE__ */ jsxs13(
2236
+ "button",
2237
+ {
2238
+ type: "button",
2239
+ onClick: () => setMobileDetailAgent(null),
2240
+ className: "flex shrink-0 items-center gap-1.5 border-b border-border px-3 py-2 text-sm font-medium text-primary transition-colors hover:bg-muted/30",
2241
+ children: [
2242
+ /* @__PURE__ */ jsx15(ChevronRightIcon, { className: "h-4 w-4 rotate-180" }),
2243
+ "Back"
2244
+ ]
2245
+ }
2246
+ ),
2247
+ /* @__PURE__ */ jsx15("div", { className: "min-h-0 flex-1 overflow-y-auto", children: /* @__PURE__ */ jsx15(
2248
+ AgentDetailCard,
2249
+ {
2250
+ agent: mobileDetailAgent,
2251
+ onSelect: () => handleSelectAgent(mobileDetailAgent)
2252
+ }
2253
+ ) })
2254
+ ] });
2255
+ }
2256
+ if (mobileSubView) {
2257
+ return /* @__PURE__ */ jsx15("div", { className: cn7("flex h-full min-h-0 flex-col", className), children: /* @__PURE__ */ jsx15(
2258
+ AgentMobileSubView,
2259
+ {
2260
+ view: mobileSubView,
2261
+ consumer,
2262
+ allCategories,
2263
+ allTags,
2264
+ catSearch,
2265
+ setCatSearch,
2266
+ tagSearch,
2267
+ setTagSearch,
2268
+ onBack: () => {
2269
+ setMobileSubView(null);
2270
+ setCatSearch("");
2271
+ setTagSearch("");
2272
+ }
2273
+ }
2274
+ ) });
2275
+ }
2276
+ return /* @__PURE__ */ jsx15("div", { className: cn7("flex h-full min-h-0 flex-col", className), children: /* @__PURE__ */ jsx15(
2277
+ AgentListContent,
2278
+ {
2279
+ agents,
2280
+ isLoading,
2281
+ consumer,
2282
+ activeAgentId,
2283
+ allCategories,
2284
+ allTags,
2285
+ inputRef,
2286
+ onSelectAgent: handleSelectAgent,
2287
+ ...resolveAgentHref ? { resolveAgentHref } : {},
2288
+ onReset: consumer.resetFilters,
2289
+ activeFilterCount,
2290
+ isMobile,
2291
+ hoveredAgent,
2292
+ onAgentHover: (agent) => handleAgentHover(agent, false),
2293
+ onAgentHoverEnd: (agent) => handleAgentHoverEnd(agent, () => {
2294
+ }),
2295
+ onDetailPress: setMobileDetailAgent,
2296
+ onFilterChipClick: handleFilterChipClick,
2297
+ rightPanel: null,
2298
+ tabCounts,
2299
+ ...visibleTabs ? { visibleTabs } : {},
2300
+ ...systemTabLabel ?? (includeSystemInAll ? "System" : void 0) ? {
2301
+ systemTabLabel: systemTabLabel ?? (includeSystemInAll ? "System" : void 0)
2302
+ } : {},
2303
+ pinnedAgent: showPinnedAgent ? pinnedAgent : null,
2304
+ defaultRow,
2305
+ listOpen: true
2306
+ }
2307
+ ) });
2308
+ }
2309
+ export {
2310
+ AgentCatalogProvider,
2311
+ AgentCategoriesPanel,
2312
+ AgentDetailCard,
2313
+ AgentFilterBar,
2314
+ AgentListContent,
2315
+ AgentListDropdown,
2316
+ AgentListInlinePicker,
2317
+ AgentListTabs,
2318
+ AgentMobileSubView,
2319
+ AgentRow,
2320
+ AgentSortPanel,
2321
+ AgentTagsPanel,
2322
+ CheckRow,
2323
+ FavoriteAgentButton,
2324
+ FilterChip,
2325
+ HOVER_GRACE_MS,
2326
+ LIST_MAX_HEIGHT,
2327
+ OptionRow,
2328
+ PANEL_HEIGHT,
2329
+ SORT_OPTIONS,
2330
+ SearchInput,
2331
+ SidePanelHeader,
2332
+ coerceVisibleTab,
2333
+ useAgentCatalog,
2334
+ useAgentCatalogRows,
2335
+ useAgentCatalogState,
2336
+ useAgentCatalogUiPorts,
2337
+ useAgentConsumer,
2338
+ useAgentListCore
2339
+ };
2340
+ //# sourceMappingURL=index.js.map