@ai-matrx/chat 0.3.23 → 0.3.24
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 +11 -0
- package/dist/agents/components/chat/ChatConversationSurface.js +2 -2
- package/dist/agents/components/chat/ChatRunHeader.js +3 -5
- package/dist/agents/components/chat/PinnedAgentsSection.js +2 -2
- package/dist/agents/components/context-preview/ContextCompareView.js +5 -12
- package/dist/agents/components/inputs/smart-input/composer/useComposerAgent.js +4 -5
- package/dist/agents/components/run/AgentRunnerPage.js +3 -3
- package/dist/agents/hooks/useAgentModelLabel.js +6 -2
- package/dist/agents/hooks/useAgentRunSurfaceScope.js +3 -4
- package/dist/agents/identity/agent-catalog-lists.d.ts +45 -0
- package/dist/agents/identity/agent-catalog-lists.js +128 -0
- package/dist/agents/identity/agent-identity.d.ts +34 -0
- package/dist/agents/identity/agent-identity.js +127 -0
- package/dist/agents/identity/run-tier-store.d.ts +15 -0
- package/dist/agents/identity/run-tier-store.js +23 -0
- package/dist/agents/redux/agent-definition/list-mirror.d.ts +139 -0
- package/dist/agents/redux/agent-definition/list-mirror.js +157 -0
- package/dist/agents/redux/agent-definition/selectors.d.ts +8 -8
- package/dist/agents/redux/agent-definition/slice.d.ts +1 -0
- package/dist/agents/redux/agent-definition/slice.js +1 -0
- package/dist/agents/redux/agent-definition/thunks.d.ts +10 -205
- package/dist/agents/redux/agent-definition/thunks.js +43 -230
- package/dist/agents/redux/agent-filter/selectors.d.ts +9 -0
- package/dist/agents/redux/agent-filter/selectors.js +25 -23
- package/dist/agents/redux/agent-filter/useAgentIdsForFilter.d.ts +6 -0
- package/dist/agents/redux/agent-filter/useAgentIdsForFilter.js +14 -0
- package/dist/agents/redux/conversation-history/selectors.js +2 -3
- package/dist/agents/redux/execution-system/thunks/launch-agent-execution.thunk.js +2 -2
- package/dist/agents/redux/execution-system/thunks/load-conversation.thunk.js +2 -2
- package/dist/agents/redux/execution-system/thunks/run-headless-agent-json.js +2 -2
- package/dist/agents/redux/execution-system/utils/output-contract-guard.js +2 -1
- package/dist/agents/types/agent-definition.types.d.ts +8 -18
- package/dist/cx-chat/components/ChatMobileAgentName.js +4 -7
- package/dist/cx-chat/components/ChatSidebarClient.js +2 -2
- package/dist/cx-chat/components/agent/AgentPickerSheet.js +10 -11
- package/dist/cx-chat/hooks/useChatCatalogueInit.js +4 -7
- package/dist/cx-chat/hooks/useInstanceBootstrap.js +4 -5
- package/dist/host/db-types.d.ts +86 -0
- package/dist/window-panels/windows/agents/AgentRunWindow.js +4 -6
- package/dist/window-panels/windows/agents/RunControlsWindow.js +2 -4
- package/package.json +4 -4
|
@@ -8,34 +8,25 @@ import {
|
|
|
8
8
|
hasField
|
|
9
9
|
} from "@ai-matrx/agents/field-flags";
|
|
10
10
|
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
} from "../../../host/session-retry.js";
|
|
11
|
+
RunTierNotReadableError,
|
|
12
|
+
RunTierReadError,
|
|
13
|
+
RunTierTimeoutError
|
|
14
|
+
} from "@ai-matrx/agents/runtime";
|
|
15
|
+
import { getRunTierStore } from "../../identity/run-tier-store.js";
|
|
17
16
|
import {
|
|
18
17
|
pgErrorToError
|
|
19
18
|
} from "@ai-matrx/data";
|
|
20
19
|
import {
|
|
21
20
|
agentNameTakenError
|
|
22
21
|
} from "./agentNameTaken.js";
|
|
23
|
-
import {
|
|
24
|
-
withRetry
|
|
25
|
-
} from "@ai-matrx/data/net";
|
|
26
22
|
import {
|
|
27
23
|
ConnectTimeoutError
|
|
28
24
|
} from "@ai-matrx/data/net";
|
|
29
|
-
import {
|
|
30
|
-
readFavoriteIds
|
|
31
|
-
} from "../../../context/sources/scopes.js";
|
|
32
25
|
import {
|
|
33
26
|
mergePartialAgent,
|
|
34
27
|
setAgentFetchStatus,
|
|
35
28
|
setAgentLoading,
|
|
36
|
-
setAgentError
|
|
37
|
-
setAgentsStatus,
|
|
38
|
-
setAgentsError
|
|
29
|
+
setAgentError
|
|
39
30
|
} from "./slice.js";
|
|
40
31
|
import {
|
|
41
32
|
selectAgentReadyForExecution,
|
|
@@ -48,6 +39,15 @@ import {
|
|
|
48
39
|
isSignedOutVisitor,
|
|
49
40
|
NotAuthenticatedError
|
|
50
41
|
} from "../../../host/identity.js";
|
|
42
|
+
function runTierFailure(agentId, e) {
|
|
43
|
+
if (e instanceof RunTierNotReadableError) return agentNotReadableError(agentId);
|
|
44
|
+
if (e instanceof RunTierTimeoutError) return new ConnectTimeoutError(e.timeoutMs);
|
|
45
|
+
if (e instanceof RunTierReadError && e.pgError) {
|
|
46
|
+
const pg = { message: e.pgError.message, code: e.pgError.code ?? "", details: e.pgError.details ?? "", hint: e.pgError.hint ?? "" };
|
|
47
|
+
return agentNameTakenError(pg) ?? pgErrorToError(pg);
|
|
48
|
+
}
|
|
49
|
+
return e instanceof Error ? e : new Error(String(e));
|
|
50
|
+
}
|
|
51
51
|
class AgentToolAssignmentError extends Error {
|
|
52
52
|
constructor(message) {
|
|
53
53
|
super(message);
|
|
@@ -131,8 +131,6 @@ function sameStringArray(a, b) {
|
|
|
131
131
|
function isToolAssignmentPhantom(current, base) {
|
|
132
132
|
return sameStringArray(current.tools, base.tools) && current.model_id === base.model_id && current.created_by === base.created_by && current.organization_id === base.organization_id && current.is_archived === base.is_archived;
|
|
133
133
|
}
|
|
134
|
-
const AGENT_LIST_RPC_PAGE_SIZE = 100;
|
|
135
|
-
const AGENT_SEARCH_LIMIT = 200;
|
|
136
134
|
const REGISTRY_ACCESS_LEVELS = [
|
|
137
135
|
"owner",
|
|
138
136
|
"admin",
|
|
@@ -145,124 +143,6 @@ function toRegistryAccessLevel(value) {
|
|
|
145
143
|
(level) => level === value
|
|
146
144
|
) ?? null;
|
|
147
145
|
}
|
|
148
|
-
function mergeAgentSummaries(dispatch, rows) {
|
|
149
|
-
for (const row of rows) {
|
|
150
|
-
dispatch(
|
|
151
|
-
mergePartialAgent({
|
|
152
|
-
id: row.id,
|
|
153
|
-
name: row.name ?? void 0,
|
|
154
|
-
description: row.description,
|
|
155
|
-
category: row.category,
|
|
156
|
-
tags: row.tags,
|
|
157
|
-
agentType: row.agentType,
|
|
158
|
-
modelId: row.modelId,
|
|
159
|
-
isActive: row.isActive,
|
|
160
|
-
isArchived: row.isArchived,
|
|
161
|
-
// No `isFavorite`: the catalog row's column is retired — stars are
|
|
162
|
-
// overlaid from platform.user_entity_state by `overlayAgentFavorites`.
|
|
163
|
-
// The registry spells "absent" as `undefined` where the DB row spells
|
|
164
|
-
// it `null`. Five fields differ; this is the vocabulary translation
|
|
165
|
-
// at the seam, not a value change.
|
|
166
|
-
createdBy: row.createdBy ?? void 0,
|
|
167
|
-
organizationId: row.organizationId ?? void 0,
|
|
168
|
-
taskId: row.taskId,
|
|
169
|
-
sourceAgentId: row.sourceAgentId,
|
|
170
|
-
createdAt: row.createdAt ?? void 0,
|
|
171
|
-
updatedAt: row.updatedAt ?? void 0,
|
|
172
|
-
isVersion: false,
|
|
173
|
-
isOwner: row.isOwner,
|
|
174
|
-
// `access_level` is a DB-owned vocabulary the package deliberately
|
|
175
|
-
// leaves open (an unknown level renders as itself). This registry's
|
|
176
|
-
// field is a closed union, so an unrecognised level is stored as
|
|
177
|
-
// `null` — absent, never silently coerced into a wrong level.
|
|
178
|
-
accessLevel: toRegistryAccessLevel(row.accessLevel),
|
|
179
|
-
sharedByEmail: row.sharedByEmail ?? void 0,
|
|
180
|
-
// The class pin; a catalog read that lacks the column leaves it absent.
|
|
181
|
-
...row.offeringId === void 0 ? {} : { listOfferingPin: row.offeringId }
|
|
182
|
-
})
|
|
183
|
-
);
|
|
184
|
-
dispatch(setAgentFetchStatus({ id: row.id, status: "list" }));
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
async function overlayAgentFavorites(dispatch, ids) {
|
|
188
|
-
if (ids.length === 0) return;
|
|
189
|
-
const favorites = await readFavoriteIds("agent", ids);
|
|
190
|
-
if (!favorites) return;
|
|
191
|
-
for (const id of ids) {
|
|
192
|
-
dispatch(mergePartialAgent({ id, isFavorite: favorites.has(id) }));
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
const overlayAgentFavoritesThunk = createAsyncThunk("agentDefinition/overlayFavorites", async (ids, { dispatch }) => {
|
|
196
|
-
await overlayAgentFavorites(dispatch, ids);
|
|
197
|
-
});
|
|
198
|
-
const fetchAgentsList = createAsyncThunk(
|
|
199
|
-
"agentDefinition/fetchList",
|
|
200
|
-
async (_, { dispatch }) => {
|
|
201
|
-
dispatch(setAgentsStatus("loading"));
|
|
202
|
-
dispatch(setAgentsError(null));
|
|
203
|
-
const catalog = getAgentCatalog();
|
|
204
|
-
try {
|
|
205
|
-
await catalog.ensureLoaded();
|
|
206
|
-
} catch (e) {
|
|
207
|
-
dispatch(setAgentsError(e instanceof Error ? e.message : String(e)));
|
|
208
|
-
dispatch(setAgentsStatus("failed"));
|
|
209
|
-
throw e;
|
|
210
|
-
}
|
|
211
|
-
const rows = catalog.getState().rows;
|
|
212
|
-
mergeAgentSummaries(dispatch, rows);
|
|
213
|
-
await overlayAgentFavorites(
|
|
214
|
-
dispatch,
|
|
215
|
-
rows.map((r) => r.id)
|
|
216
|
-
);
|
|
217
|
-
dispatch(setAgentsStatus("succeeded"));
|
|
218
|
-
}
|
|
219
|
-
);
|
|
220
|
-
const searchAgentsServer = createAsyncThunk(
|
|
221
|
-
"agentDefinition/searchServer",
|
|
222
|
-
async ({ query, deep = false }, { dispatch }) => {
|
|
223
|
-
const q = query.trim();
|
|
224
|
-
if (!q) return { ids: [], deep, query: q };
|
|
225
|
-
const catalog = getAgentCatalog();
|
|
226
|
-
const ids = await catalog.searchServer(q, deep);
|
|
227
|
-
const state = catalog.getState();
|
|
228
|
-
const hits = ids.map((id) => state.byId[id]).filter((r) => !!r);
|
|
229
|
-
mergeAgentSummaries(dispatch, hits);
|
|
230
|
-
await overlayAgentFavorites(
|
|
231
|
-
dispatch,
|
|
232
|
-
hits.map((r) => r.id)
|
|
233
|
-
);
|
|
234
|
-
return { ids, deep, query: q };
|
|
235
|
-
}
|
|
236
|
-
);
|
|
237
|
-
const fetchAgentsListFull = createAsyncThunk(
|
|
238
|
-
"agentDefinition/fetchListFull",
|
|
239
|
-
async (_, { dispatch }) => {
|
|
240
|
-
const catalog = getAgentCatalog();
|
|
241
|
-
await catalog.ensureLoaded();
|
|
242
|
-
const rows = catalog.getState().rows;
|
|
243
|
-
mergeAgentSummaries(dispatch, rows);
|
|
244
|
-
await overlayAgentFavorites(
|
|
245
|
-
dispatch,
|
|
246
|
-
rows.map((r) => r.id)
|
|
247
|
-
);
|
|
248
|
-
}
|
|
249
|
-
);
|
|
250
|
-
const ensureAgentIdentity = createAsyncThunk(
|
|
251
|
-
"agentDefinition/ensureIdentity",
|
|
252
|
-
async (agentId, { dispatch, getState }) => {
|
|
253
|
-
if (getState().agentDefinition.agents?.[agentId]?.name) return;
|
|
254
|
-
const catalog = getAgentCatalog();
|
|
255
|
-
let row = catalog.getState().byId[agentId];
|
|
256
|
-
if (!row) {
|
|
257
|
-
await catalog.ensureLoaded();
|
|
258
|
-
row = catalog.getState().byId[agentId];
|
|
259
|
-
}
|
|
260
|
-
if (row) {
|
|
261
|
-
mergeAgentSummaries(dispatch, [row]);
|
|
262
|
-
await overlayAgentFavorites(dispatch, [row.id]);
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
);
|
|
266
146
|
const fetchAgentRunTier = createAsyncThunk(
|
|
267
147
|
"agentDefinition/fetchRunTier",
|
|
268
148
|
async (arg, { dispatch, getState }) => {
|
|
@@ -273,36 +153,16 @@ const fetchAgentRunTier = createAsyncThunk(
|
|
|
273
153
|
return;
|
|
274
154
|
if (await isSignedOutVisitor()) throw new NotAuthenticatedError();
|
|
275
155
|
dispatch(setAgentLoading({ id: agentId, loading: true }));
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
resolve(result);
|
|
285
|
-
},
|
|
286
|
-
(err) => {
|
|
287
|
-
clearTimeout(timer);
|
|
288
|
-
reject(err);
|
|
289
|
-
}
|
|
290
|
-
);
|
|
291
|
-
}),
|
|
292
|
-
{ attempts: 2, initialDelayMs: 400 }
|
|
293
|
-
);
|
|
294
|
-
dispatch(setAgentLoading({ id: agentId, loading: false }));
|
|
295
|
-
if (error) {
|
|
296
|
-
dispatch(setAgentError({ id: agentId, error: error.message }));
|
|
297
|
-
throw agentNameTakenError(error) ?? pgErrorToError(error);
|
|
298
|
-
}
|
|
299
|
-
const raw = Array.isArray(data) ? data[0] : data;
|
|
300
|
-
if (!raw) {
|
|
301
|
-
const refusal = agentNotReadableError(agentId);
|
|
302
|
-
dispatch(setAgentError({ id: agentId, error: refusal.message }));
|
|
303
|
-
throw refusal;
|
|
156
|
+
let row;
|
|
157
|
+
try {
|
|
158
|
+
row = await getRunTierStore().loadRunTier(agentId, { force: true });
|
|
159
|
+
} catch (e) {
|
|
160
|
+
dispatch(setAgentLoading({ id: agentId, loading: false }));
|
|
161
|
+
const failure = runTierFailure(agentId, e);
|
|
162
|
+
dispatch(setAgentError({ id: agentId, error: failure.message }));
|
|
163
|
+
throw failure;
|
|
304
164
|
}
|
|
305
|
-
|
|
165
|
+
dispatch(setAgentLoading({ id: agentId, loading: false }));
|
|
306
166
|
dispatch(
|
|
307
167
|
mergePartialAgent({
|
|
308
168
|
id: row.id,
|
|
@@ -333,18 +193,13 @@ const fetchAgentRunControls = createAsyncThunk(
|
|
|
333
193
|
async (agentId, { dispatch, getState }) => {
|
|
334
194
|
if (selectAgentRunControlsReady(getState(), agentId)) return;
|
|
335
195
|
if (await isSignedOutVisitor()) throw new NotAuthenticatedError();
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
const row = Array.isArray(data) ? data[0] : data;
|
|
344
|
-
if (!row) {
|
|
345
|
-
const refusal = agentNotReadableError(agentId);
|
|
346
|
-
dispatch(setAgentError({ id: agentId, error: refusal.message }));
|
|
347
|
-
throw refusal;
|
|
196
|
+
let row;
|
|
197
|
+
try {
|
|
198
|
+
row = await getRunTierStore().loadRunControls(agentId, { force: true });
|
|
199
|
+
} catch (e) {
|
|
200
|
+
const failure = runTierFailure(agentId, e);
|
|
201
|
+
dispatch(setAgentError({ id: agentId, error: failure.message }));
|
|
202
|
+
throw failure;
|
|
348
203
|
}
|
|
349
204
|
const loaded = getState().agentDefinition.agents?.[agentId]?._loadedFields;
|
|
350
205
|
const missing = (field) => !loaded || !hasField(loaded, field);
|
|
@@ -360,51 +215,11 @@ const fetchAgentRunControls = createAsyncThunk(
|
|
|
360
215
|
);
|
|
361
216
|
}
|
|
362
217
|
);
|
|
363
|
-
const fetchSharedAgents = createAsyncThunk("agentDefinition/fetchShared", async (_, { dispatch }) => {
|
|
364
|
-
const { data, error } = await supabase.rpc("agx_get_shared_with_me");
|
|
365
|
-
if (error) throw pgErrorToError(error);
|
|
366
|
-
const rows = data ?? [];
|
|
367
|
-
for (const row of rows) {
|
|
368
|
-
dispatch(
|
|
369
|
-
mergePartialAgent({
|
|
370
|
-
id: row.id,
|
|
371
|
-
name: row.name ?? void 0,
|
|
372
|
-
description: row.description,
|
|
373
|
-
category: row.category,
|
|
374
|
-
tags: row.tags ?? [],
|
|
375
|
-
agentType: row.agent_type,
|
|
376
|
-
isVersion: false,
|
|
377
|
-
createdAt: row.created_at,
|
|
378
|
-
updatedAt: row.updated_at,
|
|
379
|
-
isOwner: false,
|
|
380
|
-
accessLevel: row.permission_level,
|
|
381
|
-
sharedByEmail: row.owner_email
|
|
382
|
-
})
|
|
383
|
-
);
|
|
384
|
-
dispatch(setAgentFetchStatus({ id: row.id, status: "list" }));
|
|
385
|
-
}
|
|
386
|
-
await overlayAgentFavorites(
|
|
387
|
-
dispatch,
|
|
388
|
-
rows.map((r) => r.id)
|
|
389
|
-
);
|
|
390
|
-
return rows;
|
|
391
|
-
});
|
|
392
|
-
const fetchSharedAgentsForChat = createAsyncThunk("agentDefinition/fetchSharedForChat", async () => {
|
|
393
|
-
const { data, error } = await supabase.rpc("agx_get_shared_for_chat");
|
|
394
|
-
if (error) throw pgErrorToError(error);
|
|
395
|
-
return data ?? [];
|
|
396
|
-
});
|
|
397
218
|
true;
|
|
398
219
|
const fetchAgentAccessLevel = createAsyncThunk("agentDefinition/fetchAccessLevel", async (agentId, { dispatch }) => {
|
|
399
|
-
const
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
})
|
|
403
|
-
);
|
|
404
|
-
if (error) throw pgErrorToError(error);
|
|
405
|
-
const rawRow = Array.isArray(data) ? data[0] : data;
|
|
406
|
-
if (!rawRow) throw new Error(`No access level returned for agent ${agentId}`);
|
|
407
|
-
const row = rawRow;
|
|
220
|
+
const row = await getRunTierStore().loadAccessLevel(agentId, { force: true }).catch((e) => {
|
|
221
|
+
throw runTierFailure(agentId, e);
|
|
222
|
+
});
|
|
408
223
|
dispatch(
|
|
409
224
|
mergePartialAgent({
|
|
410
225
|
id: agentId,
|
|
@@ -416,15 +231,15 @@ const fetchAgentAccessLevel = createAsyncThunk("agentDefinition/fetchAccessLevel
|
|
|
416
231
|
);
|
|
417
232
|
return row;
|
|
418
233
|
});
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
}
|
|
234
|
+
import {
|
|
235
|
+
overlayAgentFavoritesThunk,
|
|
236
|
+
fetchAgentsList,
|
|
237
|
+
searchAgentsServer,
|
|
238
|
+
fetchAgentsListFull,
|
|
239
|
+
ensureAgentIdentity,
|
|
240
|
+
isChatListStale,
|
|
241
|
+
initializeChatAgents
|
|
242
|
+
} from "./list-mirror.js";
|
|
428
243
|
export {
|
|
429
244
|
AgentToolAssignmentConflictError,
|
|
430
245
|
AgentToolAssignmentError,
|
|
@@ -439,8 +254,6 @@ export {
|
|
|
439
254
|
fetchAgentRunTier,
|
|
440
255
|
fetchAgentsList,
|
|
441
256
|
fetchAgentsListFull,
|
|
442
|
-
fetchSharedAgents,
|
|
443
|
-
fetchSharedAgentsForChat,
|
|
444
257
|
initializeChatAgents,
|
|
445
258
|
isAvailableToolModel,
|
|
446
259
|
isChatListStale,
|
|
@@ -338,6 +338,15 @@ export declare const makeSelectAgentsForFilter: () => ((state: {
|
|
|
338
338
|
memoize: typeof import("reselect").weakMapMemoize;
|
|
339
339
|
argsMemoize: typeof import("reselect").weakMapMemoize;
|
|
340
340
|
};
|
|
341
|
+
/** The fields a filter reads — satisfied by a catalog `AgentSummary` and a registry record alike. */
|
|
342
|
+
export interface FilterableAgent {
|
|
343
|
+
id: string;
|
|
344
|
+
isFavorite: boolean;
|
|
345
|
+
tags?: string[] | null;
|
|
346
|
+
category?: string | null;
|
|
347
|
+
}
|
|
348
|
+
/** Pure: the agents matching a stored `CodeAgentFilter`. `null` / "all" returns the input. */
|
|
349
|
+
export declare function filterAgentsForFilter<T extends FilterableAgent>(agents: T[], filter: CodeAgentFilter | null | undefined): T[];
|
|
341
350
|
/**
|
|
342
351
|
* Convenience shorthand: returns just the ids that match the filter. Useful
|
|
343
352
|
* for passing into `ConversationHistorySidebar`'s `agentIds` prop.
|
|
@@ -5,31 +5,32 @@ const makeSelectAgentsForFilter = () => createSelector(
|
|
|
5
5
|
selectActiveAgents,
|
|
6
6
|
(_state, filter) => filter
|
|
7
7
|
],
|
|
8
|
-
(agents, filter) =>
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
if (filter.agentIds.length === 0) return agents;
|
|
25
|
-
const wanted = new Set(filter.agentIds);
|
|
26
|
-
return agents.filter((a) => wanted.has(a.id));
|
|
27
|
-
}
|
|
28
|
-
default:
|
|
29
|
-
return agents;
|
|
8
|
+
(agents, filter) => filterAgentsForFilter(agents, filter)
|
|
9
|
+
);
|
|
10
|
+
function filterAgentsForFilter(agents, filter) {
|
|
11
|
+
if (!filter || filter.mode === "all") return agents;
|
|
12
|
+
switch (filter.mode) {
|
|
13
|
+
case "favorites":
|
|
14
|
+
return agents.filter((a) => a.isFavorite);
|
|
15
|
+
case "tags": {
|
|
16
|
+
if (filter.tags.length === 0) return agents;
|
|
17
|
+
const wanted = new Set(filter.tags);
|
|
18
|
+
return agents.filter((a) => a.tags?.some((t) => wanted.has(t)));
|
|
19
|
+
}
|
|
20
|
+
case "categories": {
|
|
21
|
+
if (filter.categories.length === 0) return agents;
|
|
22
|
+
const wanted = new Set(filter.categories);
|
|
23
|
+
return agents.filter((a) => a.category && wanted.has(a.category));
|
|
30
24
|
}
|
|
25
|
+
case "explicit": {
|
|
26
|
+
if (filter.agentIds.length === 0) return agents;
|
|
27
|
+
const wanted = new Set(filter.agentIds);
|
|
28
|
+
return agents.filter((a) => wanted.has(a.id));
|
|
29
|
+
}
|
|
30
|
+
default:
|
|
31
|
+
return agents;
|
|
31
32
|
}
|
|
32
|
-
|
|
33
|
+
}
|
|
33
34
|
const makeSelectAgentIdsForFilter = () => {
|
|
34
35
|
const selectAgents = makeSelectAgentsForFilter();
|
|
35
36
|
return createSelector(
|
|
@@ -80,6 +81,7 @@ export {
|
|
|
80
81
|
conversationHistoryAgentIds,
|
|
81
82
|
describeEmptyFilter,
|
|
82
83
|
describeFilter,
|
|
84
|
+
filterAgentsForFilter,
|
|
83
85
|
makeSelectAgentIdsForFilter,
|
|
84
86
|
makeSelectAgentsForFilter
|
|
85
87
|
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { CodeAgentFilter } from "../../../host/prefs.js";
|
|
2
|
+
/**
|
|
3
|
+
* The agent ids a stored `CodeAgentFilter` matches, over the ONE agent catalog (active, unarchived
|
|
4
|
+
* agents). "All" answers `[]` — the history sidebar's "every accessible conversation" sentinel.
|
|
5
|
+
*/
|
|
6
|
+
export declare function useAgentIdsForFilter(filter: CodeAgentFilter | null | undefined): string[];
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useMemo } from "react";
|
|
3
|
+
import { isActiveAgent, useCatalogAgents } from "../../identity/agent-catalog-lists.js";
|
|
4
|
+
import { conversationHistoryAgentIds, filterAgentsForFilter } from "./selectors.js";
|
|
5
|
+
function useAgentIdsForFilter(filter) {
|
|
6
|
+
const rows = useCatalogAgents();
|
|
7
|
+
return useMemo(() => {
|
|
8
|
+
const matching = filterAgentsForFilter(rows.filter(isActiveAgent), filter);
|
|
9
|
+
return conversationHistoryAgentIds(filter, matching.map((a) => a.id));
|
|
10
|
+
}, [rows, filter]);
|
|
11
|
+
}
|
|
12
|
+
export {
|
|
13
|
+
useAgentIdsForFilter
|
|
14
|
+
};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { createSelector } from "@reduxjs/toolkit";
|
|
2
2
|
import { idMatchesQuery } from "@ai-matrx/kit/search-scoring";
|
|
3
|
-
import { selectAgentById } from "../agent-definition/selectors.js";
|
|
4
3
|
import {
|
|
5
4
|
defaultScopeState,
|
|
6
5
|
rowMatchesArchiveView
|
|
@@ -10,6 +9,7 @@ import {
|
|
|
10
9
|
normalizeLanes
|
|
11
10
|
} from "./lanes.js";
|
|
12
11
|
import { selectStoredConversationLanes } from "../../../host/prefs.js";
|
|
12
|
+
import { readAgentName } from "../../identity/agent-identity.js";
|
|
13
13
|
const selectConversationHistory = (state) => state.conversationHistory;
|
|
14
14
|
const selectSourceFacets = (state) => state.conversationHistory.sourceFacets;
|
|
15
15
|
const selectLaneCounts = createSelector(
|
|
@@ -120,8 +120,7 @@ const makeSelectGroupedByAgent = (scopeId) => {
|
|
|
120
120
|
for (const [agentId, agentItems] of buckets.entries()) {
|
|
121
121
|
let label = "Unknown agent";
|
|
122
122
|
if (agentId) {
|
|
123
|
-
|
|
124
|
-
label = agent?.name ?? agentId.slice(0, 8);
|
|
123
|
+
label = readAgentName(state, agentId) ?? agentId.slice(0, 8);
|
|
125
124
|
}
|
|
126
125
|
result.push({ agentId, label, items: agentItems });
|
|
127
126
|
}
|
|
@@ -24,7 +24,6 @@ import {
|
|
|
24
24
|
import { withSurfaceDocumentEvidence } from "../../../../surfaces/utils/document-evidence.js";
|
|
25
25
|
import { alwaysOnSurfaceKeys } from "../../../../surfaces/utils/always-on-context.js";
|
|
26
26
|
import {
|
|
27
|
-
ensureAgentIdentity,
|
|
28
27
|
fetchAgentRunTier
|
|
29
28
|
} from "../../agent-definition/thunks.js";
|
|
30
29
|
import {
|
|
@@ -81,6 +80,7 @@ import {
|
|
|
81
80
|
resolveLaunchMappingLayers,
|
|
82
81
|
resolvePerLaunchMappings
|
|
83
82
|
} from "./surface-scope-mapping.js";
|
|
83
|
+
import { ensureAgentCatalog } from "../../../identity/agent-identity.js";
|
|
84
84
|
function hasSignedInSession(state) {
|
|
85
85
|
return Boolean(state.userAuth?.accessToken);
|
|
86
86
|
}
|
|
@@ -217,7 +217,7 @@ const launchAgentExecution = createAsyncThunk("instances/launch", async (options
|
|
|
217
217
|
let bindingAutoRunGap = [];
|
|
218
218
|
if (agentId && !shortcutId) {
|
|
219
219
|
if (hasSignedInSession(getState())) {
|
|
220
|
-
void
|
|
220
|
+
void ensureAgentCatalog();
|
|
221
221
|
}
|
|
222
222
|
const preState = getState();
|
|
223
223
|
const payload = selectAgentRunTier(preState, agentId);
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { ensureAgentIdentity } from "../../agent-definition/thunks.js";
|
|
2
1
|
import { createAsyncThunk } from "@reduxjs/toolkit";
|
|
3
2
|
import { supabase } from "../../../../host/db.js";
|
|
4
3
|
import {
|
|
@@ -70,6 +69,7 @@ import {
|
|
|
70
69
|
} from "./conversation-bundle.js";
|
|
71
70
|
import { getClaimsUser } from "../../../../host/db.js";
|
|
72
71
|
import { canActOn } from "../../../../ui/canActOn.js";
|
|
72
|
+
import { ensureAgentCatalog } from "../../../identity/agent-identity.js";
|
|
73
73
|
const NOT_READABLE_DETAIL = "it may have been removed, or your sign-in lost access to it";
|
|
74
74
|
const loadConversation = createAsyncThunk(
|
|
75
75
|
"conversations/load",
|
|
@@ -326,7 +326,7 @@ const loadConversation = createAsyncThunk(
|
|
|
326
326
|
}
|
|
327
327
|
let baseInputCapabilities = {};
|
|
328
328
|
if (conv.initial_agent_id) {
|
|
329
|
-
void
|
|
329
|
+
void ensureAgentCatalog();
|
|
330
330
|
try {
|
|
331
331
|
baseInputCapabilities = await fetchInputCapabilitiesSnapshot({
|
|
332
332
|
agentId: conv.initial_agent_id,
|
|
@@ -23,12 +23,12 @@ import {
|
|
|
23
23
|
import { setUserInputMessageParts } from "../instance-user-input/instance-user-input.slice.js";
|
|
24
24
|
import { launchAgentExecution } from "./launch-agent-execution.thunk.js";
|
|
25
25
|
import { resolveMandate } from "../../../../mandates/service.js";
|
|
26
|
-
import { selectAgentName } from "../../agent-definition/selectors.js";
|
|
27
26
|
import {
|
|
28
27
|
judgeDeclaredFlattening,
|
|
29
28
|
judgeHarvestedFlattening
|
|
30
29
|
} from "./structured-output-flattening.js";
|
|
31
30
|
import { executeInstance } from "./execute-instance.thunk.js";
|
|
31
|
+
import { readAgentName } from "../../../identity/agent-identity.js";
|
|
32
32
|
function livePosture(onConversationCreated) {
|
|
33
33
|
return onConversationCreated ? { displayMode: "direct", keepInstance: true, onConversationCreated } : {};
|
|
34
34
|
}
|
|
@@ -140,7 +140,7 @@ async function failWarnedOutputMissingKeys(getState, opts, result) {
|
|
|
140
140
|
const holderId = warning.holderId ?? resolved.agentId;
|
|
141
141
|
let holderName;
|
|
142
142
|
try {
|
|
143
|
-
holderName = holderId ?
|
|
143
|
+
holderName = holderId ? readAgentName(getState(), holderId) ?? void 0 : void 0;
|
|
144
144
|
} catch {
|
|
145
145
|
holderName = void 0;
|
|
146
146
|
}
|
|
@@ -4,6 +4,7 @@ import { peekMandateCatalogueEntry } from "../../../../host/ui-slots.js";
|
|
|
4
4
|
import { fetchAgentOutputSchemas } from "../../../../mandates/output-contract.js";
|
|
5
5
|
import { SURFACE_WRITE_TOOL_NAME } from "../../../../surfaces/runtime/surface-writeback.js";
|
|
6
6
|
import { isJsonObject } from "../../../../utils/json.js";
|
|
7
|
+
import { readAgentName } from "../../../identity/agent-identity.js";
|
|
7
8
|
function schemaName(schema) {
|
|
8
9
|
if (!isJsonObject(schema)) return null;
|
|
9
10
|
return typeof schema.name === "string" && schema.name ? schema.name : null;
|
|
@@ -14,7 +15,7 @@ async function resolveRunOutputContract(state, conversationId) {
|
|
|
14
15
|
const agentId = conversation.agentId ?? null;
|
|
15
16
|
const mandateKey = conversation.mandateKey ?? null;
|
|
16
17
|
const record = agentId ? selectAgentById(state, agentId) : void 0;
|
|
17
|
-
const agentName =
|
|
18
|
+
const agentName = readAgentName(state, agentId) ?? null;
|
|
18
19
|
const outputSchemaLoaded = record ? hasField(record._loadedFields, "outputSchema") : false;
|
|
19
20
|
if (record && outputSchemaLoaded && record.outputSchema) {
|
|
20
21
|
const name2 = record.outputSchema.name;
|
|
@@ -6,6 +6,7 @@ import type { FieldFlags } from "@ai-matrx/agents/field-flags";
|
|
|
6
6
|
import type { SkillConfig } from "../../ui/skills-types.js";
|
|
7
7
|
import type { UiGates } from "../redux/agent-settings/ui-gates.js";
|
|
8
8
|
import type { MatrxDirectivesConfig } from "./matrx-directives.types.js";
|
|
9
|
+
import type { AgentRunTierRow, AgentRunCounts } from "@ai-matrx/agents/runtime";
|
|
9
10
|
export type AgentType = "user" | "builtin";
|
|
10
11
|
/**
|
|
11
12
|
* All available UI input types for agent variables.
|
|
@@ -493,29 +494,18 @@ export interface AgentExecutionMinimal {
|
|
|
493
494
|
* `model_id` is the agent's default model (display + override diff base only —
|
|
494
495
|
* the server owns the merge of `config_overrides`). `tool_ids` is display only.
|
|
495
496
|
*/
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
497
|
+
/**
|
|
498
|
+
* The run tier row (`agx_get_run_tier`) — the core's `AgentRunTierRow`
|
|
499
|
+
* (`@ai-matrx/agents/runtime`, read by `createRunTierStore`) with its JSON
|
|
500
|
+
* columns narrowed to chat's variable, context-policy and gate shapes.
|
|
501
|
+
*/
|
|
502
|
+
export interface AgentRunTier extends Omit<AgentRunTierRow, "variable_definitions" | "context_policies" | "ui_gates"> {
|
|
502
503
|
variable_definitions: VariableDefinition[] | null;
|
|
503
504
|
context_policies: ContextPolicy[] | null;
|
|
504
|
-
auto_context_disabled: boolean;
|
|
505
|
-
model_id: string | null;
|
|
506
505
|
ui_gates: UiGates | null;
|
|
507
|
-
tool_ids: string[] | null;
|
|
508
|
-
access_level: string;
|
|
509
|
-
custom_tool_count: number;
|
|
510
|
-
skill_count: number;
|
|
511
|
-
connection_count: number;
|
|
512
506
|
}
|
|
513
507
|
/** The run tier's plain counts, as the registry stores them (P24b). */
|
|
514
|
-
export
|
|
515
|
-
customTools: number;
|
|
516
|
-
skills: number;
|
|
517
|
-
connections: number;
|
|
518
|
-
}
|
|
508
|
+
export type { AgentRunCounts } from "@ai-matrx/agents/runtime";
|
|
519
509
|
/** The run-control pickers' extra values (`agx_get_run_controls`, P25). */
|
|
520
510
|
export interface AgentRunControls {
|
|
521
511
|
customToolNames: string[];
|
|
@@ -4,8 +4,7 @@ import { useState, useCallback } from "react";
|
|
|
4
4
|
import { ChevronDown } from "lucide-react";
|
|
5
5
|
import { usePathname, useSearchParams, useRouter } from "../../host/navigation.js";
|
|
6
6
|
import { AgentPickerSheet } from "../../next/lazy/AgentPickerSheet.js";
|
|
7
|
-
import {
|
|
8
|
-
import { selectAgentById } from "../../agents/redux/agent-definition/selectors.js";
|
|
7
|
+
import { useAgentName } from "../../agents/identity/agent-identity.js";
|
|
9
8
|
import { pushAppHref } from "../../host/ui-slots.js";
|
|
10
9
|
import { Button } from "@ai-matrx/design-system/controls";
|
|
11
10
|
function ChatMobileAgentName() {
|
|
@@ -17,10 +16,8 @@ function ChatMobileAgentName() {
|
|
|
17
16
|
const pathMatch = pathname.match(/\/demos\/chat\/a\/([^/?]+)/);
|
|
18
17
|
return pathMatch?.[1] ?? searchParams.get("agent") ?? void 0;
|
|
19
18
|
})();
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
);
|
|
23
|
-
const displayName = agentRecord?.name ?? "Matrx Chat";
|
|
19
|
+
const agentName = useAgentName(agentIdFromUrl);
|
|
20
|
+
const displayName = agentName ?? "Matrx Chat";
|
|
24
21
|
const handleAgentSelect = useCallback(
|
|
25
22
|
(agent) => {
|
|
26
23
|
setIsPickerOpen(false);
|
|
@@ -34,7 +31,7 @@ function ChatMobileAgentName() {
|
|
|
34
31
|
{
|
|
35
32
|
open: isPickerOpen,
|
|
36
33
|
onOpenChange: setIsPickerOpen,
|
|
37
|
-
selectedAgent:
|
|
34
|
+
selectedAgent: agentIdFromUrl && agentName ? { promptId: agentIdFromUrl, name: agentName } : null,
|
|
38
35
|
onSelect: handleAgentSelect
|
|
39
36
|
}
|
|
40
37
|
),
|
|
@@ -15,9 +15,9 @@ import {
|
|
|
15
15
|
} from "@ai-matrx/tap-target/buttons";
|
|
16
16
|
import { useAppDispatch, useAppSelector } from "../../store/hooks.js";
|
|
17
17
|
import { selectAgentById } from "../../agents/redux/agent-definition/selectors.js";
|
|
18
|
-
import { initializeChatAgents } from "../../agents/redux/agent-definition/thunks.js";
|
|
19
18
|
import { pushAppHref } from "../../host/ui-slots.js";
|
|
20
19
|
import { Button } from "@ai-matrx/design-system/controls";
|
|
20
|
+
import { ensureAgentCatalog } from "../../agents/identity/agent-identity.js";
|
|
21
21
|
function togglePanel() {
|
|
22
22
|
const cb = document.getElementById(
|
|
23
23
|
"shell-panel-toggle"
|
|
@@ -127,7 +127,7 @@ function ChatPanelContent() {
|
|
|
127
127
|
const [searchQuery, setSearchQuery] = useState("");
|
|
128
128
|
const dispatch = useAppDispatch();
|
|
129
129
|
useEffect(() => {
|
|
130
|
-
|
|
130
|
+
void ensureAgentCatalog();
|
|
131
131
|
}, [dispatch]);
|
|
132
132
|
const agentIdFromUrl = (() => {
|
|
133
133
|
const pathMatch = pathname.match(/\/demos\/chat\/a\/([^/?]+)/);
|