@ai-matrx/agents 0.9.0 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +108 -0
- package/dist/catalog/index.cjs +51 -12
- package/dist/catalog/index.cjs.map +1 -1
- package/dist/catalog/index.d.cts +78 -4
- package/dist/catalog/index.d.ts +78 -4
- package/dist/catalog/index.js +51 -12
- package/dist/catalog/index.js.map +1 -1
- package/dist/catalog/native/index.cjs +51 -19
- package/dist/catalog/native/index.cjs.map +1 -1
- package/dist/catalog/native/index.d.cts +7 -2
- package/dist/catalog/native/index.d.ts +7 -2
- package/dist/catalog/native/index.js +51 -19
- package/dist/catalog/native/index.js.map +1 -1
- package/dist/catalog/react/index.cjs +55 -22
- package/dist/catalog/react/index.cjs.map +1 -1
- package/dist/catalog/react/index.d.cts +5 -0
- package/dist/catalog/react/index.d.ts +5 -0
- package/dist/catalog/react/index.js +55 -22
- package/dist/catalog/react/index.js.map +1 -1
- package/dist/{orchestra-BWJM2MWP.d.cts → orchestra-CID-rsu8.d.cts} +1 -1
- package/dist/{orchestra-BWJM2MWP.d.ts → orchestra-CID-rsu8.d.ts} +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,113 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.9.1 — 2026-09-08
|
|
4
|
+
|
|
5
|
+
**TWO SCREENS TOLD THE SAME USER TWO DIFFERENT TRUTHS. BOTH ARE FIXED HERE, IN
|
|
6
|
+
THE PACKAGE, AT THE CLASS.**
|
|
7
|
+
|
|
8
|
+
Independent final verification of the picker unification (2026-09-08, same
|
|
9
|
+
account signed in on both surfaces) found the tab strip, the counts, the
|
|
10
|
+
Mine/Shared/All order, the five sort options, the tri-state favourites control,
|
|
11
|
+
the 42 categories, the 871 tags and four tag-only searches identical between
|
|
12
|
+
`aimatrx.com/chat/new` and `workflows.aimatrx.com`. Two things were not.
|
|
13
|
+
|
|
14
|
+
### Consumer action: none
|
|
15
|
+
|
|
16
|
+
No export was removed, renamed or re-signed. Three symbols were ADDED —
|
|
17
|
+
`compareAgentIds`, `agentMatchesArchiveFilter`, `selectAgentTabCounts` — and the
|
|
18
|
+
web `AgentRow` gained a `data-testid` matching the native row's `testID`.
|
|
19
|
+
Every host adopts this by taking `latest`; there is nothing to change.
|
|
20
|
+
|
|
21
|
+
### Behavioural deltas (both deliberate, both were defects)
|
|
22
|
+
|
|
23
|
+
**F1 — every sort is now a TOTAL order, ending on `id` ASC.**
|
|
24
|
+
|
|
25
|
+
The Public tab diverged at index 10. 17 rows tied on
|
|
26
|
+
`updated_at = 2026-09-08T06:52:46.430326+00:00`, and the two hosts fetch the
|
|
27
|
+
same RPC through different transports:
|
|
28
|
+
|
|
29
|
+
| host | request | order of tied rows |
|
|
30
|
+
|---|---|---|
|
|
31
|
+
| matrx-frontend | `POST /rpc/agx_get_list_full` (one shot) | the RPC's own |
|
|
32
|
+
| workflow-studio | `…?order=id.asc&offset=0&limit=1000` (`readAllRows`) | id ASC |
|
|
33
|
+
|
|
34
|
+
Neither client was wrong about the ROWS. The sort was not total: each
|
|
35
|
+
comparator branch returned `0` for tied rows, so `Array.prototype.sort` left
|
|
36
|
+
them wherever the transport had put them. `sortFilteredAgents` and
|
|
37
|
+
`applyAgentSortComparator` now end on the same final key the database itself
|
|
38
|
+
ends on — `public.agx_get_list` is
|
|
39
|
+
`ORDER BY is_favorite DESC, updated_at DESC, id` — giving:
|
|
40
|
+
|
|
41
|
+
searching: score DESC -> server rank ASC -> sort key -> id ASC
|
|
42
|
+
not searching: favourites first (when asked) -> sort key -> id ASC
|
|
43
|
+
|
|
44
|
+
Comparison is a codepoint `<`/`>`, never `localeCompare`: Postgres orders
|
|
45
|
+
`uuid` by its raw bytes and a collator is free to fold case or ignore the
|
|
46
|
+
dashes, which would diverge from the server on exactly these ties. A sort key
|
|
47
|
+
that yields `NaN` (an unparseable timestamp) now collapses to the id key
|
|
48
|
+
instead of defeating it.
|
|
49
|
+
|
|
50
|
+
*What the frontend used to do on ties: whatever order the RPC page came back
|
|
51
|
+
in.* That was never a decision — it was the absence of one, and it happened to
|
|
52
|
+
look stable only until a second host fetched the same rows a different way. The
|
|
53
|
+
order is now DEFINED, is the server's own, and is a function of the rows alone.
|
|
54
|
+
|
|
55
|
+
**F5 — a tab badge counts exactly what the tab renders.**
|
|
56
|
+
|
|
57
|
+
The Mine badge said 416 while the list rendered 412 rows and the footer said
|
|
58
|
+
"412 agents": 4 owned and 2 shared ARCHIVED agents were counted by the badge
|
|
59
|
+
and (correctly) hidden by the list. One screen, three numbers, one of them
|
|
60
|
+
untrue about agents the user cannot see or reach from there. This is "a screen
|
|
61
|
+
never lies", so it is a fix and not a knob.
|
|
62
|
+
|
|
63
|
+
`selectAgentTabCounts(rows, archFilter)` is the new consumer-aware badge
|
|
64
|
+
source used by `useAgentListCore`, and the four plain aggregate counts
|
|
65
|
+
(`selectTotalUserAgentsCount`, `…Owned…`, `…Shared…`, `…Favorite…`) now honour
|
|
66
|
+
the same archive rule the list uses. Flip the archive filter and the badges
|
|
67
|
+
follow the list into the archive. `selectTotalBuiltinAgentsCount` is
|
|
68
|
+
deliberately unchanged: `filterBuiltinTypeAgents` applies no archive filter
|
|
69
|
+
(a builtin belongs to the platform and is never the user's to archive), so it
|
|
70
|
+
already counted exactly what it rendered.
|
|
71
|
+
|
|
72
|
+
### The proof
|
|
73
|
+
|
|
74
|
+
`catalog/__tests__/parity.test.ts`'s 66-row fixture had NO ties, which is why
|
|
75
|
+
293 green cases never saw F1. The new fixture does:
|
|
76
|
+
`catalog/__tests__/total-order-fixture.json` — 42 rows, every one on that exact
|
|
77
|
+
live `updated_at`, 26 of them also tied on `created_at`, with name and category
|
|
78
|
+
tie groups on top, ids deliberately uncorrelated with emission order.
|
|
79
|
+
|
|
80
|
+
`total-order-expected.json` is generated **from the RULE** by
|
|
81
|
+
`scripts/generate-total-order-fixture.mjs` — favourites -> key -> id ASC,
|
|
82
|
+
written out independently and importing nothing from `catalog/selectors.ts`.
|
|
83
|
+
Regenerating it by running the shipped comparator would have made the test a
|
|
84
|
+
mirror of the code; it measures the specification instead.
|
|
85
|
+
|
|
86
|
+
720 cases (tab x sort x favouritesFirst x archive x favourite x access) are
|
|
87
|
+
asserted three times over — kernel (`catalog/__tests__/total-order.test.ts`),
|
|
88
|
+
web shell (`catalog/react/total-order.test.tsx`) and native shell
|
|
89
|
+
(`catalog/native/__tests__/total-order.test.tsx`) — each reading the RENDERED
|
|
90
|
+
row ids, not the selector's return value.
|
|
91
|
+
|
|
92
|
+
Falsifiability, on every leg:
|
|
93
|
+
|
|
94
|
+
- the same rows are fed in four different input orders (identity, two seeded
|
|
95
|
+
shuffles, reversed) and the answer must be byte-identical — this is the live
|
|
96
|
+
defect, reproduced as a test;
|
|
97
|
+
- both shells mount the picker twice with the row array reversed and compare
|
|
98
|
+
screen to screen;
|
|
99
|
+
- deleting the id tiebreaker turns 4 of the 10 kernel tests red (verified
|
|
100
|
+
before shipping), and a key-only sort of the same fixture is asserted to
|
|
101
|
+
disagree with itself under reversal;
|
|
102
|
+
- the F5 legs assert the OLD counting rule produces a DIFFERENT number on this
|
|
103
|
+
fixture, so "badge == rows" cannot pass vacuously.
|
|
104
|
+
|
|
105
|
+
`parity.test.ts`'s count assertion now states the F5 delta explicitly — the
|
|
106
|
+
recorded matrx-frontend number minus the archived rows the list hides — rather
|
|
107
|
+
than reproducing a screen that lies. Its 293-case ordering matrix and the
|
|
108
|
+
native shell's 293-case matrix are UNCHANGED and still green: the old fixture
|
|
109
|
+
had no ties, so F1 moved nothing that was already defined.
|
|
110
|
+
|
|
3
111
|
## 0.9.0 — 2026-09-08
|
|
4
112
|
|
|
5
113
|
**THE ONE PICKER NOW RENDERS ON REACT NATIVE — `@ai-matrx/agents/catalog/native`.**
|
package/dist/catalog/index.cjs
CHANGED
|
@@ -34,10 +34,12 @@ __export(catalog_exports, {
|
|
|
34
34
|
_resetCatalogGlobalState: () => _resetCatalogGlobalState,
|
|
35
35
|
agentConsumerHasActiveFilters: () => agentConsumerHasActiveFilters,
|
|
36
36
|
agentListEmptyLabel: () => agentListEmptyLabel,
|
|
37
|
+
agentMatchesArchiveFilter: () => agentMatchesArchiveFilter,
|
|
37
38
|
agentMatchesSearch: () => agentMatchesSearch,
|
|
38
39
|
applyAgentSortComparator: () => applyAgentSortComparator,
|
|
39
40
|
asAgentId: () => asAgentId,
|
|
40
41
|
assertAgentCatalogSchema: () => assertAgentCatalogSchema,
|
|
42
|
+
compareAgentIds: () => compareAgentIds,
|
|
41
43
|
computeAgentSearchScore: () => computeAgentSearchScore,
|
|
42
44
|
createAgentCatalog: () => createAgentCatalog,
|
|
43
45
|
createMemoryStorage: () => createMemoryStorage,
|
|
@@ -73,6 +75,7 @@ __export(catalog_exports, {
|
|
|
73
75
|
readSingleAgentRow: () => readSingleAgentRow,
|
|
74
76
|
resolveDefaultRow: () => resolveDefaultRow,
|
|
75
77
|
searchAgentsOnServer: () => searchAgentsOnServer,
|
|
78
|
+
selectAgentTabCounts: () => selectAgentTabCounts,
|
|
76
79
|
selectAllAgentCategories: () => selectAllAgentCategories,
|
|
77
80
|
selectAllAgentTags: () => selectAllAgentTags,
|
|
78
81
|
selectAllSystemAgentCategories: () => selectAllSystemAgentCategories,
|
|
@@ -314,8 +317,8 @@ async function readSingleAgentRow(client, agentId) {
|
|
|
314
317
|
}
|
|
315
318
|
return null;
|
|
316
319
|
}
|
|
317
|
-
async function writeAgentFavorite(client, agentId,
|
|
318
|
-
const { error } = await client.schema("agent").from("definition").update({ is_favorite:
|
|
320
|
+
async function writeAgentFavorite(client, agentId, isFavorite2) {
|
|
321
|
+
const { error } = await client.schema("agent").from("definition").update({ is_favorite: isFavorite2 }).eq("id", agentId);
|
|
319
322
|
if (error) {
|
|
320
323
|
throw new AgentCatalogReadError(
|
|
321
324
|
"agent.definition.is_favorite",
|
|
@@ -893,7 +896,7 @@ function createAgentCatalog(config) {
|
|
|
893
896
|
mergeRows(result.rows);
|
|
894
897
|
return result.ids;
|
|
895
898
|
}
|
|
896
|
-
async function setFavorite(agentId,
|
|
899
|
+
async function setFavorite(agentId, isFavorite2) {
|
|
897
900
|
const existing = state.byId[agentId];
|
|
898
901
|
if (!existing) {
|
|
899
902
|
errorSink({
|
|
@@ -902,15 +905,15 @@ function createAgentCatalog(config) {
|
|
|
902
905
|
});
|
|
903
906
|
return;
|
|
904
907
|
}
|
|
905
|
-
mergeRows([{ ...existing, isFavorite }]);
|
|
908
|
+
mergeRows([{ ...existing, isFavorite: isFavorite2 }]);
|
|
906
909
|
try {
|
|
907
|
-
await writeAgentFavorite(client, agentId,
|
|
910
|
+
await writeAgentFavorite(client, agentId, isFavorite2);
|
|
908
911
|
} catch (e) {
|
|
909
912
|
mergeRows([existing]);
|
|
910
913
|
errorSink({
|
|
911
914
|
code: "favorite_write_failed",
|
|
912
915
|
message: `the favorite could not be saved: ${errorMessage(e)}`,
|
|
913
|
-
context: { agentId, isFavorite }
|
|
916
|
+
context: { agentId, isFavorite: isFavorite2 }
|
|
914
917
|
});
|
|
915
918
|
notifier?.({
|
|
916
919
|
level: "error",
|
|
@@ -1189,7 +1192,19 @@ function memoize3(fn) {
|
|
|
1189
1192
|
return last;
|
|
1190
1193
|
};
|
|
1191
1194
|
}
|
|
1195
|
+
function compareAgentIds(a, b) {
|
|
1196
|
+
const idA = a.id ?? "";
|
|
1197
|
+
const idB = b.id ?? "";
|
|
1198
|
+
if (idA < idB) return -1;
|
|
1199
|
+
if (idA > idB) return 1;
|
|
1200
|
+
return 0;
|
|
1201
|
+
}
|
|
1192
1202
|
function applyAgentSortComparator(a, b, sortBy) {
|
|
1203
|
+
const primary = compareAgentSortKey(a, b, sortBy);
|
|
1204
|
+
if (!Number.isFinite(primary) || primary === 0) return compareAgentIds(a, b);
|
|
1205
|
+
return primary;
|
|
1206
|
+
}
|
|
1207
|
+
function compareAgentSortKey(a, b, sortBy) {
|
|
1193
1208
|
switch (sortBy) {
|
|
1194
1209
|
case "name-asc":
|
|
1195
1210
|
return (a.name ?? "").localeCompare(b.name ?? "");
|
|
@@ -1437,21 +1452,45 @@ var makeSelectFilteredBuiltinAgentsCount = () => {
|
|
|
1437
1452
|
function agentConsumerHasActiveFilters(consumer, defaults) {
|
|
1438
1453
|
return consumer.tab !== defaults.tab || consumer.sortBy !== defaults.sortBy || consumer.searchTerm !== "" || consumer.includedCats.length > 0 || consumer.includedTags.length > 0 || consumer.favFilter !== defaults.favFilter || consumer.archFilter !== defaults.archFilter || consumer.accessFilter !== defaults.accessFilter || consumer.favoritesFirst !== defaults.favoritesFirst;
|
|
1439
1454
|
}
|
|
1455
|
+
function agentMatchesArchiveFilter(agent, archFilter) {
|
|
1456
|
+
if (archFilter === "active") return !agent.isArchived;
|
|
1457
|
+
if (archFilter === "archived") return Boolean(agent.isArchived);
|
|
1458
|
+
return true;
|
|
1459
|
+
}
|
|
1460
|
+
function countUserRows(agents, archFilter, predicate) {
|
|
1461
|
+
let n = 0;
|
|
1462
|
+
for (const a of agents) {
|
|
1463
|
+
if (a.agentType !== "user") continue;
|
|
1464
|
+
if (!agentMatchesArchiveFilter(a, archFilter)) continue;
|
|
1465
|
+
if (predicate(a)) n += 1;
|
|
1466
|
+
}
|
|
1467
|
+
return n;
|
|
1468
|
+
}
|
|
1469
|
+
var isOwned = (a) => a.isOwner === true;
|
|
1470
|
+
var isShared = (a) => a.isOwner === false && a.accessLevel != null;
|
|
1471
|
+
var isAny = () => true;
|
|
1472
|
+
var isFavorite = (a) => Boolean(a.isFavorite);
|
|
1473
|
+
var selectAgentTabCounts = memoize2(
|
|
1474
|
+
(agents, archFilter) => ({
|
|
1475
|
+
mine: countUserRows(agents, archFilter, isOwned),
|
|
1476
|
+
shared: countUserRows(agents, archFilter, isShared),
|
|
1477
|
+
all: countUserRows(agents, archFilter, isAny),
|
|
1478
|
+
system: selectBuiltinTypeAgents(agents).length
|
|
1479
|
+
})
|
|
1480
|
+
);
|
|
1440
1481
|
var selectTotalUserAgentsCount = memoize1(
|
|
1441
|
-
(agents) =>
|
|
1482
|
+
(agents) => countUserRows(agents, "active", isAny)
|
|
1442
1483
|
);
|
|
1443
1484
|
var selectTotalOwnedAgentsCount = memoize1(
|
|
1444
|
-
(agents) =>
|
|
1485
|
+
(agents) => countUserRows(agents, "active", isOwned)
|
|
1445
1486
|
);
|
|
1446
1487
|
var selectTotalSharedAgentsCount = memoize1(
|
|
1447
|
-
(agents) =>
|
|
1448
|
-
(a) => a.isOwner === false && a.accessLevel != null
|
|
1449
|
-
).length
|
|
1488
|
+
(agents) => countUserRows(agents, "active", isShared)
|
|
1450
1489
|
);
|
|
1451
1490
|
var selectTotalBuiltinAgentsCount = memoize1(
|
|
1452
1491
|
(agents) => selectBuiltinTypeAgents(agents).length
|
|
1453
1492
|
);
|
|
1454
1493
|
var selectTotalFavoriteAgentsCount = memoize1(
|
|
1455
|
-
(agents) =>
|
|
1494
|
+
(agents) => countUserRows(agents, "active", isFavorite)
|
|
1456
1495
|
);
|
|
1457
1496
|
//# sourceMappingURL=index.cjs.map
|