@ai-matrx/agents 0.6.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +205 -0
- package/README.md +65 -5
- package/dist/catalog/index.cjs +1344 -0
- package/dist/catalog/index.cjs.map +1 -0
- package/dist/catalog/index.d.cts +857 -0
- package/dist/catalog/index.d.ts +857 -0
- package/dist/catalog/index.js +1321 -0
- package/dist/catalog/index.js.map +1 -0
- package/dist/catalog/react/index.cjs +2337 -0
- package/dist/catalog/react/index.cjs.map +1 -0
- package/dist/catalog/react/index.d.cts +808 -0
- package/dist/catalog/react/index.d.ts +808 -0
- package/dist/catalog/react/index.js +2340 -0
- package/dist/catalog/react/index.js.map +1 -0
- package/dist/catalog/styles.css +117 -0
- package/package.json +25 -3
|
@@ -0,0 +1,808 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ComponentType, ReactNode, Ref } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* `@ai-matrx/agents/catalog` — the row shape and the per-consumer view state.
|
|
6
|
+
*
|
|
7
|
+
* `AgentSummary` is the 19-column row `agx_get_list_full()` returns, camelCased.
|
|
8
|
+
* It is deliberately NOT the editable agent record: dirty tracking, undo,
|
|
9
|
+
* messages, tools and `_fetchStatus` stay in whichever host owns the editor.
|
|
10
|
+
* A list row is a list row.
|
|
11
|
+
*
|
|
12
|
+
* The view-state types are a VERBATIM port of matrx-frontend
|
|
13
|
+
* `features/agents/redux/agent-consumers/slice.ts` — only the coupling seam
|
|
14
|
+
* inverts (Redux reducers become store actions in `./store`).
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* A branded agent id. Every id that reaches `onSelect` is one of these:
|
|
18
|
+
* either a `agent.definition` UUID, or the `mandate:<key>` reference a
|
|
19
|
+
* default row carries (byte-identical to the ref shape matrx-extend
|
|
20
|
+
* `src/lib/mandates.ts` and matrx-local `desktop/src/lib/mandates.ts`
|
|
21
|
+
* already hand back to their hosts).
|
|
22
|
+
*/
|
|
23
|
+
type AgentId = string & {
|
|
24
|
+
readonly __agentId: unique symbol;
|
|
25
|
+
};
|
|
26
|
+
/** `agent_type` verbatim. Only `builtin` changes how a row is grouped. */
|
|
27
|
+
type AgentCatalogAgentType = "user" | "builtin";
|
|
28
|
+
/**
|
|
29
|
+
* `access_level` verbatim from `agx_get_list_full`. Widened over the raw
|
|
30
|
+
* string because it is a DB-owned vocabulary: an unknown level renders as
|
|
31
|
+
* itself rather than being coerced into a wrong one.
|
|
32
|
+
*/
|
|
33
|
+
type AgentAccessLevel = "owner" | "admin" | "editor" | "viewer" | "system" | (string & {});
|
|
34
|
+
/**
|
|
35
|
+
* One `agx_get_list_full()` row, camelCased. Nineteen columns, no more:
|
|
36
|
+
* anything richer needs a different read and is a different type.
|
|
37
|
+
*/
|
|
38
|
+
interface AgentSummary {
|
|
39
|
+
id: AgentId;
|
|
40
|
+
name: string | null;
|
|
41
|
+
description: string | null;
|
|
42
|
+
category: string | null;
|
|
43
|
+
tags: string[];
|
|
44
|
+
agentType: AgentCatalogAgentType;
|
|
45
|
+
modelId: string | null;
|
|
46
|
+
isActive: boolean;
|
|
47
|
+
isArchived: boolean;
|
|
48
|
+
isFavorite: boolean;
|
|
49
|
+
createdBy: string | null;
|
|
50
|
+
organizationId: string | null;
|
|
51
|
+
taskId: string | null;
|
|
52
|
+
sourceAgentId: string | null;
|
|
53
|
+
createdAt: string | null;
|
|
54
|
+
updatedAt: string | null;
|
|
55
|
+
isOwner: boolean | null;
|
|
56
|
+
accessLevel: AgentAccessLevel | null;
|
|
57
|
+
sharedByEmail: string | null;
|
|
58
|
+
/**
|
|
59
|
+
* Set only on a mandate default row — the key it resolved through, so a
|
|
60
|
+
* host can tell "the default" from a stored agent without parsing the id.
|
|
61
|
+
*/
|
|
62
|
+
mandateKey?: string;
|
|
63
|
+
}
|
|
64
|
+
type AgentSortOption = "updated-desc" | "created-desc" | "name-asc" | "name-desc" | "category-asc";
|
|
65
|
+
/** Which ownership tab is active in the agent list. */
|
|
66
|
+
type AgentTab = "mine" | "shared" | "all" | "system";
|
|
67
|
+
/** Favorite filter. */
|
|
68
|
+
type AgentFavFilter = "all" | "yes" | "no";
|
|
69
|
+
/** Archive filter. */
|
|
70
|
+
type AgentArchFilter = "active" | "archived" | "both";
|
|
71
|
+
/**
|
|
72
|
+
* Access level filter.
|
|
73
|
+
* 'any' = no restriction (default).
|
|
74
|
+
* 'owned' = only agents the user owns (isOwner = true).
|
|
75
|
+
* 'shared' = only agents shared with the user (isOwner = false).
|
|
76
|
+
* 'editable' = owner + admin + editor.
|
|
77
|
+
*/
|
|
78
|
+
type AgentAccessFilter = "any" | "owned" | "shared" | "editable";
|
|
79
|
+
interface AgentConsumerState {
|
|
80
|
+
tab: AgentTab;
|
|
81
|
+
sortBy: AgentSortOption;
|
|
82
|
+
searchTerm: string;
|
|
83
|
+
/** INCLUSION model: empty = show all; non-empty = only matching. */
|
|
84
|
+
includedCats: string[];
|
|
85
|
+
/** INCLUSION model: empty = show all; non-empty = only matching. */
|
|
86
|
+
includedTags: string[];
|
|
87
|
+
favFilter: AgentFavFilter;
|
|
88
|
+
archFilter: AgentArchFilter;
|
|
89
|
+
accessFilter: AgentAccessFilter;
|
|
90
|
+
favoritesFirst: boolean;
|
|
91
|
+
/** Current page for owned-agent list items (after the card section). */
|
|
92
|
+
listPage: number;
|
|
93
|
+
/** Current page for shared-agent list items. */
|
|
94
|
+
sharedPage: number;
|
|
95
|
+
/**
|
|
96
|
+
* Ids returned by the last server-side search (`agx_search`), in server rank
|
|
97
|
+
* order. Additive: an agent in this list survives the search filter even
|
|
98
|
+
* when the local scorer gives it 0.
|
|
99
|
+
*
|
|
100
|
+
* That is load-bearing for tier 2. A deep search matches an agent's prompt
|
|
101
|
+
* content, which the client never loads — so the local scorer cannot see it.
|
|
102
|
+
* Without this list the server would return prompt matches and the UI would
|
|
103
|
+
* immediately filter them back out.
|
|
104
|
+
*
|
|
105
|
+
* Server-only matches sort BELOW every locally-scored match, in server rank
|
|
106
|
+
* order, so obvious matches always come first.
|
|
107
|
+
*/
|
|
108
|
+
serverMatchedIds: string[];
|
|
109
|
+
/** True while a server search is in flight — drives the search spinner. */
|
|
110
|
+
isServerSearching: boolean;
|
|
111
|
+
/** Tier 2: also search agent prompt content. Opt-in, per consumer. */
|
|
112
|
+
deepSearch: boolean;
|
|
113
|
+
}
|
|
114
|
+
/** The subset of consumer state a caller may patch (paging is derived). */
|
|
115
|
+
type AgentConsumerPatch = Partial<Omit<AgentConsumerState, "listPage" | "sharedPage">>;
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* catalog/default-row-types.ts — @ai-matrx/agents/catalog
|
|
119
|
+
*
|
|
120
|
+
* Split out of `default-row.ts` so `global-state.ts` can name the cached
|
|
121
|
+
* shape without importing the resolver (and its transport work) — the same
|
|
122
|
+
* split-out reflex C8 asks for, at module scale.
|
|
123
|
+
*/
|
|
124
|
+
|
|
125
|
+
/** A resolved default row, cached for first paint and compared for drift. */
|
|
126
|
+
interface ResolvedDefaultRow {
|
|
127
|
+
mandateKey: string;
|
|
128
|
+
/** The `agent.definition` id the mandate resolved to. */
|
|
129
|
+
holderId: string;
|
|
130
|
+
/** The holder's REAL name, read from the catalogue — never hardcoded. */
|
|
131
|
+
holderName: string;
|
|
132
|
+
holderDescription: string | null;
|
|
133
|
+
provenance: string;
|
|
134
|
+
/** Epoch ms of this resolution. */
|
|
135
|
+
at: number;
|
|
136
|
+
}
|
|
137
|
+
/** What the picker renders and what it screams, together. */
|
|
138
|
+
interface DefaultRowState {
|
|
139
|
+
mandateKey: string;
|
|
140
|
+
/** The row to render at the top of the list. `null` until resolved. */
|
|
141
|
+
row: AgentSummary | null;
|
|
142
|
+
/** The last live resolution, or the cached one before the live answer lands. */
|
|
143
|
+
resolved: ResolvedDefaultRow | null;
|
|
144
|
+
/** True while the resolution is in flight. */
|
|
145
|
+
loading: boolean;
|
|
146
|
+
/**
|
|
147
|
+
* 🚨 THE DRIFT SCREAM. Set when the cached first-paint row and the LIVE
|
|
148
|
+
* resolution disagree on holder id or holder name. Rendered as a persistent
|
|
149
|
+
* in-picker banner AND sent to the `notifier` port — never console-only.
|
|
150
|
+
*/
|
|
151
|
+
drift: string | null;
|
|
152
|
+
/** Set when the mandate could not be resolved at all. Loud, with a remedy. */
|
|
153
|
+
error: string | null;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* `@ai-matrx/agents/catalog` — THE PORTS.
|
|
158
|
+
*
|
|
159
|
+
* Two are required (`client`, `identity`); every other one ships a working
|
|
160
|
+
* default with a DOCUMENTED degradation, per THE ALL-INCLUSIVE LAW. A host
|
|
161
|
+
* injects identity and a Supabase client and nothing else; the picker's only
|
|
162
|
+
* contract back to the host is `onSelect(agentId)`.
|
|
163
|
+
*
|
|
164
|
+
* React appears nowhere in this file — it is import-inert and legal in any
|
|
165
|
+
* graph, server components included.
|
|
166
|
+
*/
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Every degraded path, every failed read, every drift detection reports here.
|
|
170
|
+
* DEFAULT: a tagged `console.error` that announces ONCE that no sink is bound
|
|
171
|
+
* and names the remedy.
|
|
172
|
+
*/
|
|
173
|
+
type AgentCatalogErrorSink = (event: {
|
|
174
|
+
code: string;
|
|
175
|
+
message: string;
|
|
176
|
+
context?: object;
|
|
177
|
+
}) => void;
|
|
178
|
+
/**
|
|
179
|
+
* The drift scream's second channel. DEFAULT: none — and that is safe
|
|
180
|
+
* ONLY because the in-picker persistent banner is the primary scream and
|
|
181
|
+
* always renders. A drift is never console-only.
|
|
182
|
+
*/
|
|
183
|
+
type AgentCatalogNotifier = (event: {
|
|
184
|
+
level: "warning" | "error";
|
|
185
|
+
title: string;
|
|
186
|
+
message: string;
|
|
187
|
+
}) => void;
|
|
188
|
+
/** Every user-visible string the picker renders, overridable per host. */
|
|
189
|
+
interface AgentCatalogLabels {
|
|
190
|
+
/** User-facing label for the `system` ownership tab. */
|
|
191
|
+
publicTab: string;
|
|
192
|
+
/**
|
|
193
|
+
* Badge label on a builtin row. Default `"system"` — the string
|
|
194
|
+
* `AgentRow` actually rendered in matrx-frontend. (The frontend also
|
|
195
|
+
* declared `AGENT_PUBLIC_BADGE_LABEL = "Public"` for this badge and NOTHING
|
|
196
|
+
* ever read it — a constant that named the badge without being the badge.
|
|
197
|
+
* Recorded in the CHANGELOG and dropped rather than ported.)
|
|
198
|
+
*/
|
|
199
|
+
systemBadge: string;
|
|
200
|
+
searchPlaceholder: string;
|
|
201
|
+
currentAgentHeading: string;
|
|
202
|
+
emptyDefault: string;
|
|
203
|
+
emptyShared: string;
|
|
204
|
+
emptySystem: string;
|
|
205
|
+
loading: string;
|
|
206
|
+
triggerFallback: string;
|
|
207
|
+
triggerResolving: string;
|
|
208
|
+
triggerUnnameable: string;
|
|
209
|
+
hoverHint: string;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Where a row's href goes when someone cmd-clicks it, and where `navigateTo`
|
|
213
|
+
* lands. DEFAULT: `window.location.assign` (so cmd-click and ordinary
|
|
214
|
+
* navigation both work with no host wiring at all).
|
|
215
|
+
*/
|
|
216
|
+
type AgentCatalogNavigate = (href: string) => void;
|
|
217
|
+
/**
|
|
218
|
+
* The sneak-peek affordance. Absent → the affordance is HIDDEN, never a dead
|
|
219
|
+
* button (nothing fails silently, and nothing looks alive when it is not).
|
|
220
|
+
*/
|
|
221
|
+
type AgentCatalogOpenPeek = (agent: AgentSummary) => void;
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* catalog/schema.ts — @ai-matrx/agents/catalog
|
|
225
|
+
*
|
|
226
|
+
* THE DEMANDED SCHEMA PROBE (the `@ai-matrx/associations` `assertDemandedSchema`
|
|
227
|
+
* precedent). It proves that the database a host pointed this catalog at can
|
|
228
|
+
* actually answer the three functions the picker demands.
|
|
229
|
+
*
|
|
230
|
+
* 🚨 IT MUST BE ABLE TO FAIL. A probe whose green result is unconditional
|
|
231
|
+
* proves nothing, so `selfTest: true` also probes a fabricated function name
|
|
232
|
+
* and REQUIRES it to come back missing. `catalog/__tests__/schema.test.ts`
|
|
233
|
+
* runs the whole probe against a client whose `rpc` answers PostgreSQL 42883
|
|
234
|
+
* (`undefined_function`, which PostgREST surfaces as PGRST202) and asserts the
|
|
235
|
+
* loud error.
|
|
236
|
+
*/
|
|
237
|
+
|
|
238
|
+
interface AgentCatalogSchemaReport {
|
|
239
|
+
ok: boolean;
|
|
240
|
+
/** Demanded functions the database cannot answer. */
|
|
241
|
+
missing: string[];
|
|
242
|
+
/** Functions the probe could not reach (transport/unknown failure). */
|
|
243
|
+
unreachable: {
|
|
244
|
+
fn: string;
|
|
245
|
+
error: unknown;
|
|
246
|
+
}[];
|
|
247
|
+
/** Functions that answered (success or any non-missing refusal). */
|
|
248
|
+
answered: string[];
|
|
249
|
+
/** True when `agent.definition.is_favorite` is writable by this caller. */
|
|
250
|
+
favoriteWritable: boolean | null;
|
|
251
|
+
}
|
|
252
|
+
interface AssertAgentCatalogSchemaOptions {
|
|
253
|
+
/**
|
|
254
|
+
* Also probe a fabricated function name and REQUIRE it to come back
|
|
255
|
+
* missing — proves this probe can fail.
|
|
256
|
+
*/
|
|
257
|
+
selfTest?: boolean;
|
|
258
|
+
/** Return the report instead of throwing. The self-test failure ALWAYS throws. */
|
|
259
|
+
throwOnViolation?: boolean;
|
|
260
|
+
/**
|
|
261
|
+
* Also probe the ONE write (`agent.definition.is_favorite`) against an
|
|
262
|
+
* impossible id, so a 42501/permission refusal is seen at boot rather than
|
|
263
|
+
* on a user's first click. Default: on.
|
|
264
|
+
*/
|
|
265
|
+
probeWrite?: boolean;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* catalog/store.ts — @ai-matrx/agents/catalog
|
|
270
|
+
*
|
|
271
|
+
* `createAgentCatalog(config)` — the headless kernel. Everything the picker
|
|
272
|
+
* knows lives here: the row registry, the complete-list read with its
|
|
273
|
+
* session-shared in-flight dedupe and freshness window, the tier-2 server
|
|
274
|
+
* search, the per-consumer view state, the ONE write, and the mandate default
|
|
275
|
+
* row with its drift screamer.
|
|
276
|
+
*
|
|
277
|
+
* The host injects a Supabase client and who the user is. Nothing else.
|
|
278
|
+
*
|
|
279
|
+
* The consumer reducers below are a VERBATIM port of matrx-frontend
|
|
280
|
+
* `features/agents/redux/agent-consumers/slice.ts`; only the seam inverts
|
|
281
|
+
* (a Redux reducer becomes a store method, and Immer's draft mutation becomes
|
|
282
|
+
* an explicit copy so the store can publish a new reference).
|
|
283
|
+
*/
|
|
284
|
+
|
|
285
|
+
type AgentCatalogStatus = "idle" | "loading" | "succeeded" | "failed";
|
|
286
|
+
interface AgentCatalogState {
|
|
287
|
+
/** Every row, one stable array reference per change (memoization depends on it). */
|
|
288
|
+
rows: AgentSummary[];
|
|
289
|
+
byId: Record<string, AgentSummary>;
|
|
290
|
+
status: AgentCatalogStatus;
|
|
291
|
+
error: string | null;
|
|
292
|
+
consumers: Record<string, AgentConsumerState>;
|
|
293
|
+
/** Keyed by mandate key. */
|
|
294
|
+
defaultRows: Record<string, DefaultRowState>;
|
|
295
|
+
}
|
|
296
|
+
interface AgentCatalog {
|
|
297
|
+
readonly catalogId: string;
|
|
298
|
+
readonly labels: AgentCatalogLabels;
|
|
299
|
+
readonly errorSink: AgentCatalogErrorSink;
|
|
300
|
+
readonly notifier: AgentCatalogNotifier | undefined;
|
|
301
|
+
/** True when this catalog was given a transport and can resolve mandates. */
|
|
302
|
+
readonly canResolveMandates: boolean;
|
|
303
|
+
getState(): AgentCatalogState;
|
|
304
|
+
subscribe(listener: () => void): () => void;
|
|
305
|
+
getAgent(agentId: string): AgentSummary | undefined;
|
|
306
|
+
/**
|
|
307
|
+
* The signed-in user id, or `null` when there is no session. The ONE place
|
|
308
|
+
* `identity.requireUserId()`'s throw is caught — a signed-out visitor
|
|
309
|
+
* legitimately lands on the public catalogue — and it is reported to the
|
|
310
|
+
* errorSink the first time so it is never silent.
|
|
311
|
+
*/
|
|
312
|
+
getUserIdOrNull(): string | null;
|
|
313
|
+
/** Load the catalogue if it is not fresh. Safe to call on every mount. */
|
|
314
|
+
ensureLoaded(options?: {
|
|
315
|
+
force?: boolean;
|
|
316
|
+
}): Promise<void>;
|
|
317
|
+
/** True when the last load is inside the 15-minute TTL. */
|
|
318
|
+
isFresh(): boolean;
|
|
319
|
+
/** True when the last load is older than 4 hours (tab-restore threshold). */
|
|
320
|
+
isStale(): boolean;
|
|
321
|
+
getConsumer(consumerId: string): AgentConsumerState;
|
|
322
|
+
registerConsumer(consumerId: string, initial?: AgentConsumerPatch): void;
|
|
323
|
+
unregisterConsumer(consumerId: string): void;
|
|
324
|
+
setConsumerFilter(consumerId: string, patch: AgentConsumerPatch): void;
|
|
325
|
+
setConsumerPage(consumerId: string, which: "list" | "shared", page: number): void;
|
|
326
|
+
setConsumerServerSearch(consumerId: string, args: {
|
|
327
|
+
matchedIds?: string[];
|
|
328
|
+
isSearching?: boolean;
|
|
329
|
+
}): void;
|
|
330
|
+
resetConsumerFilters(consumerId: string): void;
|
|
331
|
+
/** Tier-2 search. Purely additive; merges rows into the registry. */
|
|
332
|
+
searchServer(query: string, deep?: boolean): Promise<string[]>;
|
|
333
|
+
/** THE ONE WRITE. Optimistic, rolled back on failure, loud either way. */
|
|
334
|
+
setFavorite(agentId: string, isFavorite: boolean): Promise<void>;
|
|
335
|
+
/** Resolve (once) the default row for a mandate key. Idempotent. */
|
|
336
|
+
ensureDefaultRow(mandateKey: string): void;
|
|
337
|
+
getDefaultRow(mandateKey: string): DefaultRowState | undefined;
|
|
338
|
+
/** A person acknowledged the drift banner. The notifier already fired. */
|
|
339
|
+
dismissDefaultRowDrift(mandateKey: string): void;
|
|
340
|
+
assertSchema(options?: AssertAgentCatalogSchemaOptions): Promise<AgentCatalogSchemaReport>;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* The anchor a row renders for cmd/ctrl-click. DEFAULT: a plain `<a>` — which
|
|
345
|
+
* is a REAL, working link in every framework. A Next.js host passes
|
|
346
|
+
* `next/link`; a TanStack host passes its own `Link`.
|
|
347
|
+
*/
|
|
348
|
+
type AgentCatalogLinkComponent = ComponentType<{
|
|
349
|
+
href: string;
|
|
350
|
+
className?: string;
|
|
351
|
+
target?: string;
|
|
352
|
+
rel?: string;
|
|
353
|
+
title?: string;
|
|
354
|
+
"aria-label"?: string;
|
|
355
|
+
onClick?: (e: React.MouseEvent<HTMLAnchorElement>) => void;
|
|
356
|
+
children: ReactNode;
|
|
357
|
+
}>;
|
|
358
|
+
/** Render a model id as whatever door the host has. DEFAULT: plain text. */
|
|
359
|
+
type AgentCatalogRenderModelRef = (args: {
|
|
360
|
+
modelId: string;
|
|
361
|
+
className?: string;
|
|
362
|
+
}) => ReactNode;
|
|
363
|
+
interface AgentCatalogUiPorts {
|
|
364
|
+
/** DEFAULT: `window.location.assign`. */
|
|
365
|
+
navigate?: AgentCatalogNavigate;
|
|
366
|
+
/** DEFAULT: a plain `<a>`. */
|
|
367
|
+
LinkComponent?: AgentCatalogLinkComponent;
|
|
368
|
+
/** DEFAULT: the model id as plain text. */
|
|
369
|
+
renderModelRef?: AgentCatalogRenderModelRef;
|
|
370
|
+
/** ABSENT: the sneak-peek affordance is HIDDEN — never a dead button. */
|
|
371
|
+
openPeek?: AgentCatalogOpenPeek;
|
|
372
|
+
/**
|
|
373
|
+
* Portal container for the desktop popover, when the picker is mounted
|
|
374
|
+
* inside a dialog. DEFAULT: the document body (Radix's own default).
|
|
375
|
+
*/
|
|
376
|
+
popoverContainer?: HTMLElement | null;
|
|
377
|
+
}
|
|
378
|
+
interface AgentCatalogProviderProps extends AgentCatalogUiPorts {
|
|
379
|
+
catalog: AgentCatalog;
|
|
380
|
+
children: ReactNode;
|
|
381
|
+
}
|
|
382
|
+
declare function AgentCatalogProvider({ catalog, children, ...ports }: AgentCatalogProviderProps): react.JSX.Element;
|
|
383
|
+
/** The headless catalog this tree is bound to. Throws with no provider. */
|
|
384
|
+
declare function useAgentCatalog(): AgentCatalog;
|
|
385
|
+
/** The UI ports this tree is bound to, with every default already applied. */
|
|
386
|
+
declare function useAgentCatalogUiPorts(): Required<Pick<AgentCatalogUiPorts, "navigate" | "LinkComponent" | "renderModelRef">> & {
|
|
387
|
+
openPeek: AgentCatalogOpenPeek | undefined;
|
|
388
|
+
popoverContainer: HTMLElement | null | undefined;
|
|
389
|
+
};
|
|
390
|
+
/**
|
|
391
|
+
* Subscribe to a slice of catalog state. `useSyncExternalStore` because the
|
|
392
|
+
* catalog is an external store and React 18/19 concurrency must not tear it.
|
|
393
|
+
* `select` MUST return a stable reference for unchanged state — every
|
|
394
|
+
* selector in `../selectors` does.
|
|
395
|
+
*/
|
|
396
|
+
declare function useAgentCatalogState<T>(select: (state: AgentCatalogState) => T): T;
|
|
397
|
+
/** Every row currently in the catalogue, as one stable array. */
|
|
398
|
+
declare function useAgentCatalogRows(): AgentSummary[];
|
|
399
|
+
|
|
400
|
+
interface UseAgentConsumerReturn {
|
|
401
|
+
tab: AgentTab;
|
|
402
|
+
sortBy: AgentSortOption;
|
|
403
|
+
searchTerm: string;
|
|
404
|
+
includedCats: string[];
|
|
405
|
+
includedTags: string[];
|
|
406
|
+
favFilter: AgentFavFilter;
|
|
407
|
+
archFilter: AgentArchFilter;
|
|
408
|
+
accessFilter: AgentAccessFilter;
|
|
409
|
+
favoritesFirst: boolean;
|
|
410
|
+
listPage: number;
|
|
411
|
+
sharedPage: number;
|
|
412
|
+
/** The whole slot, for the selectors that take a consumer state. */
|
|
413
|
+
state: AgentConsumerState;
|
|
414
|
+
/** True if any filter differs from its default value. */
|
|
415
|
+
hasActiveFilters: boolean;
|
|
416
|
+
/** Tier 2 search — also match against agent prompt content. */
|
|
417
|
+
deepSearch: boolean;
|
|
418
|
+
/** True while a server-side search is in flight. */
|
|
419
|
+
isServerSearching: boolean;
|
|
420
|
+
setSearchTerm: (value: string) => void;
|
|
421
|
+
setDeepSearch: (value: boolean) => void;
|
|
422
|
+
setSortBy: (value: AgentSortOption) => void;
|
|
423
|
+
setTab: (value: AgentTab) => void;
|
|
424
|
+
setFavFilter: (value: AgentFavFilter) => void;
|
|
425
|
+
setArchFilter: (value: AgentArchFilter) => void;
|
|
426
|
+
setAccessFilter: (value: AgentAccessFilter) => void;
|
|
427
|
+
/** Add category to inclusion set; if already present, remove (toggle). */
|
|
428
|
+
toggleCategory: (cat: string) => void;
|
|
429
|
+
/** Add tag to inclusion set; if already present, remove (toggle). */
|
|
430
|
+
toggleTag: (tag: string) => void;
|
|
431
|
+
/**
|
|
432
|
+
* Replace the WHOLE category inclusion set in one write.
|
|
433
|
+
*
|
|
434
|
+
* Prefer this over looping `toggleCategory` whenever more than one value
|
|
435
|
+
* changes. Each `toggleCategory` call computes its next array from the
|
|
436
|
+
* `includedCats` captured in the CURRENT render, so two toggles fired in the
|
|
437
|
+
* same tick both start from the same snapshot and the second one's patch
|
|
438
|
+
* overwrites the first — a "Clear filter" click with three categories active
|
|
439
|
+
* removes only one. One write of the final set cannot drift that way.
|
|
440
|
+
*/
|
|
441
|
+
setIncludedCats: (next: string[]) => void;
|
|
442
|
+
/** Replace the WHOLE tag inclusion set in one write. See setIncludedCats. */
|
|
443
|
+
setIncludedTags: (next: string[]) => void;
|
|
444
|
+
toggleFavoritesFirst: () => void;
|
|
445
|
+
loadMoreList: () => void;
|
|
446
|
+
loadMoreShared: () => void;
|
|
447
|
+
resetFilters: () => void;
|
|
448
|
+
}
|
|
449
|
+
declare function useAgentConsumer(consumerId: string, options?: {
|
|
450
|
+
/** Delete the slot on unmount. Default false — persistent consumers keep state. */
|
|
451
|
+
unregisterOnUnmount?: boolean;
|
|
452
|
+
/** Applied only when the consumer is first registered (idempotent). */
|
|
453
|
+
initialTab?: AgentTab;
|
|
454
|
+
}): UseAgentConsumerReturn;
|
|
455
|
+
|
|
456
|
+
interface AgentListTabCounts {
|
|
457
|
+
mine: number;
|
|
458
|
+
shared: number;
|
|
459
|
+
all: number;
|
|
460
|
+
system: number;
|
|
461
|
+
}
|
|
462
|
+
interface AgentListTabsProps {
|
|
463
|
+
consumer: UseAgentConsumerReturn;
|
|
464
|
+
tabCounts: AgentListTabCounts;
|
|
465
|
+
/** Limit the ownership tabs for constrained pickers. */
|
|
466
|
+
visibleTabs?: readonly AgentTab[] | undefined;
|
|
467
|
+
/**
|
|
468
|
+
* Label for the builtin-agent tab. Users see "Public" (that is what a
|
|
469
|
+
* platform agent is to them); ADMIN surfaces pass "System", because there
|
|
470
|
+
* these are the agents they own and maintain.
|
|
471
|
+
*/
|
|
472
|
+
systemTabLabel?: string | undefined;
|
|
473
|
+
}
|
|
474
|
+
declare function AgentListTabs({ consumer, tabCounts, systemTabLabel, visibleTabs, }: AgentListTabsProps): react.JSX.Element;
|
|
475
|
+
|
|
476
|
+
interface AgentListCoreOptions {
|
|
477
|
+
consumerId: string;
|
|
478
|
+
onSelect?: (agentId: string) => void;
|
|
479
|
+
navigateTo?: string;
|
|
480
|
+
/** Route-scoped agent id (chat/builder headers). `undefined` = nothing pinned. */
|
|
481
|
+
activeAgentIdOverride?: string | null;
|
|
482
|
+
/**
|
|
483
|
+
* Tab this surface opens on, applied once on first mount. Admin surfaces
|
|
484
|
+
* that manage system agents pass `"system"`. When omitted the normal
|
|
485
|
+
* user heuristic applies (a user with no agents of their own lands on the
|
|
486
|
+
* public/system catalogue).
|
|
487
|
+
*/
|
|
488
|
+
initialTab?: AgentTab;
|
|
489
|
+
/**
|
|
490
|
+
* ADMIN reading of the "All" tab: blend system agents into it instead of
|
|
491
|
+
* keeping them to their own tab. See `makeSelectFilteredAgents`.
|
|
492
|
+
*/
|
|
493
|
+
includeSystemInAll?: boolean;
|
|
494
|
+
/**
|
|
495
|
+
* 🚨 THE OWNERSHIP TABS THIS CALL SITE MAY REACH — a HARD restriction, not a
|
|
496
|
+
* default.
|
|
497
|
+
*
|
|
498
|
+
* `AgentListTabs` already hides the buttons this list omits, but hiding a
|
|
499
|
+
* button never emptied the list behind it: the active tab lives in the
|
|
500
|
+
* consumer's REMEMBERED state, and `initialTab` is applied exactly once per
|
|
501
|
+
* mount (`defaultTabAppliedRef`). So a person who had been on "Mine" and
|
|
502
|
+
* then moved a control that narrows the picker got the personal catalogue
|
|
503
|
+
* with the tab bar removed — the forbidden list, and no way to see that it
|
|
504
|
+
* was forbidden. That is the defect Arman named on the mandate binding
|
|
505
|
+
* screen's global rung (VISION-RECONCILIATION D2, 2026-08-31: the picker
|
|
506
|
+
* opened on "Mine · 40").
|
|
507
|
+
*
|
|
508
|
+
* Given here, the tab is COERCED into the allowed set on every change of it,
|
|
509
|
+
* not just at mount — so a restriction that arrives later is enforced later.
|
|
510
|
+
*/
|
|
511
|
+
visibleTabs?: readonly AgentTab[];
|
|
512
|
+
/** Hide records that are invalid for this call site. */
|
|
513
|
+
excludeAgentIds?: readonly string[];
|
|
514
|
+
/**
|
|
515
|
+
* Show the platform DEFAULT agent for this mandate key at the top of the
|
|
516
|
+
* list, resolved live through the server (never a hardcoded name). Requires
|
|
517
|
+
* the catalog to have been built with a `transport`.
|
|
518
|
+
*/
|
|
519
|
+
defaultMandateKey?: string;
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* How long the hover-preview detail panel stays open after the cursor leaves
|
|
523
|
+
* an agent row (or the panel itself) before it closes. Generous on purpose:
|
|
524
|
+
* the panel renders to the side of the list, so the user needs ample time to
|
|
525
|
+
* travel the cursor across the gap to reach it without it vanishing. Paired
|
|
526
|
+
* with a reserved, non-resizing popover width so the target never moves.
|
|
527
|
+
*/
|
|
528
|
+
declare const HOVER_GRACE_MS = 900;
|
|
529
|
+
/**
|
|
530
|
+
* THE RULE, ALONE AND TESTABLE: which tab a restricted picker must land on.
|
|
531
|
+
*
|
|
532
|
+
* Returns `null` when the current tab is already allowed (nothing to do), and
|
|
533
|
+
* otherwise the tab to switch to — `initialTab` when that is itself allowed,
|
|
534
|
+
* else the first allowed tab.
|
|
535
|
+
*/
|
|
536
|
+
declare function coerceVisibleTab(current: AgentTab, allowed: readonly AgentTab[], initialTab?: AgentTab): AgentTab | null;
|
|
537
|
+
declare function useAgentListCore({ consumerId, onSelect, navigateTo, activeAgentIdOverride, initialTab, includeSystemInAll, visibleTabs, excludeAgentIds, defaultMandateKey, }: AgentListCoreOptions): {
|
|
538
|
+
agents: AgentSummary[];
|
|
539
|
+
isLoading: boolean;
|
|
540
|
+
activeAgentId: string | null;
|
|
541
|
+
pinnedAgent: AgentSummary | null;
|
|
542
|
+
defaultRow: DefaultRowState | null;
|
|
543
|
+
allCategories: string[];
|
|
544
|
+
allTags: string[];
|
|
545
|
+
consumer: UseAgentConsumerReturn;
|
|
546
|
+
tabCounts: AgentListTabCounts;
|
|
547
|
+
activeFilterCount: number;
|
|
548
|
+
hoveredAgent: AgentSummary | null;
|
|
549
|
+
setHoveredAgent: react.Dispatch<react.SetStateAction<AgentSummary | null>>;
|
|
550
|
+
ensureLoaded: () => void;
|
|
551
|
+
handleSelectAgent: (agent: AgentSummary) => void;
|
|
552
|
+
handleAgentHover: (agent: AgentSummary, panelOpen: boolean) => void;
|
|
553
|
+
handleAgentHoverEnd: (agent: AgentSummary, onClear: () => void) => void;
|
|
554
|
+
handleDetailPanelMouseEnter: () => void;
|
|
555
|
+
handleDetailPanelMouseLeave: (onClear: () => void) => void;
|
|
556
|
+
};
|
|
557
|
+
|
|
558
|
+
interface AgentListDropdownProps {
|
|
559
|
+
onSelect?: (agentId: string) => void;
|
|
560
|
+
navigateTo?: string;
|
|
561
|
+
className?: string;
|
|
562
|
+
label?: string;
|
|
563
|
+
/** Custom trigger element — replaces the default text button. */
|
|
564
|
+
triggerSlot?: React.ReactNode;
|
|
565
|
+
/** Remove the border from the default trigger button. */
|
|
566
|
+
noBorder?: boolean;
|
|
567
|
+
/** Use a compact (h-5) trigger instead of the default h-7. */
|
|
568
|
+
compact?: boolean;
|
|
569
|
+
/** Route-scoped agent id — highlights + pins the current agent in the list. */
|
|
570
|
+
activeAgentId?: string | null;
|
|
571
|
+
/**
|
|
572
|
+
* Which side the desktop popover opens toward. Defaults to Radix's "bottom".
|
|
573
|
+
* Pass "right" when the trigger lives in a narrow vertical rail so the panel
|
|
574
|
+
* opens beside the rail instead of covering it. Ignored on mobile (Drawer).
|
|
575
|
+
*/
|
|
576
|
+
contentSide?: "top" | "right" | "bottom" | "left";
|
|
577
|
+
/**
|
|
578
|
+
* Isolate this dropdown's filter/tab state under its own consumer id.
|
|
579
|
+
* Defaults to the shared `agent-list-dropdown` consumer so ordinary chat
|
|
580
|
+
* triggers keep one remembered set of filters across the app.
|
|
581
|
+
*/
|
|
582
|
+
consumerId?: string;
|
|
583
|
+
/** Tab to open on. Admin surfaces managing system agents pass `"system"`. */
|
|
584
|
+
initialTab?: AgentTab;
|
|
585
|
+
/** ADMIN variant: blend system agents into the "All" tab. */
|
|
586
|
+
includeSystemInAll?: boolean;
|
|
587
|
+
/** Restrict which ownership tabs are available for domain-constrained pickers. */
|
|
588
|
+
visibleTabs?: readonly AgentTab[];
|
|
589
|
+
/** Label override for the builtin-agent tab. Admin surfaces use "System". */
|
|
590
|
+
systemTabLabel?: string;
|
|
591
|
+
/** Resolve the route used by each named agent door. */
|
|
592
|
+
resolveAgentHref?: (agent: AgentSummary) => string;
|
|
593
|
+
/** Show the active agent above the filtered list. Default true. */
|
|
594
|
+
showPinnedAgent?: boolean;
|
|
595
|
+
/** Hide records that are invalid for this call site. */
|
|
596
|
+
excludeAgentIds?: readonly string[];
|
|
597
|
+
/**
|
|
598
|
+
* Offer the platform DEFAULT agent for this mandate key at the top of the
|
|
599
|
+
* list, named LIVE from the mandate's real Holder. `onSelect` receives
|
|
600
|
+
* `mandate:<key>` for that row — the ref shape every client already speaks.
|
|
601
|
+
*/
|
|
602
|
+
defaultMandateKey?: string;
|
|
603
|
+
}
|
|
604
|
+
declare function AgentListDropdown({ onSelect, navigateTo, className, label, triggerSlot, noBorder, compact, activeAgentId: activeAgentIdProp, contentSide, consumerId, initialTab, includeSystemInAll, visibleTabs, systemTabLabel, resolveAgentHref: resolveAgentHrefProp, showPinnedAgent, excludeAgentIds, defaultMandateKey, }: AgentListDropdownProps): react.JSX.Element;
|
|
605
|
+
|
|
606
|
+
interface AgentListInlinePickerProps {
|
|
607
|
+
/** Unique consumer id for filter/tab state (see `useAgentConsumer`). */
|
|
608
|
+
consumerId: string;
|
|
609
|
+
onSelect: (agentId: string) => void;
|
|
610
|
+
activeAgentId?: string | null;
|
|
611
|
+
className?: string;
|
|
612
|
+
/** Auto-focus the search field on mount. Default true. */
|
|
613
|
+
autoFocusSearch?: boolean;
|
|
614
|
+
/** Tab to open on. Admin surfaces that manage system agents pass `"system"`. */
|
|
615
|
+
initialTab?: AgentTab;
|
|
616
|
+
/** ADMIN variant: blend system agents into the "All" tab. */
|
|
617
|
+
includeSystemInAll?: boolean;
|
|
618
|
+
/** Restrict which ownership tabs are available for domain-constrained pickers. */
|
|
619
|
+
visibleTabs?: readonly AgentTab[];
|
|
620
|
+
/** Label override for the builtin-agent tab. Admin surfaces use "System". */
|
|
621
|
+
systemTabLabel?: string;
|
|
622
|
+
/** Resolve the route used by each named agent door. */
|
|
623
|
+
resolveAgentHref?: (agent: AgentSummary) => string;
|
|
624
|
+
/** Show the globally active agent above the filtered list. Default true. */
|
|
625
|
+
showPinnedAgent?: boolean;
|
|
626
|
+
/** Hide records that are invalid for this call site. */
|
|
627
|
+
excludeAgentIds?: readonly string[];
|
|
628
|
+
/** Offer the mandate's live-resolved default agent at the top of the list. */
|
|
629
|
+
defaultMandateKey?: string;
|
|
630
|
+
}
|
|
631
|
+
declare function AgentListInlinePicker({ consumerId, onSelect, activeAgentId, className, autoFocusSearch, initialTab, includeSystemInAll, visibleTabs, systemTabLabel, resolveAgentHref, showPinnedAgent, excludeAgentIds, defaultMandateKey, }: AgentListInlinePickerProps): react.JSX.Element;
|
|
632
|
+
|
|
633
|
+
/**
|
|
634
|
+
* catalog/react/types.ts — VERBATIM port of matrx-frontend
|
|
635
|
+
* `features/agents/components/agent-listings/core/types.ts`.
|
|
636
|
+
*/
|
|
637
|
+
|
|
638
|
+
type RightPanel = "detail" | "sort" | "categories" | "tags" | null;
|
|
639
|
+
declare const SORT_OPTIONS: {
|
|
640
|
+
value: AgentSortOption;
|
|
641
|
+
label: string;
|
|
642
|
+
}[];
|
|
643
|
+
declare const PANEL_HEIGHT = "528px";
|
|
644
|
+
/**
|
|
645
|
+
* 🚨 THE PANEL NEVER OUTGROWS THE SPACE IT HAS.
|
|
646
|
+
*
|
|
647
|
+
* The popover reserves a FIXED footprint on purpose (a resizing panel in a
|
|
648
|
+
* narrow rail gets collision-shifted out from under the cursor). But a flat
|
|
649
|
+
* 528px is taller than the room above a trigger sitting mid-page on a laptop,
|
|
650
|
+
* and Radix cannot shift what does not fit either way — so the top of the
|
|
651
|
+
* panel, which is the SEARCH BOX, was rendered off-screen. Measured 2026-09-08
|
|
652
|
+
* on the mandate Holder screen at 1280x900: the popover sat at `top: -76`.
|
|
653
|
+
*
|
|
654
|
+
* Clamping to Radix's own measurement keeps the footprint fixed whenever there
|
|
655
|
+
* IS room and merely shortens the list when there is not — the panel still
|
|
656
|
+
* never resizes while open, because the available height does not change while
|
|
657
|
+
* the popover is open.
|
|
658
|
+
*/
|
|
659
|
+
declare const LIST_MAX_HEIGHT = "min(528px, var(--radix-popper-available-height, 528px))";
|
|
660
|
+
|
|
661
|
+
interface AgentListContentProps {
|
|
662
|
+
agents: AgentSummary[];
|
|
663
|
+
isLoading: boolean;
|
|
664
|
+
consumer: UseAgentConsumerReturn;
|
|
665
|
+
activeAgentId: string | null;
|
|
666
|
+
allCategories: string[];
|
|
667
|
+
allTags: string[];
|
|
668
|
+
inputRef: React.RefObject<HTMLInputElement | null>;
|
|
669
|
+
onSelectAgent: (a: AgentSummary) => void;
|
|
670
|
+
/** Per-row href for cmd/ctrl+click. Defaults to `/agents/go/[id]`. */
|
|
671
|
+
resolveAgentHref?: ((agent: AgentSummary) => string) | undefined;
|
|
672
|
+
onReset: () => void;
|
|
673
|
+
activeFilterCount: number;
|
|
674
|
+
isMobile: boolean;
|
|
675
|
+
hoveredAgent: AgentSummary | null;
|
|
676
|
+
onAgentHover: (a: AgentSummary) => void;
|
|
677
|
+
onAgentHoverEnd: (a: AgentSummary) => void;
|
|
678
|
+
onDetailPress: (a: AgentSummary) => void;
|
|
679
|
+
onFilterChipClick: (panel: "sort" | "categories" | "tags") => void;
|
|
680
|
+
rightPanel: RightPanel;
|
|
681
|
+
tabCounts: AgentListTabCounts;
|
|
682
|
+
/** Limit the ownership tabs shown by this picker. */
|
|
683
|
+
visibleTabs?: readonly AgentTab[] | undefined;
|
|
684
|
+
/** Label override for the builtin tab — admin surfaces pass "System". */
|
|
685
|
+
systemTabLabel?: string | undefined;
|
|
686
|
+
/** Resolved current agent — pinned at the top when the list opens. */
|
|
687
|
+
pinnedAgent?: AgentSummary | null | undefined;
|
|
688
|
+
/** The mandate default row, when this picker was given a `defaultMandateKey`. */
|
|
689
|
+
defaultRow?: DefaultRowState | null | undefined;
|
|
690
|
+
/** When true, scroll the list to the pinned row (top). */
|
|
691
|
+
listOpen?: boolean | undefined;
|
|
692
|
+
}
|
|
693
|
+
declare function AgentListContent({ agents, isLoading, consumer, activeAgentId, allCategories, allTags, inputRef, onSelectAgent, resolveAgentHref, onReset, activeFilterCount, isMobile, hoveredAgent, onAgentHover, onAgentHoverEnd, onDetailPress, onFilterChipClick, rightPanel, tabCounts, visibleTabs, systemTabLabel, pinnedAgent, defaultRow, listOpen, }: AgentListContentProps): react.JSX.Element;
|
|
694
|
+
|
|
695
|
+
interface AgentFilterBarProps {
|
|
696
|
+
consumer: UseAgentConsumerReturn;
|
|
697
|
+
allCategories: string[];
|
|
698
|
+
allTags: string[];
|
|
699
|
+
activeFilterCount: number;
|
|
700
|
+
isMobile: boolean;
|
|
701
|
+
rightPanel: RightPanel;
|
|
702
|
+
onFilterChipClick: (panel: "sort" | "categories" | "tags") => void;
|
|
703
|
+
onReset: () => void;
|
|
704
|
+
}
|
|
705
|
+
/**
|
|
706
|
+
* The filter bar is IDENTICAL on every tab, system included. A tab that offers
|
|
707
|
+
* fewer controls than its neighbour is the half-built shape this list exists
|
|
708
|
+
* to prevent — the system tab's category/tag options simply come from the
|
|
709
|
+
* builtin population (see `selectAllSystemAgentCategories`).
|
|
710
|
+
*/
|
|
711
|
+
declare function AgentFilterBar({ consumer, allCategories, allTags, activeFilterCount, isMobile, rightPanel, onFilterChipClick, onReset, }: AgentFilterBarProps): react.JSX.Element;
|
|
712
|
+
|
|
713
|
+
interface AgentRowProps {
|
|
714
|
+
agent: AgentSummary;
|
|
715
|
+
isActive: boolean;
|
|
716
|
+
isHovered: boolean;
|
|
717
|
+
isMobile: boolean;
|
|
718
|
+
/** Row href. Defaults to `/agents/go/[id]`. */
|
|
719
|
+
href?: string | undefined;
|
|
720
|
+
onClick: () => void;
|
|
721
|
+
onHover: () => void;
|
|
722
|
+
onHoverEnd: () => void;
|
|
723
|
+
onDetailPress: () => void;
|
|
724
|
+
}
|
|
725
|
+
declare function AgentRow({ agent, isActive, isHovered, isMobile, href, onClick, onHover, onHoverEnd, onDetailPress, }: AgentRowProps): react.JSX.Element;
|
|
726
|
+
|
|
727
|
+
interface AgentDetailCardProps {
|
|
728
|
+
agent: AgentSummary;
|
|
729
|
+
onSelect: () => void;
|
|
730
|
+
}
|
|
731
|
+
declare function AgentDetailCard({ agent, onSelect }: AgentDetailCardProps): react.JSX.Element;
|
|
732
|
+
|
|
733
|
+
interface AgentSortPanelProps {
|
|
734
|
+
consumer: UseAgentConsumerReturn;
|
|
735
|
+
onClose: () => void;
|
|
736
|
+
}
|
|
737
|
+
declare function AgentSortPanel({ consumer, onClose }: AgentSortPanelProps): react.JSX.Element;
|
|
738
|
+
|
|
739
|
+
interface AgentCategoriesPanelProps {
|
|
740
|
+
consumer: UseAgentConsumerReturn;
|
|
741
|
+
allCategories: string[];
|
|
742
|
+
search: string;
|
|
743
|
+
setSearch: (v: string) => void;
|
|
744
|
+
onClose: () => void;
|
|
745
|
+
}
|
|
746
|
+
declare function AgentCategoriesPanel({ consumer, allCategories, search, setSearch, onClose, }: AgentCategoriesPanelProps): react.JSX.Element;
|
|
747
|
+
|
|
748
|
+
interface AgentTagsPanelProps {
|
|
749
|
+
consumer: UseAgentConsumerReturn;
|
|
750
|
+
allTags: string[];
|
|
751
|
+
search: string;
|
|
752
|
+
setSearch: (v: string) => void;
|
|
753
|
+
onClose: () => void;
|
|
754
|
+
}
|
|
755
|
+
declare function AgentTagsPanel({ consumer, allTags, search, setSearch, onClose, }: AgentTagsPanelProps): react.JSX.Element;
|
|
756
|
+
|
|
757
|
+
interface AgentMobileSubViewProps {
|
|
758
|
+
view: "sort" | "categories" | "tags";
|
|
759
|
+
consumer: UseAgentConsumerReturn;
|
|
760
|
+
allCategories: string[];
|
|
761
|
+
allTags: string[];
|
|
762
|
+
catSearch: string;
|
|
763
|
+
setCatSearch: (v: string) => void;
|
|
764
|
+
tagSearch: string;
|
|
765
|
+
setTagSearch: (v: string) => void;
|
|
766
|
+
onBack: () => void;
|
|
767
|
+
}
|
|
768
|
+
declare function AgentMobileSubView({ view, consumer, allCategories, allTags, catSearch, setCatSearch, tagSearch, setTagSearch, onBack, }: AgentMobileSubViewProps): react.JSX.Element;
|
|
769
|
+
|
|
770
|
+
interface FavoriteAgentButtonProps {
|
|
771
|
+
id: string;
|
|
772
|
+
/** "card" = absolute-positioned corner star, "list" = inline icon button */
|
|
773
|
+
variant?: "card" | "list";
|
|
774
|
+
disabled?: boolean;
|
|
775
|
+
}
|
|
776
|
+
declare function FavoriteAgentButton({ id, variant, disabled, }: FavoriteAgentButtonProps): react.JSX.Element;
|
|
777
|
+
|
|
778
|
+
declare const SearchInput: ({ ref, value, onChange, placeholder, }: {
|
|
779
|
+
ref?: Ref<HTMLInputElement>;
|
|
780
|
+
value: string;
|
|
781
|
+
onChange: (v: string) => void;
|
|
782
|
+
placeholder: string;
|
|
783
|
+
}) => react.JSX.Element;
|
|
784
|
+
declare function FilterChip({ icon: Icon, label, active, focused, onClick, }: {
|
|
785
|
+
icon: ComponentType<{
|
|
786
|
+
className?: string;
|
|
787
|
+
}>;
|
|
788
|
+
label: string;
|
|
789
|
+
active: boolean;
|
|
790
|
+
focused?: boolean;
|
|
791
|
+
onClick: () => void;
|
|
792
|
+
}): react.JSX.Element;
|
|
793
|
+
declare function OptionRow({ label, selected, onClick, }: {
|
|
794
|
+
label: string;
|
|
795
|
+
selected: boolean;
|
|
796
|
+
onClick: () => void;
|
|
797
|
+
}): react.JSX.Element;
|
|
798
|
+
declare function CheckRow({ label, checked, onClick, }: {
|
|
799
|
+
label: string;
|
|
800
|
+
checked: boolean;
|
|
801
|
+
onClick: () => void;
|
|
802
|
+
}): react.JSX.Element;
|
|
803
|
+
declare function SidePanelHeader({ title, onClose, }: {
|
|
804
|
+
title: string;
|
|
805
|
+
onClose: () => void;
|
|
806
|
+
}): react.JSX.Element;
|
|
807
|
+
|
|
808
|
+
export { type AgentCatalogLinkComponent, AgentCatalogProvider, type AgentCatalogProviderProps, type AgentCatalogRenderModelRef, type AgentCatalogUiPorts, AgentCategoriesPanel, type AgentCategoriesPanelProps, AgentDetailCard, type AgentDetailCardProps, AgentFilterBar, type AgentFilterBarProps, AgentListContent, type AgentListContentProps, type AgentListCoreOptions, AgentListDropdown, type AgentListDropdownProps, AgentListInlinePicker, type AgentListInlinePickerProps, type AgentListTabCounts, AgentListTabs, AgentMobileSubView, type AgentMobileSubViewProps, AgentRow, type AgentRowProps, AgentSortPanel, type AgentSortPanelProps, AgentTagsPanel, type AgentTagsPanelProps, CheckRow, FavoriteAgentButton, FilterChip, HOVER_GRACE_MS, LIST_MAX_HEIGHT, OptionRow, PANEL_HEIGHT, type RightPanel, SORT_OPTIONS, SearchInput, SidePanelHeader, type UseAgentConsumerReturn, coerceVisibleTab, useAgentCatalog, useAgentCatalogRows, useAgentCatalogState, useAgentCatalogUiPorts, useAgentConsumer, useAgentListCore };
|