@ai-matrx/agents 0.8.0 → 0.9.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,2806 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // catalog/native/index.ts
21
+ var native_exports = {};
22
+ __export(native_exports, {
23
+ AgentCatalogProvider: () => AgentCatalogProvider,
24
+ AgentDetailCard: () => AgentDetailCard,
25
+ AgentFilterBar: () => AgentFilterBar,
26
+ AgentIcon: () => AgentIcon,
27
+ AgentListContent: () => AgentListContent,
28
+ AgentListInlinePicker: () => AgentListInlinePicker,
29
+ AgentListSheet: () => AgentListSheet,
30
+ AgentListTabs: () => AgentListTabs,
31
+ AgentPickerBody: () => AgentPickerBody,
32
+ AgentRow: () => AgentRow,
33
+ AgentSubView: () => AgentSubView,
34
+ CheckRow: () => CheckRow,
35
+ DEFAULT_AGENT_CATALOG_NATIVE_THEME: () => DEFAULT_AGENT_CATALOG_NATIVE_THEME,
36
+ FavoriteAgentButton: () => FavoriteAgentButton,
37
+ FilterChip: () => FilterChip,
38
+ HOVER_GRACE_MS: () => HOVER_GRACE_MS,
39
+ LIGHT_AGENT_CATALOG_NATIVE_THEME: () => LIGHT_AGENT_CATALOG_NATIVE_THEME,
40
+ OptionRow: () => OptionRow,
41
+ SearchInput: () => SearchInput,
42
+ SidePanelHeader: () => SidePanelHeader,
43
+ _resetNativeIconState: () => _resetNativeIconState,
44
+ announceMissingSvgOnce: () => announceMissingSvgOnce,
45
+ coerceVisibleTab: () => coerceVisibleTab,
46
+ orchestraDelegatesLine: () => orchestraDelegatesLine,
47
+ orchestraDepthLine: () => orchestraDepthLine,
48
+ orchestraLabel: () => orchestraLabel,
49
+ orchestraModeLabel: () => orchestraModeLabel,
50
+ resolveAgentCatalogNativeTheme: () => resolveAgentCatalogNativeTheme,
51
+ resolveSvgModule: () => resolveSvgModule,
52
+ useAgentCatalog: () => useAgentCatalog,
53
+ useAgentCatalogNativeTheme: () => useAgentCatalogNativeTheme,
54
+ useAgentCatalogRows: () => useAgentCatalogRows,
55
+ useAgentCatalogState: () => useAgentCatalogState,
56
+ useAgentCatalogUiPorts: () => useAgentCatalogUiPorts,
57
+ useAgentConsumer: () => useAgentConsumer,
58
+ useAgentListCore: () => useAgentListCore
59
+ });
60
+ module.exports = __toCommonJS(native_exports);
61
+
62
+ // catalog/native/context.tsx
63
+ var import_react2 = require("react");
64
+ var import_react_native = require("react-native");
65
+
66
+ // catalog/shared/context.tsx
67
+ var import_react = require("react");
68
+ var import_jsx_runtime = require("react/jsx-runtime");
69
+ var AgentCatalogContext = (0, import_react.createContext)(null);
70
+ function AgentCatalogProviderCore({
71
+ catalog,
72
+ platform,
73
+ children,
74
+ ...ports
75
+ }) {
76
+ const value = (0, import_react.useMemo)(
77
+ () => ({ catalog, platform, ...ports }),
78
+ // The ports are plain values a host declares once; re-binding on identity
79
+ // change is correct and cheap.
80
+ [
81
+ catalog,
82
+ platform,
83
+ ports.navigate,
84
+ ports.LinkComponent,
85
+ ports.renderModelRef,
86
+ ports.openPeek,
87
+ ports.popoverContainer
88
+ ]
89
+ );
90
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AgentCatalogContext.Provider, { value, children });
91
+ }
92
+ function useBinding() {
93
+ const binding = (0, import_react.useContext)(AgentCatalogContext);
94
+ if (!binding) {
95
+ throw new Error(
96
+ "@ai-matrx/agents/catalog: 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."
97
+ );
98
+ }
99
+ return binding;
100
+ }
101
+ function useAgentCatalog() {
102
+ return useBinding().catalog;
103
+ }
104
+ function useAgentCatalogUiPorts() {
105
+ const binding = useBinding();
106
+ const hostNavigate = binding.navigate;
107
+ const platformNavigate = binding.platform.navigate;
108
+ const navigate = (0, import_react.useCallback)(
109
+ (href) => {
110
+ if (hostNavigate) {
111
+ hostNavigate(href);
112
+ return;
113
+ }
114
+ platformNavigate(href);
115
+ },
116
+ [hostNavigate, platformNavigate]
117
+ );
118
+ return {
119
+ navigate,
120
+ LinkComponent: binding.LinkComponent ?? binding.platform.LinkComponent,
121
+ renderModelRef: binding.renderModelRef ?? binding.platform.renderModelRef,
122
+ openPeek: binding.openPeek,
123
+ popoverContainer: binding.popoverContainer
124
+ };
125
+ }
126
+ function useAgentCatalogState(select) {
127
+ const catalog = useAgentCatalog();
128
+ const getSnapshot = (0, import_react.useCallback)(
129
+ () => select(catalog.getState()),
130
+ [catalog, select]
131
+ );
132
+ return (0, import_react.useSyncExternalStore)(catalog.subscribe, getSnapshot, getSnapshot);
133
+ }
134
+ function useAgentCatalogRows() {
135
+ return useAgentCatalogState(selectRows);
136
+ }
137
+ var selectRows = (state) => state.rows;
138
+
139
+ // catalog/native/theme.ts
140
+ var DEFAULT_AGENT_CATALOG_NATIVE_THEME = {
141
+ colors: {
142
+ background: "#0b0b0f",
143
+ surface: "#17171d",
144
+ surfacePressed: "#22222b",
145
+ text: "#f5f5f7",
146
+ textMuted: "#9b9ba5",
147
+ textFaint: "#6e6e78",
148
+ border: "#2a2a33",
149
+ primary: "#3b82f6",
150
+ primaryForeground: "#ffffff",
151
+ primarySoft: "#1c2a44",
152
+ // The web sheet's dark value for --matrx-agent-favorite.
153
+ favorite: "#fbbf24",
154
+ driftBackground: "#451a03",
155
+ driftForeground: "#fcd34d",
156
+ driftBorder: "#78350f"
157
+ },
158
+ radius: { sm: 4, md: 8, lg: 12 },
159
+ spacing: { xs: 4, sm: 8, md: 12, lg: 16 },
160
+ fontSize: { xs: 10, sm: 11, md: 13, lg: 15 }
161
+ };
162
+ var LIGHT_AGENT_CATALOG_NATIVE_THEME = {
163
+ ...DEFAULT_AGENT_CATALOG_NATIVE_THEME,
164
+ colors: {
165
+ background: "#ffffff",
166
+ surface: "#f4f4f6",
167
+ surfacePressed: "#e9e9ee",
168
+ text: "#0b0b0f",
169
+ textMuted: "#61616b",
170
+ textFaint: "#8c8c96",
171
+ border: "#e2e2e8",
172
+ primary: "#2563eb",
173
+ primaryForeground: "#ffffff",
174
+ primarySoft: "#e5edfd",
175
+ favorite: "#f59e0b",
176
+ driftBackground: "#fef3c7",
177
+ driftForeground: "#92400e",
178
+ driftBorder: "#fcd34d"
179
+ }
180
+ };
181
+ function resolveAgentCatalogNativeTheme(override, base = DEFAULT_AGENT_CATALOG_NATIVE_THEME) {
182
+ if (!override) return base;
183
+ return {
184
+ colors: { ...base.colors, ...override.colors ?? {} },
185
+ radius: { ...base.radius, ...override.radius ?? {} },
186
+ spacing: { ...base.spacing, ...override.spacing ?? {} },
187
+ fontSize: { ...base.fontSize, ...override.fontSize ?? {} }
188
+ };
189
+ }
190
+
191
+ // catalog/native/context.tsx
192
+ var import_jsx_runtime2 = require("react/jsx-runtime");
193
+ var ThemeContext = (0, import_react2.createContext)(
194
+ DEFAULT_AGENT_CATALOG_NATIVE_THEME
195
+ );
196
+ function useAgentCatalogNativeTheme() {
197
+ return (0, import_react2.useContext)(ThemeContext);
198
+ }
199
+ var NativeLink = ({ children, onClick, title }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
200
+ import_react_native.Pressable,
201
+ {
202
+ accessibilityRole: "link",
203
+ ...title ? { accessibilityLabel: title } : {},
204
+ onPress: () => onClick?.({
205
+ preventDefault: () => {
206
+ },
207
+ stopPropagation: () => {
208
+ }
209
+ }),
210
+ children
211
+ }
212
+ );
213
+ var nativeRenderModelRef = ({ modelId }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native.Text, { children: modelId });
214
+ function AgentCatalogProvider({
215
+ catalog,
216
+ theme,
217
+ children,
218
+ ...ports
219
+ }) {
220
+ const resolvedTheme = (0, import_react2.useMemo)(
221
+ () => resolveAgentCatalogNativeTheme(theme),
222
+ // A theme object is declared once by a host; re-resolving on identity
223
+ // change is correct and cheap.
224
+ [theme]
225
+ );
226
+ const platform = (0, import_react2.useMemo)(
227
+ () => ({
228
+ /**
229
+ * 🚨 THE NATIVE `navigate` DEFAULT. There is no `window.location` to
230
+ * assign, and there is no router this package may assume — Expo Router,
231
+ * React Navigation and a custom stack all differ. So the default is a
232
+ * no-op that REPORTS, with the remedy, through the catalog's own
233
+ * errorSink. It never fails silently, and it never pretends to have
234
+ * navigated. A host that wants working links passes `navigate`.
235
+ */
236
+ navigate: (href) => {
237
+ catalog.errorSink({
238
+ code: "native_navigate_not_bound",
239
+ message: "the agent picker was asked to navigate, but this native host bound no `navigate` port, so nothing moved.",
240
+ context: {
241
+ href,
242
+ remedy: "pass navigate={(href) => router.push(href)} (Expo Router) or your navigator's equivalent to <AgentCatalogProvider>"
243
+ }
244
+ });
245
+ },
246
+ LinkComponent: NativeLink,
247
+ renderModelRef: nativeRenderModelRef
248
+ }),
249
+ [catalog]
250
+ );
251
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ThemeContext.Provider, { value: resolvedTheme, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
252
+ AgentCatalogProviderCore,
253
+ {
254
+ catalog,
255
+ platform,
256
+ ...ports,
257
+ children
258
+ }
259
+ ) });
260
+ }
261
+
262
+ // catalog/native/AgentListSheet.tsx
263
+ var import_react_native12 = require("react-native");
264
+
265
+ // catalog/native/AgentPickerBody.tsx
266
+ var import_react6 = require("react");
267
+ var import_react_native11 = require("react-native");
268
+
269
+ // catalog/shared/useAgentListCore.ts
270
+ var import_react4 = require("react");
271
+
272
+ // catalog/shared/useAgentConsumer.ts
273
+ var import_react3 = require("react");
274
+
275
+ // catalog/types.ts
276
+ function isMandateAgentId(id) {
277
+ return id.startsWith("mandate:");
278
+ }
279
+ var SORT_OPTIONS = [
280
+ { value: "updated-desc", label: "Recent" },
281
+ { value: "created-desc", label: "Created" },
282
+ { value: "name-asc", label: "A \u2192 Z" },
283
+ { value: "name-desc", label: "Z \u2192 A" },
284
+ { value: "category-asc", label: "Category" }
285
+ ];
286
+ var AGENT_NONE_SENTINEL = "__none__";
287
+ var DEFAULT_AGENT_CONSUMER_STATE = {
288
+ tab: "mine",
289
+ sortBy: "updated-desc",
290
+ searchTerm: "",
291
+ includedCats: [],
292
+ includedTags: [],
293
+ favFilter: "all",
294
+ archFilter: "active",
295
+ accessFilter: "any",
296
+ favoritesFirst: true,
297
+ listPage: 1,
298
+ sharedPage: 1,
299
+ serverMatchedIds: [],
300
+ isServerSearching: false,
301
+ deepSearch: false
302
+ };
303
+
304
+ // catalog/shared/useAgentConsumer.ts
305
+ var DEBOUNCE_MS = 250;
306
+ var MIN_QUERY_LENGTH = 2;
307
+ function useAgentConsumer(consumerId, options) {
308
+ const catalog = useAgentCatalog();
309
+ const selectConsumer = (0, import_react3.useCallback)(
310
+ (state) => state.consumers[consumerId] ?? DEFAULT_AGENT_CONSUMER_STATE,
311
+ [consumerId]
312
+ );
313
+ const consumer = useAgentCatalogState(selectConsumer);
314
+ const optionsRef = (0, import_react3.useRef)(options);
315
+ optionsRef.current = options;
316
+ (0, import_react3.useEffect)(() => {
317
+ const opts = optionsRef.current;
318
+ catalog.registerConsumer(
319
+ consumerId,
320
+ opts?.initialTab ? { tab: opts.initialTab } : void 0
321
+ );
322
+ return () => {
323
+ if (optionsRef.current?.unregisterOnUnmount) {
324
+ catalog.unregisterConsumer(consumerId);
325
+ }
326
+ };
327
+ }, [consumerId, catalog]);
328
+ const setSearchTerm = (0, import_react3.useCallback)(
329
+ (value) => catalog.setConsumerFilter(consumerId, { searchTerm: value }),
330
+ [consumerId, catalog]
331
+ );
332
+ const setDeepSearch = (0, import_react3.useCallback)(
333
+ (value) => catalog.setConsumerFilter(consumerId, { deepSearch: value }),
334
+ [consumerId, catalog]
335
+ );
336
+ const setSortBy = (0, import_react3.useCallback)(
337
+ (value) => catalog.setConsumerFilter(consumerId, { sortBy: value }),
338
+ [consumerId, catalog]
339
+ );
340
+ const setTab = (0, import_react3.useCallback)(
341
+ (value) => catalog.setConsumerFilter(consumerId, { tab: value }),
342
+ [consumerId, catalog]
343
+ );
344
+ const setFavFilter = (0, import_react3.useCallback)(
345
+ (value) => catalog.setConsumerFilter(consumerId, { favFilter: value }),
346
+ [consumerId, catalog]
347
+ );
348
+ const setArchFilter = (0, import_react3.useCallback)(
349
+ (value) => catalog.setConsumerFilter(consumerId, { archFilter: value }),
350
+ [consumerId, catalog]
351
+ );
352
+ const setAccessFilter = (0, import_react3.useCallback)(
353
+ (value) => catalog.setConsumerFilter(consumerId, { accessFilter: value }),
354
+ [consumerId, catalog]
355
+ );
356
+ const toggleCategory = (0, import_react3.useCallback)(
357
+ (cat) => {
358
+ const current = catalog.getConsumer(consumerId).includedCats;
359
+ const next = current.includes(cat) ? current.filter((c) => c !== cat) : [...current, cat];
360
+ catalog.setConsumerFilter(consumerId, { includedCats: next });
361
+ },
362
+ [consumerId, catalog]
363
+ );
364
+ const toggleTag = (0, import_react3.useCallback)(
365
+ (tag) => {
366
+ const current = catalog.getConsumer(consumerId).includedTags;
367
+ const next = current.includes(tag) ? current.filter((t) => t !== tag) : [...current, tag];
368
+ catalog.setConsumerFilter(consumerId, { includedTags: next });
369
+ },
370
+ [consumerId, catalog]
371
+ );
372
+ const setIncludedCats = (0, import_react3.useCallback)(
373
+ (next) => catalog.setConsumerFilter(consumerId, { includedCats: next }),
374
+ [consumerId, catalog]
375
+ );
376
+ const setIncludedTags = (0, import_react3.useCallback)(
377
+ (next) => catalog.setConsumerFilter(consumerId, { includedTags: next }),
378
+ [consumerId, catalog]
379
+ );
380
+ const toggleFavoritesFirst = (0, import_react3.useCallback)(
381
+ () => catalog.setConsumerFilter(consumerId, {
382
+ favoritesFirst: !catalog.getConsumer(consumerId).favoritesFirst
383
+ }),
384
+ [consumerId, catalog]
385
+ );
386
+ const loadMoreList = (0, import_react3.useCallback)(
387
+ () => catalog.setConsumerPage(
388
+ consumerId,
389
+ "list",
390
+ catalog.getConsumer(consumerId).listPage + 1
391
+ ),
392
+ [consumerId, catalog]
393
+ );
394
+ const loadMoreShared = (0, import_react3.useCallback)(
395
+ () => catalog.setConsumerPage(
396
+ consumerId,
397
+ "shared",
398
+ catalog.getConsumer(consumerId).sharedPage + 1
399
+ ),
400
+ [consumerId, catalog]
401
+ );
402
+ const resetFilters = (0, import_react3.useCallback)(
403
+ () => catalog.resetConsumerFilters(consumerId),
404
+ [consumerId, catalog]
405
+ );
406
+ const [isSearching, setIsSearching] = (0, import_react3.useState)(false);
407
+ const [matchedIds, setMatchedIds] = (0, import_react3.useState)(null);
408
+ const requestSeq = (0, import_react3.useRef)(0);
409
+ const query = consumer.searchTerm;
410
+ const deep = consumer.deepSearch;
411
+ (0, import_react3.useEffect)(() => {
412
+ const q = query.trim();
413
+ if (q.length < MIN_QUERY_LENGTH) {
414
+ setIsSearching(false);
415
+ setMatchedIds(null);
416
+ return void 0;
417
+ }
418
+ const seq = ++requestSeq.current;
419
+ setIsSearching(true);
420
+ const timer = setTimeout(() => {
421
+ void catalog.searchServer(q, deep).then((ids) => {
422
+ if (seq !== requestSeq.current) return;
423
+ setMatchedIds(ids);
424
+ setIsSearching(false);
425
+ }).catch((e) => {
426
+ if (seq !== requestSeq.current) return;
427
+ catalog.errorSink({
428
+ code: "server_search_failed",
429
+ message: `agent search failed: ${e instanceof Error ? e.message : String(e)}`,
430
+ context: { query: q, deep }
431
+ });
432
+ setIsSearching(false);
433
+ });
434
+ }, DEBOUNCE_MS);
435
+ return () => clearTimeout(timer);
436
+ }, [query, deep, catalog]);
437
+ (0, import_react3.useEffect)(() => {
438
+ catalog.setConsumerServerSearch(consumerId, {
439
+ matchedIds: matchedIds ?? [],
440
+ isSearching
441
+ });
442
+ }, [consumerId, catalog, matchedIds, isSearching]);
443
+ const hasActiveFilters = consumer.searchTerm !== "" || consumer.includedCats.length > 0 || consumer.includedTags.length > 0 || consumer.favFilter !== "all" || consumer.archFilter !== "active" || consumer.accessFilter !== "any" || !consumer.favoritesFirst;
444
+ return {
445
+ tab: consumer.tab,
446
+ sortBy: consumer.sortBy,
447
+ searchTerm: consumer.searchTerm,
448
+ includedCats: consumer.includedCats,
449
+ includedTags: consumer.includedTags,
450
+ favFilter: consumer.favFilter,
451
+ archFilter: consumer.archFilter,
452
+ accessFilter: consumer.accessFilter,
453
+ favoritesFirst: consumer.favoritesFirst,
454
+ listPage: consumer.listPage,
455
+ sharedPage: consumer.sharedPage,
456
+ state: consumer,
457
+ hasActiveFilters,
458
+ deepSearch: consumer.deepSearch,
459
+ isServerSearching: consumer.isServerSearching,
460
+ setSearchTerm,
461
+ setDeepSearch,
462
+ setSortBy,
463
+ setTab,
464
+ setFavFilter,
465
+ setArchFilter,
466
+ setAccessFilter,
467
+ toggleCategory,
468
+ toggleTag,
469
+ setIncludedCats,
470
+ setIncludedTags,
471
+ toggleFavoritesFirst,
472
+ loadMoreList,
473
+ loadMoreShared,
474
+ resetFilters
475
+ };
476
+ }
477
+
478
+ // catalog/labels.ts
479
+ function agentListEmptyLabel(tab, labels) {
480
+ switch (tab) {
481
+ case "system":
482
+ return labels.emptySystem;
483
+ case "shared":
484
+ return labels.emptyShared;
485
+ default:
486
+ return labels.emptyDefault;
487
+ }
488
+ }
489
+ function shouldDefaultAgentListToPublicTab(args) {
490
+ if (!args.userId) return true;
491
+ if (!args.agentsLoaded) return false;
492
+ return args.ownedCount === 0;
493
+ }
494
+
495
+ // catalog/score.ts
496
+ function computeAgentSearchScore(agent, query) {
497
+ const q = query.trim().toLowerCase();
498
+ if (!q) return 0;
499
+ let score = 0;
500
+ const name = (agent.name ?? "").toLowerCase();
501
+ const desc = (agent.description ?? "").toLowerCase();
502
+ if (name === q) score += 1e4;
503
+ else if (name.startsWith(q)) score += 5e3;
504
+ else if (matchesWholeWord(name, q)) score += 3e3;
505
+ else if (name.includes(q)) score += 2e3;
506
+ if (desc === q) score += 1e3;
507
+ else if (desc.includes(q)) score += 500;
508
+ if (agent.category?.toLowerCase().includes(q)) score += 300;
509
+ if (agent.tags?.some((t) => t.toLowerCase().includes(q))) score += 300;
510
+ if (agent.modelId?.toLowerCase().includes(q)) score += 100;
511
+ if (agent.agentType?.toLowerCase().includes(q)) score += 100;
512
+ if (agent.outputFormat?.toLowerCase().includes(q)) score += 100;
513
+ const id = agent.id.toLowerCase();
514
+ if (id === q) score += 1e5;
515
+ else if (id.includes(q)) score += 5e3;
516
+ if (agent.sharedByEmail?.toLowerCase().includes(q)) score += 200;
517
+ if (score === 0 && q.includes(" ")) {
518
+ const terms = q.split(/\s+/).filter(Boolean);
519
+ let hits = 0;
520
+ let termScore = 0;
521
+ for (const term of terms) {
522
+ const inName = name.includes(term);
523
+ const matched = inName || desc.includes(term) || (agent.category?.toLowerCase().includes(term) ?? false) || (agent.tags?.some((t) => t.toLowerCase().includes(term)) ?? false);
524
+ if (matched) {
525
+ hits += 1;
526
+ termScore += inName ? 400 : 100;
527
+ }
528
+ }
529
+ if (hits === terms.length) score += termScore;
530
+ }
531
+ return score;
532
+ }
533
+ function matchesWholeWord(haystack, q) {
534
+ const escaped = q.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
535
+ return new RegExp(`\\b${escaped}\\b`).test(haystack);
536
+ }
537
+ function agentMatchesSearch(agent, query) {
538
+ return computeAgentSearchScore(agent, query) > 0;
539
+ }
540
+
541
+ // catalog/selectors.ts
542
+ function memoize1(fn) {
543
+ let lastA;
544
+ let last;
545
+ let has = false;
546
+ return (a) => {
547
+ if (!has || lastA !== a) {
548
+ last = fn(a);
549
+ lastA = a;
550
+ has = true;
551
+ }
552
+ return last;
553
+ };
554
+ }
555
+ function memoize2(fn) {
556
+ let lastA;
557
+ let lastB;
558
+ let last;
559
+ let has = false;
560
+ return (a, b) => {
561
+ if (!has || lastA !== a || lastB !== b) {
562
+ last = fn(a, b);
563
+ lastA = a;
564
+ lastB = b;
565
+ has = true;
566
+ }
567
+ return last;
568
+ };
569
+ }
570
+ function applyAgentSortComparator(a, b, sortBy) {
571
+ switch (sortBy) {
572
+ case "name-asc":
573
+ return (a.name ?? "").localeCompare(b.name ?? "");
574
+ case "name-desc":
575
+ return (b.name ?? "").localeCompare(a.name ?? "");
576
+ case "created-desc":
577
+ return +new Date(b.createdAt ?? 0) - +new Date(a.createdAt ?? 0);
578
+ case "category-asc":
579
+ return (a.category ?? "").localeCompare(b.category ?? "");
580
+ case "updated-desc":
581
+ default:
582
+ return +new Date(b.updatedAt ?? 0) - +new Date(a.updatedAt ?? 0);
583
+ }
584
+ }
585
+ var selectAllAgentCategories = memoize1(
586
+ (agents) => {
587
+ const cats = /* @__PURE__ */ new Set();
588
+ for (const a of agents) {
589
+ if (a.agentType === "user" && a.category) cats.add(a.category);
590
+ }
591
+ return Array.from(cats).sort();
592
+ }
593
+ );
594
+ var selectAllSystemAgentCategories = memoize1(
595
+ (agents) => {
596
+ const cats = /* @__PURE__ */ new Set();
597
+ for (const a of agents) {
598
+ if (a.agentType === "builtin" && a.category) cats.add(a.category);
599
+ }
600
+ return Array.from(cats).sort();
601
+ }
602
+ );
603
+ var selectAllAgentTags = memoize1(
604
+ (agents) => {
605
+ const tags = /* @__PURE__ */ new Set();
606
+ for (const a of agents) {
607
+ if (a.agentType === "user") a.tags?.forEach((t) => tags.add(t));
608
+ }
609
+ return Array.from(tags).sort();
610
+ }
611
+ );
612
+ var selectAllSystemAgentTags = memoize1(
613
+ (agents) => {
614
+ const tags = /* @__PURE__ */ new Set();
615
+ for (const a of agents) {
616
+ if (a.agentType === "builtin") a.tags?.forEach((t) => tags.add(t));
617
+ }
618
+ return Array.from(tags).sort();
619
+ }
620
+ );
621
+ var selectUserTypeAgents = memoize1(
622
+ (agents) => agents.filter((a) => a.agentType === "user")
623
+ );
624
+ var selectBuiltinTypeAgents = memoize1(
625
+ (agents) => agents.filter((a) => a.agentType === "builtin")
626
+ );
627
+ function sortFilteredAgents(filtered, consumer) {
628
+ const { searchTerm, sortBy, favFilter, favoritesFirst } = consumer;
629
+ if (searchTerm) {
630
+ const scores = /* @__PURE__ */ new Map();
631
+ filtered.forEach((a) => {
632
+ scores.set(a.id, computeAgentSearchScore(a, searchTerm));
633
+ });
634
+ const serverRank = /* @__PURE__ */ new Map();
635
+ consumer.serverMatchedIds.forEach((id, i) => serverRank.set(id, i));
636
+ return [...filtered].sort((a, b) => {
637
+ const sa = scores.get(a.id) ?? 0;
638
+ const sb = scores.get(b.id) ?? 0;
639
+ if (sb !== sa) return sb - sa;
640
+ if (sa === 0) {
641
+ const ra = serverRank.get(a.id);
642
+ const rb = serverRank.get(b.id);
643
+ if (ra !== void 0 && rb !== void 0 && ra !== rb) return ra - rb;
644
+ }
645
+ return applyAgentSortComparator(a, b, sortBy);
646
+ });
647
+ }
648
+ return [...filtered].sort((a, b) => {
649
+ if (favoritesFirst && favFilter === "all") {
650
+ const aFav = a.isFavorite ? 1 : 0;
651
+ const bFav = b.isFavorite ? 1 : 0;
652
+ if (bFav !== aFav) return bFav - aFav;
653
+ }
654
+ return applyAgentSortComparator(a, b, sortBy);
655
+ });
656
+ }
657
+ function filterUserTypeAgents(agents, consumer) {
658
+ const {
659
+ searchTerm,
660
+ includedCats,
661
+ includedTags,
662
+ favFilter,
663
+ archFilter,
664
+ accessFilter,
665
+ tab
666
+ } = consumer;
667
+ const serverMatched = new Set(consumer.serverMatchedIds);
668
+ const filtered = agents.filter((agent) => {
669
+ if (tab === "mine" && agent.isOwner !== true) return false;
670
+ if (tab === "shared" && !(agent.isOwner === false && agent.accessLevel != null))
671
+ return false;
672
+ if (archFilter === "active" && agent.isArchived) return false;
673
+ if (archFilter === "archived" && !agent.isArchived) return false;
674
+ if (favFilter === "yes" && !agent.isFavorite) return false;
675
+ if (favFilter === "no" && agent.isFavorite) return false;
676
+ if (accessFilter === "owned" && agent.isOwner !== true) return false;
677
+ if (accessFilter === "shared" && agent.isOwner !== false) return false;
678
+ if (accessFilter === "editable" && agent.accessLevel !== "owner" && agent.accessLevel !== "admin" && agent.accessLevel !== "editor")
679
+ return false;
680
+ if (includedCats.length > 0) {
681
+ const category = agent.category;
682
+ if (!category) {
683
+ if (!includedCats.includes(AGENT_NONE_SENTINEL)) return false;
684
+ } else if (!includedCats.includes(category)) {
685
+ return false;
686
+ }
687
+ }
688
+ if (includedTags.length > 0) {
689
+ const isUntagged = !agent.tags?.length;
690
+ if (isUntagged) {
691
+ if (!includedTags.includes(AGENT_NONE_SENTINEL)) return false;
692
+ } else if (!agent.tags?.some((t) => includedTags.includes(t))) {
693
+ return false;
694
+ }
695
+ }
696
+ if (searchTerm && !agentMatchesSearch(agent, searchTerm) && !serverMatched.has(agent.id))
697
+ return false;
698
+ return true;
699
+ });
700
+ return sortFilteredAgents(filtered, consumer);
701
+ }
702
+ function filterBuiltinTypeAgents(agents, consumer) {
703
+ const { searchTerm, favFilter, includedCats, includedTags } = consumer;
704
+ const serverMatched = new Set(consumer.serverMatchedIds);
705
+ const filtered = agents.filter((agent) => {
706
+ if (favFilter === "yes" && !agent.isFavorite) return false;
707
+ if (favFilter === "no" && agent.isFavorite) return false;
708
+ if (includedCats.length > 0) {
709
+ const category = agent.category;
710
+ if (!category) {
711
+ if (!includedCats.includes(AGENT_NONE_SENTINEL)) return false;
712
+ } else if (!includedCats.includes(category)) {
713
+ return false;
714
+ }
715
+ }
716
+ if (includedTags.length > 0) {
717
+ const isUntagged = !agent.tags?.length;
718
+ if (isUntagged) {
719
+ if (!includedTags.includes(AGENT_NONE_SENTINEL)) return false;
720
+ } else if (!agent.tags?.some((t) => includedTags.includes(t))) {
721
+ return false;
722
+ }
723
+ }
724
+ if (searchTerm && !agentMatchesSearch(agent, searchTerm) && !serverMatched.has(agent.id))
725
+ return false;
726
+ return true;
727
+ });
728
+ return sortFilteredAgents(filtered, consumer);
729
+ }
730
+ var makeSelectFilteredAgents = (includeSystemInAll = false) => memoize2(
731
+ (agents, consumer) => {
732
+ const userAgents = selectUserTypeAgents(agents);
733
+ const builtinAgents = selectBuiltinTypeAgents(agents);
734
+ if (consumer.tab === "system") {
735
+ return filterBuiltinTypeAgents(builtinAgents, consumer);
736
+ }
737
+ if (includeSystemInAll && consumer.tab === "all") {
738
+ return [
739
+ ...filterUserTypeAgents(userAgents, consumer),
740
+ ...filterBuiltinTypeAgents(builtinAgents, consumer)
741
+ ];
742
+ }
743
+ return filterUserTypeAgents(userAgents, consumer);
744
+ }
745
+ );
746
+ var selectTotalUserAgentsCount = memoize1(
747
+ (agents) => selectUserTypeAgents(agents).length
748
+ );
749
+ var selectTotalOwnedAgentsCount = memoize1(
750
+ (agents) => selectUserTypeAgents(agents).filter((a) => a.isOwner === true).length
751
+ );
752
+ var selectTotalSharedAgentsCount = memoize1(
753
+ (agents) => selectUserTypeAgents(agents).filter(
754
+ (a) => a.isOwner === false && a.accessLevel != null
755
+ ).length
756
+ );
757
+ var selectTotalBuiltinAgentsCount = memoize1(
758
+ (agents) => selectBuiltinTypeAgents(agents).length
759
+ );
760
+ var selectTotalFavoriteAgentsCount = memoize1(
761
+ (agents) => selectUserTypeAgents(agents).filter((a) => a.isFavorite).length
762
+ );
763
+
764
+ // catalog/shared/useAgentListCore.ts
765
+ var HOVER_GRACE_MS = 900;
766
+ function coerceVisibleTab(current, allowed, initialTab) {
767
+ if (allowed.length === 0) return null;
768
+ if (allowed.includes(current)) return null;
769
+ return initialTab && allowed.includes(initialTab) ? initialTab : allowed[0] ?? null;
770
+ }
771
+ var EMPTY_EXCLUDES = [];
772
+ function useAgentListCore({
773
+ consumerId,
774
+ onSelect,
775
+ navigateTo,
776
+ activeAgentIdOverride,
777
+ initialTab,
778
+ includeSystemInAll = false,
779
+ visibleTabs,
780
+ excludeAgentIds = EMPTY_EXCLUDES,
781
+ defaultMandateKey
782
+ }) {
783
+ const catalog = useAgentCatalog();
784
+ const { navigate } = useAgentCatalogUiPorts();
785
+ const hasFetchedRef = (0, import_react4.useRef)(false);
786
+ const [hoveredAgent, setHoveredAgent] = (0, import_react4.useState)(null);
787
+ const hoverLeaveTimerRef = (0, import_react4.useRef)(null);
788
+ const defaultTabAppliedRef = (0, import_react4.useRef)(false);
789
+ const consumer = useAgentConsumer(consumerId, { unregisterOnUnmount: true });
790
+ const rows = useAgentCatalogRows();
791
+ const userId = catalog.getUserIdOrNull();
792
+ const ownedCount = selectTotalOwnedAgentsCount(rows);
793
+ const selectFiltered = (0, import_react4.useMemo)(
794
+ () => makeSelectFilteredAgents(includeSystemInAll),
795
+ [includeSystemInAll]
796
+ );
797
+ const filteredAgents = selectFiltered(rows, consumer.state);
798
+ const excludedAgentIds = (0, import_react4.useMemo)(
799
+ () => new Set(excludeAgentIds),
800
+ [excludeAgentIds]
801
+ );
802
+ const agents = excludedAgentIds.size === 0 ? filteredAgents : filteredAgents.filter((agent) => !excludedAgentIds.has(agent.id));
803
+ const status = useAgentCatalogState(selectStatus);
804
+ const activeAgentId = activeAgentIdOverride ?? null;
805
+ const pinnedAgent = activeAgentId ? catalog.getAgent(activeAgentId) : void 0;
806
+ const onSystemTab = consumer.tab === "system";
807
+ const allCategories = onSystemTab ? selectAllSystemAgentCategories(rows) : selectAllAgentCategories(rows);
808
+ const allTags = onSystemTab ? selectAllSystemAgentTags(rows) : selectAllAgentTags(rows);
809
+ const tabCounts = {
810
+ mine: ownedCount,
811
+ shared: selectTotalSharedAgentsCount(rows),
812
+ all: selectTotalUserAgentsCount(rows),
813
+ system: selectTotalBuiltinAgentsCount(rows)
814
+ };
815
+ const isLoading = status === "loading";
816
+ const agentsLoaded = status === "succeeded" || status === "failed";
817
+ const ensureLoaded = (0, import_react4.useCallback)(() => {
818
+ if (!hasFetchedRef.current) {
819
+ hasFetchedRef.current = true;
820
+ void catalog.ensureLoaded().catch(() => {
821
+ });
822
+ }
823
+ }, [catalog]);
824
+ const selectDefaultRow = (0, import_react4.useCallback)(
825
+ (state) => defaultMandateKey ? state.defaultRows[defaultMandateKey] : void 0,
826
+ [defaultMandateKey]
827
+ );
828
+ const defaultRow = useAgentCatalogState(selectDefaultRow);
829
+ (0, import_react4.useEffect)(() => {
830
+ if (!defaultMandateKey) return;
831
+ catalog.ensureDefaultRow(defaultMandateKey);
832
+ }, [catalog, defaultMandateKey]);
833
+ (0, import_react4.useEffect)(() => {
834
+ if (defaultTabAppliedRef.current) return;
835
+ if (initialTab) {
836
+ defaultTabAppliedRef.current = true;
837
+ if (consumer.tab !== initialTab) consumer.setTab(initialTab);
838
+ return;
839
+ }
840
+ if (consumer.tab !== "mine") {
841
+ defaultTabAppliedRef.current = true;
842
+ return;
843
+ }
844
+ const wantsPublic = shouldDefaultAgentListToPublicTab({
845
+ userId,
846
+ ownedCount,
847
+ agentsLoaded
848
+ });
849
+ if (!wantsPublic) {
850
+ if (!userId || agentsLoaded) {
851
+ defaultTabAppliedRef.current = true;
852
+ }
853
+ return;
854
+ }
855
+ consumer.setTab("system");
856
+ defaultTabAppliedRef.current = true;
857
+ }, [
858
+ userId,
859
+ ownedCount,
860
+ agentsLoaded,
861
+ initialTab,
862
+ consumer.tab,
863
+ consumer.setTab
864
+ ]);
865
+ const allowedTabsKey = visibleTabs ? visibleTabs.join(",") : "";
866
+ (0, import_react4.useEffect)(() => {
867
+ if (!allowedTabsKey) return;
868
+ const next = coerceVisibleTab(
869
+ consumer.tab,
870
+ allowedTabsKey.split(","),
871
+ initialTab
872
+ );
873
+ if (next) consumer.setTab(next);
874
+ }, [allowedTabsKey, initialTab, consumer.tab, consumer.setTab]);
875
+ (0, import_react4.useEffect)(() => {
876
+ ensureLoaded();
877
+ }, [ensureLoaded]);
878
+ const handleSelectAgent = (0, import_react4.useCallback)(
879
+ (agent) => {
880
+ if (onSelect) {
881
+ onSelect(agent.id);
882
+ } else if (navigateTo) {
883
+ navigate(navigateTo.replace("{id}", agent.id));
884
+ } else {
885
+ catalog.errorSink({
886
+ code: "select_has_nowhere_to_go",
887
+ message: "an agent was chosen but this picker was given neither onSelect nor navigateTo, so the choice went nowhere.",
888
+ context: { consumerId, agentId: agent.id }
889
+ });
890
+ }
891
+ },
892
+ [onSelect, navigateTo, navigate, catalog, consumerId]
893
+ );
894
+ 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);
895
+ const handleAgentHover = (0, import_react4.useCallback)(
896
+ (agent, panelOpen) => {
897
+ if (panelOpen) return;
898
+ if (hoverLeaveTimerRef.current) {
899
+ clearTimeout(hoverLeaveTimerRef.current);
900
+ hoverLeaveTimerRef.current = null;
901
+ }
902
+ setHoveredAgent(agent);
903
+ },
904
+ []
905
+ );
906
+ const handleAgentHoverEnd = (0, import_react4.useCallback)(
907
+ (agent, onClear) => {
908
+ if (hoveredAgent?.id === agent.id) {
909
+ hoverLeaveTimerRef.current = setTimeout(() => {
910
+ setHoveredAgent(null);
911
+ onClear();
912
+ }, HOVER_GRACE_MS);
913
+ }
914
+ },
915
+ [hoveredAgent]
916
+ );
917
+ const handleDetailPanelMouseEnter = (0, import_react4.useCallback)(() => {
918
+ if (hoverLeaveTimerRef.current) {
919
+ clearTimeout(hoverLeaveTimerRef.current);
920
+ hoverLeaveTimerRef.current = null;
921
+ }
922
+ }, []);
923
+ const handleDetailPanelMouseLeave = (0, import_react4.useCallback)((onClear) => {
924
+ hoverLeaveTimerRef.current = setTimeout(() => {
925
+ setHoveredAgent(null);
926
+ onClear();
927
+ }, HOVER_GRACE_MS);
928
+ }, []);
929
+ (0, import_react4.useEffect)(
930
+ () => () => {
931
+ if (hoverLeaveTimerRef.current) clearTimeout(hoverLeaveTimerRef.current);
932
+ },
933
+ []
934
+ );
935
+ return {
936
+ agents,
937
+ isLoading,
938
+ activeAgentId,
939
+ pinnedAgent: pinnedAgent ?? null,
940
+ defaultRow: defaultRow ?? null,
941
+ allCategories,
942
+ allTags,
943
+ consumer,
944
+ tabCounts,
945
+ activeFilterCount,
946
+ hoveredAgent,
947
+ setHoveredAgent,
948
+ ensureLoaded,
949
+ handleSelectAgent,
950
+ handleAgentHover,
951
+ handleAgentHoverEnd,
952
+ handleDetailPanelMouseEnter,
953
+ handleDetailPanelMouseLeave
954
+ };
955
+ }
956
+ var selectStatus = (state) => state.status;
957
+
958
+ // catalog/native/AgentDetailCard.tsx
959
+ var import_react_native4 = require("react-native");
960
+
961
+ // catalog/orchestra.ts
962
+ var ORCHESTRA_MODE_LABEL = {
963
+ supervisor: "supervisor",
964
+ sequential: "in order",
965
+ parallel: "together",
966
+ dag: "custom flow"
967
+ };
968
+ function orchestraModeLabel(mode) {
969
+ return ORCHESTRA_MODE_LABEL[mode] ?? mode;
970
+ }
971
+ function orchestraLabel(badge) {
972
+ const n = badge.memberCount;
973
+ return `Orchestra \xB7 ${orchestraModeLabel(badge.mode)} \xB7 ${n} ${n === 1 ? "member" : "members"}`;
974
+ }
975
+ function orchestraDepthLine(badge) {
976
+ const n = badge.depthBudget;
977
+ if (typeof n !== "number" || n <= 0) return null;
978
+ return `Team members can call helpers up to ${n} ${n === 1 ? "level" : "levels"} deep`;
979
+ }
980
+ function orchestraDelegatesLine(badge, limit = 3) {
981
+ const titles = badge.memberTitles;
982
+ if (titles.length === 0) return null;
983
+ const shown = titles.slice(0, limit);
984
+ const extra = titles.length - shown.length;
985
+ return `Delegates to: ${shown.join(", ")}${extra > 0 ? ` +${extra} more` : ""}`;
986
+ }
987
+
988
+ // catalog/native/icons.tsx
989
+ var import_react_native2 = require("react-native");
990
+
991
+ // catalog/shared/icon-paths.ts
992
+ var SHAPES = {
993
+ star: {
994
+ paths: [
995
+ "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"
996
+ ],
997
+ fillable: true
998
+ },
999
+ chevronRight: { paths: ["m9 18 6-6-6-6"] },
1000
+ chevronDown: { paths: ["m6 9 6 6 6-6"] },
1001
+ search: {
1002
+ paths: ["m21 21-4.3-4.3"],
1003
+ circles: [{ cx: 11, cy: 11, r: 8 }]
1004
+ },
1005
+ x: { paths: ["M18 6 6 18", "m6 6 12 12"] },
1006
+ check: { paths: ["M20 6 9 17l-5-5"] },
1007
+ arrowUpDown: {
1008
+ paths: ["m21 16-4 4-4-4", "M17 20V4", "m3 8 4-4 4 4", "M7 4v16"]
1009
+ },
1010
+ folder: {
1011
+ paths: [
1012
+ "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"
1013
+ ]
1014
+ },
1015
+ tag: {
1016
+ paths: [
1017
+ "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"
1018
+ ],
1019
+ circles: [{ cx: 7.5, cy: 7.5, r: 0.5, filled: true }]
1020
+ },
1021
+ rotateCcw: {
1022
+ paths: [
1023
+ "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",
1024
+ "M3 3v5h5"
1025
+ ]
1026
+ },
1027
+ loader: { paths: ["M21 12a9 9 0 1 1-6.219-8.56"] },
1028
+ alertTriangle: {
1029
+ paths: [
1030
+ "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",
1031
+ "M12 9v4",
1032
+ "M12 17h.01"
1033
+ ]
1034
+ },
1035
+ /**
1036
+ * The Orchestra marker (Lucide `music-4`): the glyph the Workflow Studio's
1037
+ * picker used for a conductor, kept identical so the same agent wears the
1038
+ * same mark in every client.
1039
+ */
1040
+ music4: {
1041
+ paths: ["M9 18V5l12-2v13", "m9 9 12-2"],
1042
+ circles: [
1043
+ { cx: 6, cy: 18, r: 3 },
1044
+ { cx: 18, cy: 16, r: 3 }
1045
+ ]
1046
+ },
1047
+ clock: {
1048
+ paths: ["M12 6v6l4 2"],
1049
+ circles: [{ cx: 12, cy: 12, r: 10 }]
1050
+ },
1051
+ globe: {
1052
+ paths: ["M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20", "M2 12h20"],
1053
+ circles: [{ cx: 12, cy: 12, r: 10 }]
1054
+ },
1055
+ users: {
1056
+ paths: [
1057
+ "M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2",
1058
+ "M22 21v-2a4 4 0 0 0-3-3.87",
1059
+ "M16 3.13a4 4 0 0 1 0 7.75"
1060
+ ],
1061
+ circles: [{ cx: 9, cy: 7, r: 4 }]
1062
+ },
1063
+ externalLink: {
1064
+ paths: [
1065
+ "M15 3h6v6",
1066
+ "M10 14 21 3",
1067
+ "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"
1068
+ ]
1069
+ },
1070
+ messageCircle: { paths: ["M7.9 20A9 9 0 1 0 4 16.1L2 22Z"] },
1071
+ rocket: {
1072
+ paths: [
1073
+ "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",
1074
+ "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",
1075
+ "M9 12H4s.55-3.03 2-4c1.62-1.08 5 0 5 0",
1076
+ "M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5"
1077
+ ]
1078
+ },
1079
+ circleCheck: {
1080
+ paths: ["m9 12 2 2 4-4"],
1081
+ circles: [{ cx: 12, cy: 12, r: 10 }]
1082
+ }
1083
+ };
1084
+ var ICON_PATHS = SHAPES;
1085
+ var ICON_NAMES = Object.keys(ICON_PATHS);
1086
+
1087
+ // catalog/native/icons.tsx
1088
+ var import_jsx_runtime3 = require("react/jsx-runtime");
1089
+ var STATE_KEY = /* @__PURE__ */ Symbol.for("ai-matrx.agents.catalog.native.icons");
1090
+ function getIconsGlobalState() {
1091
+ const store = globalThis;
1092
+ const existing = store[STATE_KEY];
1093
+ if (existing) return existing;
1094
+ const created = { svg: void 0, announced: false };
1095
+ store[STATE_KEY] = created;
1096
+ return created;
1097
+ }
1098
+ function _resetNativeIconState(svg) {
1099
+ const state = getIconsGlobalState();
1100
+ state.svg = svg === void 0 ? void 0 : svg;
1101
+ state.announced = false;
1102
+ }
1103
+ function isSvgModule(value) {
1104
+ if (typeof value !== "object" || value === null) return false;
1105
+ const record = value;
1106
+ return Boolean(record["Path"] && record["Circle"] && record["default"]);
1107
+ }
1108
+ function resolveSvgModule() {
1109
+ const state = getIconsGlobalState();
1110
+ if (state.svg !== void 0) return state.svg;
1111
+ let resolved = null;
1112
+ try {
1113
+ const required = globalThis.require?.("react-native-svg");
1114
+ if (isSvgModule(required)) resolved = required;
1115
+ else {
1116
+ const viaModule = require("react-native-svg");
1117
+ if (isSvgModule(viaModule)) resolved = viaModule;
1118
+ }
1119
+ } catch {
1120
+ resolved = null;
1121
+ }
1122
+ state.svg = resolved;
1123
+ return resolved;
1124
+ }
1125
+ function announceMissingSvgOnce(report) {
1126
+ const state = getIconsGlobalState();
1127
+ if (state.announced) return;
1128
+ state.announced = true;
1129
+ report({
1130
+ code: "native_icons_degraded_to_text",
1131
+ message: "react-native-svg is not installed, so the agent picker is drawing its icons as text glyphs. Every control still works and every label is still correct \u2014 only the glyphs are plainer.",
1132
+ context: {
1133
+ remedy: "run `npx expo install react-native-svg` (it is an optional peer of @ai-matrx/agents) and reload to get the real icons"
1134
+ }
1135
+ });
1136
+ }
1137
+ var TEXT_GLYPHS = {
1138
+ star: "\u2605",
1139
+ chevronRight: "\u203A",
1140
+ chevronDown: "\u2304",
1141
+ search: "\u2315",
1142
+ x: "\u2715",
1143
+ check: "\u2713",
1144
+ arrowUpDown: "\u21C5",
1145
+ folder: "\u25A4",
1146
+ tag: "\u2317",
1147
+ rotateCcw: "\u21BA",
1148
+ loader: "\u25CC",
1149
+ alertTriangle: "\u26A0",
1150
+ music4: "\u266A",
1151
+ clock: "\u25F7",
1152
+ globe: "\u2295",
1153
+ users: "\u2687",
1154
+ externalLink: "\u2197",
1155
+ messageCircle: "\u2709",
1156
+ rocket: "\u27A4",
1157
+ circleCheck: "\u2713"
1158
+ };
1159
+ function AgentIcon({
1160
+ name,
1161
+ size = 14,
1162
+ color,
1163
+ filled = false,
1164
+ report
1165
+ }) {
1166
+ const svg = resolveSvgModule();
1167
+ if (!svg) {
1168
+ announceMissingSvgOnce(report);
1169
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1170
+ import_react_native2.Text,
1171
+ {
1172
+ accessible: false,
1173
+ style: { color, fontSize: size, lineHeight: size * 1.2 },
1174
+ children: TEXT_GLYPHS[name]
1175
+ }
1176
+ );
1177
+ }
1178
+ const Svg = svg.default;
1179
+ const Path = svg.Path;
1180
+ const Circle = svg.Circle;
1181
+ const shape = ICON_PATHS[name];
1182
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1183
+ Svg,
1184
+ {
1185
+ width: size,
1186
+ height: size,
1187
+ viewBox: "0 0 24 24",
1188
+ fill: "none",
1189
+ stroke: color,
1190
+ strokeWidth: 2,
1191
+ strokeLinecap: "round",
1192
+ strokeLinejoin: "round",
1193
+ children: [
1194
+ shape.paths.map((d, index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1195
+ Path,
1196
+ {
1197
+ d,
1198
+ ...filled && shape.fillable ? { fill: color } : {}
1199
+ },
1200
+ `p${index}`
1201
+ )),
1202
+ (shape.circles ?? []).map((circle, index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1203
+ Circle,
1204
+ {
1205
+ cx: circle.cx,
1206
+ cy: circle.cy,
1207
+ r: circle.r,
1208
+ ...circle.filled ? { fill: color } : {}
1209
+ },
1210
+ `c${index}`
1211
+ ))
1212
+ ]
1213
+ }
1214
+ );
1215
+ }
1216
+
1217
+ // catalog/native/FavoriteAgentButton.tsx
1218
+ var import_react5 = require("react");
1219
+ var import_react_native3 = require("react-native");
1220
+ var import_jsx_runtime4 = require("react/jsx-runtime");
1221
+ function FavoriteAgentButton({
1222
+ id,
1223
+ size = 18,
1224
+ disabled
1225
+ }) {
1226
+ const catalog = useAgentCatalog();
1227
+ const theme = useAgentCatalogNativeTheme();
1228
+ const select = (0, import_react5.useCallback)((state) => state.byId[id], [id]);
1229
+ const record = useAgentCatalogState(select);
1230
+ const isFavorite = record?.isFavorite ?? false;
1231
+ const isOwner = record?.isOwner ?? true;
1232
+ const inert = Boolean(disabled) || !isOwner;
1233
+ const title = isOwner ? isFavorite ? "Remove from favorites" : "Add to favorites" : "Shared \u2014 cannot favorite";
1234
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1235
+ import_react_native3.Pressable,
1236
+ {
1237
+ onPress: () => {
1238
+ if (inert) return;
1239
+ void catalog.setFavorite(id, !isFavorite).catch(() => {
1240
+ });
1241
+ },
1242
+ disabled: inert,
1243
+ hitSlop: 8,
1244
+ accessibilityRole: "button",
1245
+ accessibilityLabel: title,
1246
+ accessibilityState: { disabled: inert, selected: isFavorite },
1247
+ style: { opacity: inert ? 0.4 : 1 },
1248
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1249
+ AgentIcon,
1250
+ {
1251
+ name: "star",
1252
+ size,
1253
+ filled: isFavorite,
1254
+ color: isFavorite ? theme.colors.favorite : theme.colors.textFaint,
1255
+ report: catalog.errorSink
1256
+ }
1257
+ )
1258
+ }
1259
+ );
1260
+ }
1261
+
1262
+ // catalog/native/AgentDetailCard.tsx
1263
+ var import_jsx_runtime5 = require("react/jsx-runtime");
1264
+ function formatDate(value) {
1265
+ if (!value) return null;
1266
+ const date = new Date(value);
1267
+ if (Number.isNaN(date.getTime())) return null;
1268
+ return date.toLocaleDateString(void 0, {
1269
+ month: "short",
1270
+ day: "numeric",
1271
+ year: "numeric"
1272
+ });
1273
+ }
1274
+ function AgentDetailCard({ agent, onSelect }) {
1275
+ const { errorSink } = useAgentCatalog();
1276
+ const { renderModelRef, openPeek } = useAgentCatalogUiPorts();
1277
+ const theme = useAgentCatalogNativeTheme();
1278
+ const isDefaultRow = isMandateAgentId(agent.id);
1279
+ const updated = formatDate(agent.updatedAt);
1280
+ const created = formatDate(agent.createdAt);
1281
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native4.View, { style: styles.container, children: [
1282
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native4.View, { style: [styles.header, { padding: theme.spacing.md }], children: [
1283
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native4.View, { style: { flex: 1, minWidth: 0 }, children: [
1284
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1285
+ import_react_native4.Text,
1286
+ {
1287
+ numberOfLines: 2,
1288
+ style: {
1289
+ color: theme.colors.text,
1290
+ fontSize: theme.fontSize.lg,
1291
+ fontWeight: "600"
1292
+ },
1293
+ children: agent.name || "Untitled"
1294
+ }
1295
+ ),
1296
+ agent.isFavorite && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1297
+ import_react_native4.Text,
1298
+ {
1299
+ style: { color: theme.colors.favorite, fontSize: theme.fontSize.sm },
1300
+ children: "Pinned to favorites"
1301
+ }
1302
+ )
1303
+ ] }),
1304
+ !isDefaultRow && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(FavoriteAgentButton, { id: agent.id })
1305
+ ] }),
1306
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native4.View, { style: { height: import_react_native4.StyleSheet.hairlineWidth, backgroundColor: theme.colors.border } }),
1307
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1308
+ import_react_native4.ScrollView,
1309
+ {
1310
+ style: styles.body,
1311
+ contentContainerStyle: { padding: theme.spacing.md, gap: theme.spacing.md },
1312
+ children: [
1313
+ agent.orchestra && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1314
+ import_react_native4.View,
1315
+ {
1316
+ style: [
1317
+ styles.orchestra,
1318
+ {
1319
+ borderColor: theme.colors.primary,
1320
+ backgroundColor: theme.colors.primarySoft,
1321
+ borderRadius: theme.radius.md,
1322
+ padding: theme.spacing.sm
1323
+ }
1324
+ ],
1325
+ children: [
1326
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native4.View, { style: styles.inline, children: [
1327
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1328
+ AgentIcon,
1329
+ {
1330
+ name: "music4",
1331
+ size: 14,
1332
+ color: theme.colors.primary,
1333
+ report: errorSink
1334
+ }
1335
+ ),
1336
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1337
+ import_react_native4.Text,
1338
+ {
1339
+ style: {
1340
+ color: theme.colors.primary,
1341
+ fontSize: theme.fontSize.sm,
1342
+ fontWeight: "600"
1343
+ },
1344
+ children: orchestraLabel(agent.orchestra)
1345
+ }
1346
+ )
1347
+ ] }),
1348
+ agent.orchestra.tagline && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native4.Text, { style: { color: theme.colors.text, fontSize: theme.fontSize.md }, children: agent.orchestra.tagline }),
1349
+ orchestraDelegatesLine(agent.orchestra) && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1350
+ import_react_native4.Text,
1351
+ {
1352
+ style: { color: theme.colors.textMuted, fontSize: theme.fontSize.sm },
1353
+ children: orchestraDelegatesLine(agent.orchestra)
1354
+ }
1355
+ ),
1356
+ orchestraDepthLine(agent.orchestra) && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1357
+ import_react_native4.Text,
1358
+ {
1359
+ style: { color: theme.colors.textMuted, fontSize: theme.fontSize.sm },
1360
+ children: orchestraDepthLine(agent.orchestra)
1361
+ }
1362
+ )
1363
+ ]
1364
+ }
1365
+ ),
1366
+ agent.description && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native4.View, { style: { gap: 4 }, children: [
1367
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1368
+ import_react_native4.Text,
1369
+ {
1370
+ style: {
1371
+ color: theme.colors.textMuted,
1372
+ fontSize: theme.fontSize.sm,
1373
+ fontWeight: "600",
1374
+ textTransform: "uppercase"
1375
+ },
1376
+ children: "Description"
1377
+ }
1378
+ ),
1379
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native4.Text, { style: { color: theme.colors.text, fontSize: theme.fontSize.md }, children: agent.description })
1380
+ ] }),
1381
+ agent.category && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native4.View, { style: styles.inline, children: [
1382
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1383
+ AgentIcon,
1384
+ {
1385
+ name: "folder",
1386
+ size: 14,
1387
+ color: theme.colors.textMuted,
1388
+ report: errorSink
1389
+ }
1390
+ ),
1391
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native4.Text, { style: { color: theme.colors.text, fontSize: theme.fontSize.md }, children: agent.category })
1392
+ ] }),
1393
+ agent.tags.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native4.View, { style: { gap: 6 }, children: [
1394
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native4.View, { style: styles.inline, children: [
1395
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1396
+ AgentIcon,
1397
+ {
1398
+ name: "tag",
1399
+ size: 14,
1400
+ color: theme.colors.textMuted,
1401
+ report: errorSink
1402
+ }
1403
+ ),
1404
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1405
+ import_react_native4.Text,
1406
+ {
1407
+ style: { color: theme.colors.textMuted, fontSize: theme.fontSize.sm },
1408
+ children: "Tags"
1409
+ }
1410
+ )
1411
+ ] }),
1412
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native4.View, { style: styles.tagWrap, children: agent.tags.map((tag) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1413
+ import_react_native4.Text,
1414
+ {
1415
+ style: {
1416
+ color: theme.colors.textMuted,
1417
+ backgroundColor: theme.colors.surface,
1418
+ borderRadius: theme.radius.sm,
1419
+ overflow: "hidden",
1420
+ paddingHorizontal: 6,
1421
+ paddingVertical: 2,
1422
+ fontSize: theme.fontSize.xs
1423
+ },
1424
+ children: tag
1425
+ },
1426
+ tag
1427
+ )) })
1428
+ ] }),
1429
+ agent.accessLevel && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native4.View, { style: styles.inline, children: [
1430
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1431
+ AgentIcon,
1432
+ {
1433
+ name: agent.isOwner === false ? "users" : "globe",
1434
+ size: 14,
1435
+ color: theme.colors.textMuted,
1436
+ report: errorSink
1437
+ }
1438
+ ),
1439
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native4.View, { children: [
1440
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native4.Text, { style: { color: theme.colors.text, fontSize: theme.fontSize.md }, children: agent.accessLevel === "owner" ? "You own this" : `Shared \u2014 ${agent.accessLevel}` }),
1441
+ agent.sharedByEmail && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1442
+ import_react_native4.Text,
1443
+ {
1444
+ style: { color: theme.colors.textMuted, fontSize: theme.fontSize.xs },
1445
+ children: [
1446
+ "by ",
1447
+ agent.sharedByEmail
1448
+ ]
1449
+ }
1450
+ )
1451
+ ] })
1452
+ ] }),
1453
+ agent.modelId && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native4.View, { children: renderModelRef({ modelId: agent.modelId }) }),
1454
+ (updated || created) && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native4.View, { style: { gap: 4 }, children: [
1455
+ updated && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native4.View, { style: styles.inline, children: [
1456
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1457
+ AgentIcon,
1458
+ {
1459
+ name: "clock",
1460
+ size: 13,
1461
+ color: theme.colors.textMuted,
1462
+ report: errorSink
1463
+ }
1464
+ ),
1465
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1466
+ import_react_native4.Text,
1467
+ {
1468
+ style: { color: theme.colors.textMuted, fontSize: theme.fontSize.sm },
1469
+ children: [
1470
+ "Updated ",
1471
+ updated
1472
+ ]
1473
+ }
1474
+ )
1475
+ ] }),
1476
+ created && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native4.View, { style: styles.inline, children: [
1477
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1478
+ AgentIcon,
1479
+ {
1480
+ name: "clock",
1481
+ size: 13,
1482
+ color: theme.colors.textFaint,
1483
+ report: errorSink
1484
+ }
1485
+ ),
1486
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1487
+ import_react_native4.Text,
1488
+ {
1489
+ style: { color: theme.colors.textFaint, fontSize: theme.fontSize.sm },
1490
+ children: [
1491
+ "Created ",
1492
+ created
1493
+ ]
1494
+ }
1495
+ )
1496
+ ] })
1497
+ ] })
1498
+ ]
1499
+ }
1500
+ ),
1501
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native4.View, { style: { height: import_react_native4.StyleSheet.hairlineWidth, backgroundColor: theme.colors.border } }),
1502
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native4.View, { style: [styles.footer, { padding: theme.spacing.sm }], children: [
1503
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1504
+ import_react_native4.Pressable,
1505
+ {
1506
+ onPress: onSelect,
1507
+ accessibilityRole: "button",
1508
+ accessibilityLabel: `Select ${agent.name || "Untitled"}`,
1509
+ style: ({ pressed }) => [
1510
+ styles.selectButton,
1511
+ {
1512
+ borderRadius: theme.radius.md,
1513
+ backgroundColor: theme.colors.primary,
1514
+ opacity: pressed ? 0.85 : 1
1515
+ }
1516
+ ],
1517
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1518
+ import_react_native4.Text,
1519
+ {
1520
+ style: {
1521
+ color: theme.colors.primaryForeground,
1522
+ fontSize: theme.fontSize.md,
1523
+ fontWeight: "600"
1524
+ },
1525
+ children: "Select"
1526
+ }
1527
+ )
1528
+ }
1529
+ ),
1530
+ openPeek && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1531
+ import_react_native4.Pressable,
1532
+ {
1533
+ onPress: () => openPeek(agent),
1534
+ accessibilityRole: "button",
1535
+ accessibilityLabel: "Sneak Peek",
1536
+ style: ({ pressed }) => [
1537
+ styles.iconButton,
1538
+ {
1539
+ borderRadius: theme.radius.md,
1540
+ borderColor: theme.colors.border,
1541
+ backgroundColor: pressed ? theme.colors.surfacePressed : theme.colors.surface
1542
+ }
1543
+ ],
1544
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1545
+ AgentIcon,
1546
+ {
1547
+ name: "rocket",
1548
+ size: 14,
1549
+ color: theme.colors.textMuted,
1550
+ report: errorSink
1551
+ }
1552
+ )
1553
+ }
1554
+ )
1555
+ ] })
1556
+ ] });
1557
+ }
1558
+ var styles = import_react_native4.StyleSheet.create({
1559
+ container: { flex: 1, minHeight: 0 },
1560
+ header: { flexDirection: "row", alignItems: "flex-start", gap: 12 },
1561
+ body: { flex: 1, minHeight: 0 },
1562
+ inline: { flexDirection: "row", alignItems: "center", gap: 8 },
1563
+ orchestra: { borderWidth: import_react_native4.StyleSheet.hairlineWidth, gap: 4 },
1564
+ tagWrap: { flexDirection: "row", flexWrap: "wrap", gap: 4 },
1565
+ footer: { flexDirection: "row", alignItems: "center", gap: 8 },
1566
+ selectButton: {
1567
+ flex: 1,
1568
+ height: 40,
1569
+ alignItems: "center",
1570
+ justifyContent: "center"
1571
+ },
1572
+ iconButton: {
1573
+ width: 40,
1574
+ height: 40,
1575
+ alignItems: "center",
1576
+ justifyContent: "center",
1577
+ borderWidth: import_react_native4.StyleSheet.hairlineWidth
1578
+ }
1579
+ });
1580
+
1581
+ // catalog/native/AgentListContent.tsx
1582
+ var import_react_native9 = require("react-native");
1583
+
1584
+ // catalog/native/AgentFilterBar.tsx
1585
+ var import_react_native6 = require("react-native");
1586
+
1587
+ // catalog/native/primitives.tsx
1588
+ var import_react_native5 = require("react-native");
1589
+ var import_jsx_runtime6 = require("react/jsx-runtime");
1590
+ function SearchInput({
1591
+ value,
1592
+ onChange,
1593
+ placeholder,
1594
+ autoFocus = false
1595
+ }) {
1596
+ const theme = useAgentCatalogNativeTheme();
1597
+ const { errorSink } = useAgentCatalog();
1598
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1599
+ import_react_native5.View,
1600
+ {
1601
+ style: [
1602
+ styles2.searchWrap,
1603
+ {
1604
+ backgroundColor: theme.colors.surface,
1605
+ borderColor: theme.colors.border,
1606
+ borderRadius: theme.radius.md,
1607
+ paddingHorizontal: theme.spacing.sm
1608
+ }
1609
+ ],
1610
+ children: [
1611
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1612
+ AgentIcon,
1613
+ {
1614
+ name: "search",
1615
+ size: 14,
1616
+ color: theme.colors.textMuted,
1617
+ report: errorSink
1618
+ }
1619
+ ),
1620
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1621
+ import_react_native5.TextInput,
1622
+ {
1623
+ value,
1624
+ onChangeText: onChange,
1625
+ placeholder,
1626
+ placeholderTextColor: theme.colors.textFaint,
1627
+ autoFocus,
1628
+ autoCorrect: false,
1629
+ autoCapitalize: "none",
1630
+ returnKeyType: "search",
1631
+ accessibilityLabel: placeholder,
1632
+ style: [styles2.searchInput, { color: theme.colors.text }]
1633
+ }
1634
+ ),
1635
+ value.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1636
+ import_react_native5.Pressable,
1637
+ {
1638
+ onPress: () => onChange(""),
1639
+ accessibilityRole: "button",
1640
+ accessibilityLabel: "Clear search",
1641
+ hitSlop: 8,
1642
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1643
+ AgentIcon,
1644
+ {
1645
+ name: "x",
1646
+ size: 13,
1647
+ color: theme.colors.textMuted,
1648
+ report: errorSink
1649
+ }
1650
+ )
1651
+ }
1652
+ )
1653
+ ]
1654
+ }
1655
+ );
1656
+ }
1657
+ function FilterChip({
1658
+ icon,
1659
+ label,
1660
+ active,
1661
+ onPress
1662
+ }) {
1663
+ const theme = useAgentCatalogNativeTheme();
1664
+ const { errorSink } = useAgentCatalog();
1665
+ const tint = active ? theme.colors.primary : theme.colors.textMuted;
1666
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1667
+ import_react_native5.Pressable,
1668
+ {
1669
+ onPress,
1670
+ accessibilityRole: "button",
1671
+ accessibilityState: { selected: active },
1672
+ accessibilityLabel: label,
1673
+ style: ({ pressed }) => [
1674
+ styles2.chip,
1675
+ {
1676
+ borderRadius: theme.radius.sm,
1677
+ backgroundColor: active ? theme.colors.primarySoft : pressed ? theme.colors.surfacePressed : "transparent",
1678
+ borderColor: active ? theme.colors.primary : "transparent"
1679
+ }
1680
+ ],
1681
+ children: [
1682
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(AgentIcon, { name: icon, size: 12, color: tint, report: errorSink }),
1683
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native5.Text, { style: { color: tint, fontSize: theme.fontSize.sm, fontWeight: "500" }, children: label })
1684
+ ]
1685
+ }
1686
+ );
1687
+ }
1688
+ function OptionRow({
1689
+ label,
1690
+ selected,
1691
+ onPress
1692
+ }) {
1693
+ const theme = useAgentCatalogNativeTheme();
1694
+ const { errorSink } = useAgentCatalog();
1695
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1696
+ import_react_native5.Pressable,
1697
+ {
1698
+ onPress,
1699
+ accessibilityRole: "button",
1700
+ accessibilityState: { selected },
1701
+ style: ({ pressed }) => [
1702
+ styles2.optionRow,
1703
+ {
1704
+ paddingHorizontal: theme.spacing.md,
1705
+ backgroundColor: pressed ? theme.colors.surfacePressed : "transparent"
1706
+ }
1707
+ ],
1708
+ children: [
1709
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1710
+ import_react_native5.Text,
1711
+ {
1712
+ style: {
1713
+ flex: 1,
1714
+ color: selected ? theme.colors.primary : theme.colors.text,
1715
+ fontSize: theme.fontSize.md,
1716
+ fontWeight: selected ? "600" : "400"
1717
+ },
1718
+ children: label
1719
+ }
1720
+ ),
1721
+ selected && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1722
+ AgentIcon,
1723
+ {
1724
+ name: "check",
1725
+ size: 14,
1726
+ color: theme.colors.primary,
1727
+ report: errorSink
1728
+ }
1729
+ )
1730
+ ]
1731
+ }
1732
+ );
1733
+ }
1734
+ function CheckRow({
1735
+ label,
1736
+ checked,
1737
+ onPress
1738
+ }) {
1739
+ const theme = useAgentCatalogNativeTheme();
1740
+ const { errorSink } = useAgentCatalog();
1741
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1742
+ import_react_native5.Pressable,
1743
+ {
1744
+ onPress,
1745
+ accessibilityRole: "checkbox",
1746
+ accessibilityState: { checked },
1747
+ style: ({ pressed }) => [
1748
+ styles2.checkRow,
1749
+ {
1750
+ paddingHorizontal: theme.spacing.md,
1751
+ backgroundColor: pressed ? theme.colors.surfacePressed : "transparent"
1752
+ }
1753
+ ],
1754
+ children: [
1755
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1756
+ import_react_native5.View,
1757
+ {
1758
+ style: [
1759
+ styles2.checkBox,
1760
+ {
1761
+ borderRadius: theme.radius.sm,
1762
+ borderColor: checked ? theme.colors.primary : theme.colors.border,
1763
+ backgroundColor: checked ? theme.colors.primary : "transparent"
1764
+ }
1765
+ ],
1766
+ children: checked && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1767
+ AgentIcon,
1768
+ {
1769
+ name: "check",
1770
+ size: 10,
1771
+ color: theme.colors.primaryForeground,
1772
+ report: errorSink
1773
+ }
1774
+ )
1775
+ }
1776
+ ),
1777
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1778
+ import_react_native5.Text,
1779
+ {
1780
+ numberOfLines: 1,
1781
+ style: { flex: 1, color: theme.colors.text, fontSize: theme.fontSize.md },
1782
+ children: label
1783
+ }
1784
+ )
1785
+ ]
1786
+ }
1787
+ );
1788
+ }
1789
+ function SidePanelHeader({
1790
+ title,
1791
+ onClose
1792
+ }) {
1793
+ const theme = useAgentCatalogNativeTheme();
1794
+ const { errorSink } = useAgentCatalog();
1795
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1796
+ import_react_native5.View,
1797
+ {
1798
+ style: [
1799
+ styles2.panelHeader,
1800
+ {
1801
+ paddingHorizontal: theme.spacing.md,
1802
+ borderBottomColor: theme.colors.border
1803
+ }
1804
+ ],
1805
+ children: [
1806
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1807
+ import_react_native5.Text,
1808
+ {
1809
+ style: {
1810
+ color: theme.colors.text,
1811
+ fontSize: theme.fontSize.md,
1812
+ fontWeight: "600"
1813
+ },
1814
+ children: title
1815
+ }
1816
+ ),
1817
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1818
+ import_react_native5.Pressable,
1819
+ {
1820
+ onPress: onClose,
1821
+ accessibilityRole: "button",
1822
+ accessibilityLabel: "Close",
1823
+ hitSlop: 8,
1824
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1825
+ AgentIcon,
1826
+ {
1827
+ name: "x",
1828
+ size: 14,
1829
+ color: theme.colors.textMuted,
1830
+ report: errorSink
1831
+ }
1832
+ )
1833
+ }
1834
+ )
1835
+ ]
1836
+ }
1837
+ );
1838
+ }
1839
+ var styles2 = import_react_native5.StyleSheet.create({
1840
+ searchWrap: {
1841
+ flexDirection: "row",
1842
+ alignItems: "center",
1843
+ gap: 6,
1844
+ height: 36,
1845
+ borderWidth: import_react_native5.StyleSheet.hairlineWidth
1846
+ },
1847
+ searchInput: {
1848
+ flex: 1,
1849
+ minWidth: 0,
1850
+ padding: 0,
1851
+ fontSize: 15
1852
+ },
1853
+ chip: {
1854
+ flexDirection: "row",
1855
+ alignItems: "center",
1856
+ gap: 4,
1857
+ height: 28,
1858
+ paddingHorizontal: 8,
1859
+ borderWidth: import_react_native5.StyleSheet.hairlineWidth
1860
+ },
1861
+ optionRow: {
1862
+ flexDirection: "row",
1863
+ alignItems: "center",
1864
+ paddingVertical: 10
1865
+ },
1866
+ checkRow: {
1867
+ flexDirection: "row",
1868
+ alignItems: "center",
1869
+ gap: 8,
1870
+ paddingVertical: 8
1871
+ },
1872
+ checkBox: {
1873
+ width: 18,
1874
+ height: 18,
1875
+ alignItems: "center",
1876
+ justifyContent: "center",
1877
+ borderWidth: 1
1878
+ },
1879
+ panelHeader: {
1880
+ flexDirection: "row",
1881
+ alignItems: "center",
1882
+ justifyContent: "space-between",
1883
+ paddingVertical: 10,
1884
+ borderBottomWidth: import_react_native5.StyleSheet.hairlineWidth
1885
+ }
1886
+ });
1887
+
1888
+ // catalog/native/AgentFilterBar.tsx
1889
+ var import_jsx_runtime7 = require("react/jsx-runtime");
1890
+ function AgentFilterBar({
1891
+ consumer,
1892
+ allCategories,
1893
+ allTags,
1894
+ activeFilterCount,
1895
+ onFilterChipPress,
1896
+ onReset
1897
+ }) {
1898
+ const theme = useAgentCatalogNativeTheme();
1899
+ const { errorSink } = useAgentCatalog();
1900
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1901
+ import_react_native6.ScrollView,
1902
+ {
1903
+ horizontal: true,
1904
+ showsHorizontalScrollIndicator: false,
1905
+ contentContainerStyle: [
1906
+ styles3.bar,
1907
+ { paddingHorizontal: theme.spacing.sm }
1908
+ ],
1909
+ children: [
1910
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1911
+ FilterChip,
1912
+ {
1913
+ icon: "arrowUpDown",
1914
+ label: SORT_OPTIONS.find((o) => o.value === consumer.sortBy)?.label ?? "Sort",
1915
+ active: consumer.sortBy !== "updated-desc",
1916
+ onPress: () => onFilterChipPress("sort")
1917
+ }
1918
+ ),
1919
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1920
+ FilterChip,
1921
+ {
1922
+ icon: "star",
1923
+ label: consumer.favFilter === "no" ? "No Favs" : "Favs",
1924
+ active: consumer.favFilter !== "all",
1925
+ onPress: () => {
1926
+ const next = consumer.favFilter === "all" ? "yes" : consumer.favFilter === "yes" ? "no" : "all";
1927
+ consumer.setFavFilter(next);
1928
+ }
1929
+ }
1930
+ ),
1931
+ allCategories.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1932
+ FilterChip,
1933
+ {
1934
+ icon: "folder",
1935
+ label: consumer.includedCats.length > 0 ? `${consumer.includedCats.length}` : "Category",
1936
+ active: consumer.includedCats.length > 0,
1937
+ onPress: () => onFilterChipPress("categories")
1938
+ }
1939
+ ),
1940
+ allTags.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1941
+ FilterChip,
1942
+ {
1943
+ icon: "tag",
1944
+ label: consumer.includedTags.length > 0 ? `${consumer.includedTags.length}` : "Tags",
1945
+ active: consumer.includedTags.length > 0,
1946
+ onPress: () => onFilterChipPress("tags")
1947
+ }
1948
+ ),
1949
+ activeFilterCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1950
+ import_react_native6.Pressable,
1951
+ {
1952
+ onPress: onReset,
1953
+ accessibilityRole: "button",
1954
+ accessibilityLabel: "Reset filters",
1955
+ hitSlop: 8,
1956
+ style: ({ pressed }) => [
1957
+ styles3.reset,
1958
+ {
1959
+ borderRadius: theme.radius.sm,
1960
+ backgroundColor: pressed ? theme.colors.surfacePressed : "transparent"
1961
+ }
1962
+ ],
1963
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1964
+ AgentIcon,
1965
+ {
1966
+ name: "rotateCcw",
1967
+ size: 12,
1968
+ color: theme.colors.textMuted,
1969
+ report: errorSink
1970
+ }
1971
+ )
1972
+ }
1973
+ )
1974
+ ]
1975
+ }
1976
+ );
1977
+ }
1978
+ var styles3 = import_react_native6.StyleSheet.create({
1979
+ bar: { flexDirection: "row", alignItems: "center", gap: 4, paddingBottom: 6 },
1980
+ reset: {
1981
+ height: 28,
1982
+ paddingHorizontal: 8,
1983
+ alignItems: "center",
1984
+ justifyContent: "center"
1985
+ }
1986
+ });
1987
+
1988
+ // catalog/native/AgentListTabs.tsx
1989
+ var import_react_native7 = require("react-native");
1990
+ var import_jsx_runtime8 = require("react/jsx-runtime");
1991
+ function AgentListTabs({
1992
+ consumer,
1993
+ tabCounts,
1994
+ visibleTabs,
1995
+ systemTabLabel
1996
+ }) {
1997
+ const { labels } = useAgentCatalog();
1998
+ const theme = useAgentCatalogNativeTheme();
1999
+ const tabs = [
2000
+ { value: "mine", label: "Mine", countKey: "mine" },
2001
+ { value: "shared", label: "Shared", countKey: "shared" },
2002
+ { value: "all", label: "All", countKey: "all" },
2003
+ { value: "system", label: labels.publicTab, countKey: "system" }
2004
+ ];
2005
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2006
+ import_react_native7.ScrollView,
2007
+ {
2008
+ horizontal: true,
2009
+ showsHorizontalScrollIndicator: false,
2010
+ accessibilityRole: "tablist",
2011
+ accessibilityLabel: "Agent ownership",
2012
+ contentContainerStyle: [
2013
+ styles4.strip,
2014
+ { paddingHorizontal: theme.spacing.sm }
2015
+ ],
2016
+ children: tabs.filter(({ value }) => !visibleTabs || visibleTabs.includes(value)).map(({ value, label: baseLabel, countKey }) => {
2017
+ const label = value === "system" ? systemTabLabel ?? baseLabel : baseLabel;
2018
+ const active = consumer.tab === value;
2019
+ const count = tabCounts[countKey];
2020
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
2021
+ import_react_native7.Pressable,
2022
+ {
2023
+ onPress: () => consumer.setTab(value),
2024
+ accessibilityRole: "tab",
2025
+ accessibilityState: { selected: active },
2026
+ accessibilityLabel: `${label}, ${count}`,
2027
+ style: ({ pressed }) => [
2028
+ styles4.tab,
2029
+ {
2030
+ borderRadius: theme.radius.md,
2031
+ backgroundColor: active ? theme.colors.primary : pressed ? theme.colors.surfacePressed : "transparent"
2032
+ }
2033
+ ],
2034
+ children: [
2035
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2036
+ import_react_native7.Text,
2037
+ {
2038
+ style: {
2039
+ color: active ? theme.colors.primaryForeground : theme.colors.textMuted,
2040
+ fontSize: theme.fontSize.sm,
2041
+ fontWeight: "500"
2042
+ },
2043
+ children: label
2044
+ }
2045
+ ),
2046
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2047
+ import_react_native7.Text,
2048
+ {
2049
+ style: {
2050
+ color: active ? theme.colors.primaryForeground : theme.colors.textMuted,
2051
+ fontSize: theme.fontSize.sm,
2052
+ opacity: 0.8,
2053
+ fontVariant: ["tabular-nums"]
2054
+ },
2055
+ children: count
2056
+ }
2057
+ )
2058
+ ]
2059
+ },
2060
+ value
2061
+ );
2062
+ })
2063
+ }
2064
+ );
2065
+ }
2066
+ var styles4 = import_react_native7.StyleSheet.create({
2067
+ strip: { flexDirection: "row", alignItems: "center", gap: 4, paddingBottom: 6 },
2068
+ tab: {
2069
+ flexDirection: "row",
2070
+ alignItems: "center",
2071
+ gap: 4,
2072
+ paddingHorizontal: 10,
2073
+ paddingVertical: 6
2074
+ }
2075
+ });
2076
+
2077
+ // catalog/native/AgentRow.tsx
2078
+ var import_react_native8 = require("react-native");
2079
+ var import_jsx_runtime9 = require("react/jsx-runtime");
2080
+ function AgentRow({
2081
+ agent,
2082
+ isActive,
2083
+ onPress,
2084
+ onDetailPress
2085
+ }) {
2086
+ const { labels, errorSink } = useAgentCatalog();
2087
+ const theme = useAgentCatalogNativeTheme();
2088
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
2089
+ import_react_native8.View,
2090
+ {
2091
+ testID: `agent-row-${agent.id}`,
2092
+ style: [
2093
+ styles5.row,
2094
+ isActive ? { backgroundColor: theme.colors.primarySoft } : null
2095
+ ],
2096
+ children: [
2097
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
2098
+ import_react_native8.Pressable,
2099
+ {
2100
+ onPress,
2101
+ accessibilityRole: "button",
2102
+ accessibilityState: { selected: isActive },
2103
+ accessibilityLabel: agent.name || "Untitled",
2104
+ style: ({ pressed }) => [
2105
+ styles5.main,
2106
+ {
2107
+ paddingHorizontal: theme.spacing.md,
2108
+ backgroundColor: pressed ? theme.colors.surfacePressed : "transparent"
2109
+ }
2110
+ ],
2111
+ children: [
2112
+ agent.isFavorite && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2113
+ AgentIcon,
2114
+ {
2115
+ name: "star",
2116
+ size: 12,
2117
+ filled: true,
2118
+ color: theme.colors.favorite,
2119
+ report: errorSink
2120
+ }
2121
+ ),
2122
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2123
+ import_react_native8.Text,
2124
+ {
2125
+ numberOfLines: 1,
2126
+ style: {
2127
+ flexShrink: 1,
2128
+ color: isActive ? theme.colors.primary : theme.colors.text,
2129
+ fontSize: theme.fontSize.md,
2130
+ fontWeight: "500"
2131
+ },
2132
+ children: agent.name || "Untitled"
2133
+ }
2134
+ ),
2135
+ agent.orchestra && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
2136
+ import_react_native8.View,
2137
+ {
2138
+ accessibilityLabel: orchestraDelegatesLine(agent.orchestra) ?? orchestraLabel(agent.orchestra),
2139
+ style: [
2140
+ styles5.badge,
2141
+ {
2142
+ backgroundColor: theme.colors.primarySoft,
2143
+ borderRadius: theme.radius.sm
2144
+ }
2145
+ ],
2146
+ children: [
2147
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2148
+ AgentIcon,
2149
+ {
2150
+ name: "music4",
2151
+ size: 10,
2152
+ color: theme.colors.primary,
2153
+ report: errorSink
2154
+ }
2155
+ ),
2156
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2157
+ import_react_native8.Text,
2158
+ {
2159
+ style: { color: theme.colors.primary, fontSize: theme.fontSize.xs },
2160
+ children: agent.orchestra.memberCount
2161
+ }
2162
+ )
2163
+ ]
2164
+ }
2165
+ ),
2166
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native8.View, { style: styles5.spacer }),
2167
+ agent.agentType === "builtin" ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2168
+ import_react_native8.Text,
2169
+ {
2170
+ style: [
2171
+ styles5.originBadge,
2172
+ {
2173
+ color: theme.colors.primary,
2174
+ backgroundColor: theme.colors.primarySoft,
2175
+ borderRadius: theme.radius.sm,
2176
+ fontSize: theme.fontSize.xs
2177
+ }
2178
+ ],
2179
+ children: labels.systemBadge
2180
+ }
2181
+ ) : agent.isOwner === false ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2182
+ import_react_native8.Text,
2183
+ {
2184
+ style: [
2185
+ styles5.originBadge,
2186
+ {
2187
+ color: theme.colors.textMuted,
2188
+ backgroundColor: theme.colors.surface,
2189
+ borderRadius: theme.radius.sm,
2190
+ fontSize: theme.fontSize.xs
2191
+ }
2192
+ ],
2193
+ children: "shared"
2194
+ }
2195
+ ) : null
2196
+ ]
2197
+ }
2198
+ ),
2199
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2200
+ import_react_native8.Pressable,
2201
+ {
2202
+ onPress: onDetailPress,
2203
+ accessibilityRole: "button",
2204
+ accessibilityLabel: `Show details for ${agent.name || "Untitled"}`,
2205
+ hitSlop: 6,
2206
+ style: ({ pressed }) => [
2207
+ styles5.detailButton,
2208
+ {
2209
+ backgroundColor: pressed ? theme.colors.surfacePressed : "transparent"
2210
+ }
2211
+ ],
2212
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2213
+ AgentIcon,
2214
+ {
2215
+ name: "chevronRight",
2216
+ size: 16,
2217
+ color: theme.colors.textFaint,
2218
+ report: errorSink
2219
+ }
2220
+ )
2221
+ }
2222
+ )
2223
+ ]
2224
+ }
2225
+ );
2226
+ }
2227
+ var styles5 = import_react_native8.StyleSheet.create({
2228
+ row: { flexDirection: "row", alignItems: "stretch" },
2229
+ main: {
2230
+ flex: 1,
2231
+ flexDirection: "row",
2232
+ alignItems: "center",
2233
+ gap: 6,
2234
+ paddingVertical: 10,
2235
+ minWidth: 0
2236
+ },
2237
+ spacer: { flex: 1 },
2238
+ badge: {
2239
+ flexDirection: "row",
2240
+ alignItems: "center",
2241
+ gap: 2,
2242
+ paddingHorizontal: 4,
2243
+ paddingVertical: 1
2244
+ },
2245
+ originBadge: {
2246
+ overflow: "hidden",
2247
+ paddingHorizontal: 4,
2248
+ paddingVertical: 1,
2249
+ fontWeight: "500"
2250
+ },
2251
+ detailButton: {
2252
+ width: 40,
2253
+ alignItems: "center",
2254
+ justifyContent: "center"
2255
+ }
2256
+ });
2257
+
2258
+ // catalog/native/AgentListContent.tsx
2259
+ var import_jsx_runtime10 = require("react/jsx-runtime");
2260
+ function AgentListContent({
2261
+ agents,
2262
+ isLoading,
2263
+ consumer,
2264
+ activeAgentId,
2265
+ allCategories,
2266
+ allTags,
2267
+ onSelectAgent,
2268
+ onDetailPress,
2269
+ onFilterChipPress,
2270
+ onReset,
2271
+ activeFilterCount,
2272
+ tabCounts,
2273
+ visibleTabs,
2274
+ systemTabLabel,
2275
+ pinnedAgent = null,
2276
+ defaultRow = null,
2277
+ autoFocusSearch = false
2278
+ }) {
2279
+ const catalog = useAgentCatalog();
2280
+ const theme = useAgentCatalogNativeTheme();
2281
+ const { labels, errorSink } = catalog;
2282
+ const emptyLabel = agentListEmptyLabel(consumer.tab, labels);
2283
+ const defaultAgent = defaultRow?.row ?? null;
2284
+ const items = [];
2285
+ if (defaultAgent) {
2286
+ items.push({ key: "label-default", kind: "label", text: "Default" });
2287
+ items.push({
2288
+ key: `default-${defaultAgent.id}`,
2289
+ kind: "row",
2290
+ agent: defaultAgent,
2291
+ forceActive: defaultAgent.id === activeAgentId
2292
+ });
2293
+ items.push({ key: "divider-default", kind: "divider" });
2294
+ }
2295
+ if (pinnedAgent) {
2296
+ items.push({
2297
+ key: "label-pinned",
2298
+ kind: "label",
2299
+ text: labels.currentAgentHeading
2300
+ });
2301
+ items.push({
2302
+ key: `pinned-${pinnedAgent.id}`,
2303
+ kind: "row",
2304
+ agent: pinnedAgent,
2305
+ forceActive: true
2306
+ });
2307
+ items.push({ key: "divider-pinned", kind: "divider" });
2308
+ }
2309
+ for (const agent of agents) {
2310
+ items.push({
2311
+ key: agent.id,
2312
+ kind: "row",
2313
+ agent,
2314
+ forceActive: agent.id === activeAgentId
2315
+ });
2316
+ }
2317
+ const hairline = {
2318
+ height: import_react_native9.StyleSheet.hairlineWidth,
2319
+ backgroundColor: theme.colors.border
2320
+ };
2321
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native9.View, { style: [styles6.container, { backgroundColor: theme.colors.background }], children: [
2322
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native9.View, { style: { paddingHorizontal: theme.spacing.sm, paddingBottom: 6 }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2323
+ SearchInput,
2324
+ {
2325
+ value: consumer.searchTerm,
2326
+ onChange: consumer.setSearchTerm,
2327
+ placeholder: labels.searchPlaceholder,
2328
+ autoFocus: autoFocusSearch
2329
+ }
2330
+ ) }),
2331
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2332
+ AgentListTabs,
2333
+ {
2334
+ consumer,
2335
+ tabCounts,
2336
+ visibleTabs,
2337
+ systemTabLabel
2338
+ }
2339
+ ),
2340
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2341
+ AgentFilterBar,
2342
+ {
2343
+ consumer,
2344
+ allCategories,
2345
+ allTags,
2346
+ activeFilterCount,
2347
+ onFilterChipPress,
2348
+ onReset
2349
+ }
2350
+ ),
2351
+ defaultRow?.drift && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2352
+ import_react_native9.View,
2353
+ {
2354
+ accessibilityRole: "alert",
2355
+ style: [
2356
+ styles6.banner,
2357
+ {
2358
+ marginHorizontal: theme.spacing.sm,
2359
+ borderRadius: theme.radius.md,
2360
+ backgroundColor: theme.colors.driftBackground,
2361
+ borderColor: theme.colors.driftBorder
2362
+ }
2363
+ ],
2364
+ children: [
2365
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2366
+ AgentIcon,
2367
+ {
2368
+ name: "alertTriangle",
2369
+ size: 14,
2370
+ color: theme.colors.driftForeground,
2371
+ report: errorSink
2372
+ }
2373
+ ),
2374
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2375
+ import_react_native9.Text,
2376
+ {
2377
+ style: {
2378
+ flex: 1,
2379
+ color: theme.colors.driftForeground,
2380
+ fontSize: theme.fontSize.sm
2381
+ },
2382
+ children: defaultRow.drift
2383
+ }
2384
+ ),
2385
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2386
+ import_react_native9.Pressable,
2387
+ {
2388
+ onPress: () => catalog.dismissDefaultRowDrift(defaultRow.mandateKey),
2389
+ accessibilityRole: "button",
2390
+ accessibilityLabel: "Dismiss",
2391
+ hitSlop: 8,
2392
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2393
+ AgentIcon,
2394
+ {
2395
+ name: "x",
2396
+ size: 12,
2397
+ color: theme.colors.driftForeground,
2398
+ report: errorSink
2399
+ }
2400
+ )
2401
+ }
2402
+ )
2403
+ ]
2404
+ }
2405
+ ),
2406
+ defaultRow?.error && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2407
+ import_react_native9.View,
2408
+ {
2409
+ accessibilityRole: "alert",
2410
+ style: [
2411
+ styles6.banner,
2412
+ {
2413
+ marginHorizontal: theme.spacing.sm,
2414
+ borderRadius: theme.radius.md,
2415
+ backgroundColor: theme.colors.driftBackground,
2416
+ borderColor: theme.colors.driftBorder
2417
+ }
2418
+ ],
2419
+ children: [
2420
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2421
+ AgentIcon,
2422
+ {
2423
+ name: "alertTriangle",
2424
+ size: 14,
2425
+ color: theme.colors.driftForeground,
2426
+ report: errorSink
2427
+ }
2428
+ ),
2429
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2430
+ import_react_native9.Text,
2431
+ {
2432
+ style: {
2433
+ flex: 1,
2434
+ color: theme.colors.driftForeground,
2435
+ fontSize: theme.fontSize.sm
2436
+ },
2437
+ children: defaultRow.error
2438
+ }
2439
+ )
2440
+ ]
2441
+ }
2442
+ ),
2443
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native9.View, { style: hairline }),
2444
+ isLoading ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native9.View, { style: styles6.centered, children: [
2445
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2446
+ AgentIcon,
2447
+ {
2448
+ name: "loader",
2449
+ size: 16,
2450
+ color: theme.colors.textMuted,
2451
+ report: errorSink
2452
+ }
2453
+ ),
2454
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native9.Text, { style: { color: theme.colors.textMuted, fontSize: theme.fontSize.md }, children: labels.loading })
2455
+ ] }) : items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native9.View, { style: styles6.centered, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native9.Text, { style: { color: theme.colors.textMuted, fontSize: theme.fontSize.md }, children: emptyLabel }) }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2456
+ import_react_native9.FlatList,
2457
+ {
2458
+ style: styles6.list,
2459
+ data: items,
2460
+ keyExtractor: (item) => item.key,
2461
+ keyboardShouldPersistTaps: "handled",
2462
+ renderItem: ({ item }) => {
2463
+ if (item.kind === "divider") return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native9.View, { style: hairline });
2464
+ if (item.kind === "label") {
2465
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2466
+ import_react_native9.Text,
2467
+ {
2468
+ style: {
2469
+ color: theme.colors.textMuted,
2470
+ fontSize: theme.fontSize.xs,
2471
+ fontWeight: "600",
2472
+ textTransform: "uppercase",
2473
+ paddingHorizontal: theme.spacing.md,
2474
+ paddingTop: 8,
2475
+ paddingBottom: 2
2476
+ },
2477
+ children: item.text
2478
+ }
2479
+ );
2480
+ }
2481
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2482
+ AgentRow,
2483
+ {
2484
+ agent: item.agent,
2485
+ isActive: item.forceActive,
2486
+ onPress: () => onSelectAgent(item.agent),
2487
+ onDetailPress: () => onDetailPress(item.agent)
2488
+ }
2489
+ );
2490
+ },
2491
+ ListFooterComponent: agents.length === 0 && (pinnedAgent || defaultAgent) ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native9.View, { style: styles6.centered, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2492
+ import_react_native9.Text,
2493
+ {
2494
+ style: {
2495
+ color: theme.colors.textMuted,
2496
+ fontSize: theme.fontSize.md
2497
+ },
2498
+ children: emptyLabel
2499
+ }
2500
+ ) }) : null
2501
+ }
2502
+ ),
2503
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native9.View, { style: hairline }),
2504
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native9.View, { style: [styles6.footer, { paddingHorizontal: theme.spacing.md }], children: [
2505
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2506
+ import_react_native9.Text,
2507
+ {
2508
+ style: {
2509
+ color: theme.colors.textMuted,
2510
+ fontSize: theme.fontSize.xs,
2511
+ fontVariant: ["tabular-nums"]
2512
+ },
2513
+ children: [
2514
+ agents.length,
2515
+ " agent",
2516
+ agents.length !== 1 ? "s" : ""
2517
+ ]
2518
+ }
2519
+ ),
2520
+ consumer.searchTerm.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2521
+ import_react_native9.Pressable,
2522
+ {
2523
+ onPress: () => consumer.setSearchTerm(""),
2524
+ accessibilityRole: "button",
2525
+ accessibilityLabel: "Clear search",
2526
+ hitSlop: 8,
2527
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2528
+ import_react_native9.Text,
2529
+ {
2530
+ style: { color: theme.colors.textMuted, fontSize: theme.fontSize.xs },
2531
+ children: "Clear search"
2532
+ }
2533
+ )
2534
+ }
2535
+ )
2536
+ ] })
2537
+ ] });
2538
+ }
2539
+ var styles6 = import_react_native9.StyleSheet.create({
2540
+ container: { flex: 1, minHeight: 0 },
2541
+ list: { flex: 1, minHeight: 0 },
2542
+ banner: {
2543
+ flexDirection: "row",
2544
+ alignItems: "flex-start",
2545
+ gap: 8,
2546
+ marginBottom: 6,
2547
+ paddingHorizontal: 8,
2548
+ paddingVertical: 6,
2549
+ borderWidth: import_react_native9.StyleSheet.hairlineWidth
2550
+ },
2551
+ centered: {
2552
+ alignItems: "center",
2553
+ justifyContent: "center",
2554
+ gap: 8,
2555
+ paddingVertical: 32
2556
+ },
2557
+ footer: {
2558
+ flexDirection: "row",
2559
+ alignItems: "center",
2560
+ justifyContent: "space-between",
2561
+ paddingVertical: 8
2562
+ }
2563
+ });
2564
+
2565
+ // catalog/native/AgentSubView.tsx
2566
+ var import_react_native10 = require("react-native");
2567
+ var import_jsx_runtime11 = require("react/jsx-runtime");
2568
+ function AgentSubView({
2569
+ view,
2570
+ consumer,
2571
+ allCategories,
2572
+ allTags,
2573
+ search,
2574
+ setSearch,
2575
+ onBack
2576
+ }) {
2577
+ const theme = useAgentCatalogNativeTheme();
2578
+ const title = view === "sort" ? "Sort" : view === "categories" ? "Categories" : "Tags";
2579
+ const values = view === "categories" ? allCategories : allTags;
2580
+ const included = view === "categories" ? consumer.includedCats : consumer.includedTags;
2581
+ const filtered = values.filter(
2582
+ (value) => !search || value.toLowerCase().includes(search.toLowerCase())
2583
+ );
2584
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_react_native10.View, { style: styles7.container, children: [
2585
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SidePanelHeader, { title, onClose: onBack }),
2586
+ view === "sort" ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native10.ScrollView, { style: styles7.list, children: SORT_OPTIONS.map((option) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2587
+ OptionRow,
2588
+ {
2589
+ label: option.label,
2590
+ selected: consumer.sortBy === option.value,
2591
+ onPress: () => {
2592
+ consumer.setSortBy(option.value);
2593
+ onBack();
2594
+ }
2595
+ },
2596
+ option.value
2597
+ )) }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
2598
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native10.View, { style: { paddingHorizontal: theme.spacing.sm, paddingVertical: 6 }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2599
+ SearchInput,
2600
+ {
2601
+ value: search,
2602
+ onChange: setSearch,
2603
+ placeholder: view === "categories" ? "Filter categories..." : "Filter tags..."
2604
+ }
2605
+ ) }),
2606
+ included.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2607
+ import_react_native10.Pressable,
2608
+ {
2609
+ onPress: () => view === "categories" ? consumer.setIncludedCats([]) : consumer.setIncludedTags([]),
2610
+ accessibilityRole: "button",
2611
+ accessibilityLabel: `Clear ${included.length} filters`,
2612
+ style: {
2613
+ marginHorizontal: theme.spacing.sm,
2614
+ marginBottom: 4,
2615
+ paddingVertical: 6
2616
+ },
2617
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
2618
+ import_react_native10.Text,
2619
+ {
2620
+ style: {
2621
+ color: theme.colors.primary,
2622
+ fontSize: theme.fontSize.sm,
2623
+ fontWeight: "600"
2624
+ },
2625
+ children: [
2626
+ "Clear (",
2627
+ included.length,
2628
+ ")"
2629
+ ]
2630
+ }
2631
+ )
2632
+ }
2633
+ ),
2634
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native10.ScrollView, { style: styles7.list, children: filtered.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2635
+ import_react_native10.Text,
2636
+ {
2637
+ style: {
2638
+ color: theme.colors.textMuted,
2639
+ fontSize: theme.fontSize.md,
2640
+ textAlign: "center",
2641
+ paddingVertical: 24
2642
+ },
2643
+ children: view === "categories" ? "No categories" : "No tags"
2644
+ }
2645
+ ) : filtered.map((value) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2646
+ CheckRow,
2647
+ {
2648
+ label: value,
2649
+ checked: included.includes(value),
2650
+ onPress: () => view === "categories" ? consumer.toggleCategory(value) : consumer.toggleTag(value)
2651
+ },
2652
+ value
2653
+ )) })
2654
+ ] })
2655
+ ] });
2656
+ }
2657
+ var styles7 = import_react_native10.StyleSheet.create({
2658
+ container: { flex: 1, minHeight: 0 },
2659
+ list: { flex: 1, minHeight: 0 }
2660
+ });
2661
+
2662
+ // catalog/native/AgentPickerBody.tsx
2663
+ var import_jsx_runtime12 = require("react/jsx-runtime");
2664
+ function AgentPickerBody({
2665
+ consumerId,
2666
+ onSelect,
2667
+ activeAgentId = null,
2668
+ autoFocusSearch = false,
2669
+ initialTab,
2670
+ includeSystemInAll = false,
2671
+ visibleTabs,
2672
+ systemTabLabel,
2673
+ showPinnedAgent = true,
2674
+ excludeAgentIds,
2675
+ defaultMandateKey,
2676
+ compact = false,
2677
+ onAfterSelect
2678
+ }) {
2679
+ const [detailAgent, setDetailAgent] = (0, import_react6.useState)(null);
2680
+ const [subView, setSubView] = (0, import_react6.useState)(null);
2681
+ const [panelSearch, setPanelSearch] = (0, import_react6.useState)("");
2682
+ const {
2683
+ agents,
2684
+ isLoading,
2685
+ allCategories,
2686
+ allTags,
2687
+ consumer,
2688
+ tabCounts,
2689
+ activeFilterCount,
2690
+ pinnedAgent,
2691
+ defaultRow,
2692
+ ensureLoaded,
2693
+ handleSelectAgent: coreSelectAgent
2694
+ } = useAgentListCore({
2695
+ consumerId,
2696
+ onSelect,
2697
+ activeAgentIdOverride: activeAgentId,
2698
+ ...initialTab ? { initialTab } : {},
2699
+ includeSystemInAll,
2700
+ // The restriction has to reach the CORE, not just the tab strip.
2701
+ ...visibleTabs ? { visibleTabs } : {},
2702
+ ...excludeAgentIds ? { excludeAgentIds } : {},
2703
+ ...defaultMandateKey ? { defaultMandateKey } : {}
2704
+ });
2705
+ (0, import_react6.useEffect)(() => {
2706
+ ensureLoaded();
2707
+ }, [ensureLoaded]);
2708
+ const selectAgent = (agent) => {
2709
+ coreSelectAgent(agent);
2710
+ setDetailAgent(null);
2711
+ setSubView(null);
2712
+ onAfterSelect?.();
2713
+ };
2714
+ if (detailAgent) {
2715
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native11.View, { style: styles8.fill, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2716
+ AgentDetailCard,
2717
+ {
2718
+ agent: detailAgent,
2719
+ onSelect: () => selectAgent(detailAgent)
2720
+ }
2721
+ ) });
2722
+ }
2723
+ if (subView) {
2724
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native11.View, { style: styles8.fill, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2725
+ AgentSubView,
2726
+ {
2727
+ view: subView,
2728
+ consumer,
2729
+ allCategories,
2730
+ allTags,
2731
+ search: panelSearch,
2732
+ setSearch: setPanelSearch,
2733
+ onBack: () => {
2734
+ setSubView(null);
2735
+ setPanelSearch("");
2736
+ }
2737
+ }
2738
+ ) });
2739
+ }
2740
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native11.View, { style: [styles8.fill, compact ? styles8.compact : null], children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2741
+ AgentListContent,
2742
+ {
2743
+ agents,
2744
+ isLoading,
2745
+ consumer,
2746
+ activeAgentId,
2747
+ allCategories,
2748
+ allTags,
2749
+ onSelectAgent: selectAgent,
2750
+ onDetailPress: setDetailAgent,
2751
+ onFilterChipPress: setSubView,
2752
+ onReset: consumer.resetFilters,
2753
+ activeFilterCount,
2754
+ tabCounts,
2755
+ ...visibleTabs ? { visibleTabs } : {},
2756
+ ...systemTabLabel ?? (includeSystemInAll ? "System" : void 0) ? {
2757
+ systemTabLabel: systemTabLabel ?? (includeSystemInAll ? "System" : void 0)
2758
+ } : {},
2759
+ pinnedAgent: showPinnedAgent ? pinnedAgent : null,
2760
+ defaultRow,
2761
+ autoFocusSearch
2762
+ }
2763
+ ) });
2764
+ }
2765
+ var styles8 = import_react_native11.StyleSheet.create({
2766
+ fill: { flex: 1, minHeight: 0 },
2767
+ compact: { paddingTop: 0 }
2768
+ });
2769
+
2770
+ // catalog/native/AgentListSheet.tsx
2771
+ var import_jsx_runtime13 = require("react/jsx-runtime");
2772
+ function AgentListSheet({ title, ...props }) {
2773
+ const theme = useAgentCatalogNativeTheme();
2774
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_react_native12.View, { style: [styles9.sheet, { backgroundColor: theme.colors.background }], children: [
2775
+ title ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2776
+ import_react_native12.Text,
2777
+ {
2778
+ accessibilityRole: "header",
2779
+ style: {
2780
+ color: theme.colors.text,
2781
+ fontSize: theme.fontSize.lg + 3,
2782
+ fontWeight: "700",
2783
+ paddingHorizontal: theme.spacing.md,
2784
+ paddingTop: theme.spacing.sm,
2785
+ paddingBottom: theme.spacing.sm
2786
+ },
2787
+ children: title
2788
+ }
2789
+ ) : null,
2790
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(AgentPickerBody, { ...props })
2791
+ ] });
2792
+ }
2793
+ var styles9 = import_react_native12.StyleSheet.create({
2794
+ sheet: { flex: 1, minHeight: 0 }
2795
+ });
2796
+
2797
+ // catalog/native/AgentListInlinePicker.tsx
2798
+ var import_react_native13 = require("react-native");
2799
+ var import_jsx_runtime14 = require("react/jsx-runtime");
2800
+ function AgentListInlinePicker(props) {
2801
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native13.View, { style: styles10.fill, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(AgentPickerBody, { ...props }) });
2802
+ }
2803
+ var styles10 = import_react_native13.StyleSheet.create({
2804
+ fill: { flex: 1, minHeight: 0 }
2805
+ });
2806
+ //# sourceMappingURL=index.cjs.map