@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
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# @ai-matrx/chat
|
|
2
2
|
|
|
3
|
+
## 0.3.24 — 2026-10-07
|
|
4
|
+
### Agent identity and lists read the ONE agent catalog; the run tier reads the core store (agent core B2, phase A)
|
|
5
|
+
|
|
6
|
+
- New `agents/identity/agent-identity`: `useAgentView` / `readAgentView` / `agentViewOf` (the record completed from the catalog row — derived, no copy), `useAgentName`, `useAgentDescription`, `useAgentIdentity`, `useAgentSummaryRow` (the record when it has read the field — run tier, builder edit — else the catalog row), `readAgentName` / `readAgentDescription` (non-reactive), `ensureAgentCatalog`, `isAgentCatalogStale`.
|
|
7
|
+
- New `agents/identity/agent-catalog-lists`: `useCatalogAgents`, `useAgentsById`, `useBuiltinAgents`, `useActiveAgents`, `useOwnedAgents`, `useSharedWithMeAgents`, `useAgentLineageIndex`, `useAgentCatalogStatus` / `useAgentCatalogError` / `useAgentCatalogLoad`, `readCatalogAgents` / `readBuiltinAgents` / `readOwnedAgents`, `buildAgentLineageIndex` — the catalog-backed replacements for the `agentDefinition` list selectors.
|
|
8
|
+
- New `agents/redux/agent-filter/useAgentIdsForFilter` + pure `filterAgentsForFilter`.
|
|
9
|
+
- `agents/identity/run-tier-store`: `getRunTierStore()` binds `@ai-matrx/agents/runtime` `createRunTierStore`; `fetchAgentRunTier`, `fetchAgentRunControls`, `fetchAgentAccessLevel` read through it (same errors: `agentNotReadableError`, `ConnectTimeoutError`, pg errors). `fetchSharedAgents` / `fetchSharedAgentsForChat` are gone (no caller; `getRunTierStore().loadSharedWithMe()` / `.loadSharedForChat()`). `AgentRunTier` / `AgentRunCounts` are the core's row types, narrowed.
|
|
10
|
+
- Every chat surface that showed an agent's name reads the catalog first (run header, run window, run controls, composer, runner page, mobile name, picker sheet, history buckets, output-contract errors); the picker sheet no longer refuses an agent the run record has not loaded.
|
|
11
|
+
- DEPRECATED, removed in the next release: `fetchAgentsList`, `fetchAgentsListFull`, `initializeChatAgents`, `searchAgentsServer`, `ensureAgentIdentity`, `overlayAgentFavoritesThunk`, `isChatListStale` (now `agents/redux/agent-definition/list-mirror`), `AgentListHydrator`, the list selectors (`selectAllAgentsArray`, `selectLiveAgents`, `selectBuiltinAgents`, `selectActiveAgents`, `selectOwnedAgents`, `selectSharedWithMeAgents`, `selectAgentLineageIndex`, `selectAgentsSliceStatus`, `selectAgentsSliceError`, …), `selectAgentName`, `selectAgentDescription`, `makeSelectAgentsForFilter` / `makeSelectAgentIdsForFilter`.
|
|
12
|
+
- Consumer action: repoint to the hooks above (requires `@ai-matrx/agents` ≥ 0.51.0).
|
|
13
|
+
|
|
3
14
|
## 0.3.23 — 2026-10-07
|
|
4
15
|
### The working document reaches the agent again
|
|
5
16
|
|
|
@@ -54,7 +54,6 @@ import {
|
|
|
54
54
|
} from "../../redux/execution-system/messages/messages.selectors.js";
|
|
55
55
|
import { selectConversationTitle } from "../../redux/execution-system/conversations/conversations.selectors.js";
|
|
56
56
|
import { selectIsStreaming } from "../../redux/execution-system/selectors/aggregate.selectors.js";
|
|
57
|
-
import { selectAgentName } from "../../redux/agent-definition/selectors.js";
|
|
58
57
|
import { selectCurrentSettings } from "../../redux/execution-system/instance-model-overrides/instance-model-overrides.selectors.js";
|
|
59
58
|
import { selectInstanceResources } from "../../redux/execution-system/instance-resources/instance-resources.selectors.js";
|
|
60
59
|
import { selectResolvedVariables } from "../../redux/execution-system/instance-variable-values/instance-variable-values.selectors.js";
|
|
@@ -63,6 +62,7 @@ import {
|
|
|
63
62
|
selectAttachedScratchpadIds,
|
|
64
63
|
selectWorkingDocEntry
|
|
65
64
|
} from "../../redux/execution-system/instance-working-document/instance-working-document.selectors.js";
|
|
65
|
+
import { readAgentName } from "../../identity/agent-identity.js";
|
|
66
66
|
function promptForkOutcomeLazily(args) {
|
|
67
67
|
void import("../messages-display/message-options/promptForkOutcome.js").then(({ promptForkOutcome }) => promptForkOutcome(args));
|
|
68
68
|
}
|
|
@@ -161,7 +161,7 @@ function ChatConversationSurface({
|
|
|
161
161
|
} : null;
|
|
162
162
|
const conversationStatus = state.conversations?.byConversationId?.[conversationId]?.status ?? null;
|
|
163
163
|
const isStreamingNow2 = selectIsStreaming(conversationId)(state);
|
|
164
|
-
const agentName =
|
|
164
|
+
const agentName = readAgentName(state, agentId) ?? null;
|
|
165
165
|
const conversationTitle = selectConversationTitle(conversationId)(state);
|
|
166
166
|
const conversation = transcript ? buildChatConversationRecord({
|
|
167
167
|
id: conversationId,
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useRouter } from "../../../host/navigation.js";
|
|
4
|
-
import {
|
|
5
|
-
import { selectAgentName } from "../../redux/agent-definition/selectors.js";
|
|
4
|
+
import { useAppStore } from "../../../store/hooks.js";
|
|
6
5
|
import { AgentListDropdown } from "@ai-matrx/agents/catalog/react";
|
|
7
6
|
import { ActiveContextLensChip } from "../../../context/sources/scopes.js";
|
|
8
7
|
import { ComposerModeSwitch } from "../inputs/smart-input/composer/ComposerModeSwitch.js";
|
|
@@ -15,6 +14,7 @@ import {
|
|
|
15
14
|
stageChatAgentSwitch
|
|
16
15
|
} from "./begin-fresh-chat.js";
|
|
17
16
|
import { RouteHeader } from "../../../host/chrome.js";
|
|
17
|
+
import { useAgentName } from "../../identity/agent-identity.js";
|
|
18
18
|
const defaultAgentHref = (agentId) => `/chat/a/${encodeURIComponent(agentId)}`;
|
|
19
19
|
function ChatRunHeader({
|
|
20
20
|
activeAgentId,
|
|
@@ -25,9 +25,7 @@ function ChatRunHeader({
|
|
|
25
25
|
}) {
|
|
26
26
|
const router = useRouter();
|
|
27
27
|
const store = useAppStore();
|
|
28
|
-
const liveName =
|
|
29
|
-
(state) => activeAgentId ? selectAgentName(state, activeAgentId) : void 0
|
|
30
|
-
);
|
|
28
|
+
const liveName = useAgentName(activeAgentId);
|
|
31
29
|
const label = liveName?.trim() || initialAgentName?.trim() || "Select an agent";
|
|
32
30
|
const handleAgentSelect = (id) => {
|
|
33
31
|
if (id === activeAgentId) return;
|
|
@@ -10,10 +10,10 @@ import {
|
|
|
10
10
|
useAgentConsumer
|
|
11
11
|
} from "@ai-matrx/agents/catalog/react";
|
|
12
12
|
import { makeSelectFilteredAgents } from "@ai-matrx/agents/catalog";
|
|
13
|
-
import { initializeChatAgents } from "../../redux/agent-definition/thunks.js";
|
|
14
13
|
import { useAppStore } from "../../../store/hooks.js";
|
|
15
14
|
import { stageChatAgentSwitch } from "./begin-fresh-chat.js";
|
|
16
15
|
import { Button, DisclosureHeader } from "@ai-matrx/design-system/controls";
|
|
16
|
+
import { ensureAgentCatalog } from "../../identity/agent-identity.js";
|
|
17
17
|
const CONSUMER_ID = "chat-sidebar-pinned";
|
|
18
18
|
const PINNED_COLLAPSED_LIMIT = 5;
|
|
19
19
|
const selectPinnedAgents = makeSelectFilteredAgents();
|
|
@@ -28,7 +28,7 @@ function PinnedAgentsSection({
|
|
|
28
28
|
const store = useAppStore();
|
|
29
29
|
const consumer = useAgentConsumer(CONSUMER_ID);
|
|
30
30
|
useEffect(() => {
|
|
31
|
-
|
|
31
|
+
void ensureAgentCatalog();
|
|
32
32
|
}, [dispatch]);
|
|
33
33
|
useEffect(() => {
|
|
34
34
|
if (consumer.favFilter !== "yes") consumer.setFavFilter("yes");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
-
import {
|
|
3
|
+
import { useState } from "react";
|
|
4
4
|
import { DiffViewer } from "@ai-matrx/diff/react";
|
|
5
5
|
import { AlertTriangle, ChevronDown, GitCompareArrows, MessageSquareText, RefreshCw } from "lucide-react";
|
|
6
6
|
import { AgentListDropdown } from "@ai-matrx/agents/catalog/react";
|
|
@@ -12,9 +12,7 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from "../../../ui/tabs.js";
|
|
|
12
12
|
import { CopyButtons } from "../../../host/ui-slots.js";
|
|
13
13
|
import { RichContent } from "../../../host/ui-slots.js";
|
|
14
14
|
import { SystemItemsLine } from "./SystemItemsLine.js";
|
|
15
|
-
import { useAppDispatch
|
|
16
|
-
import { selectAllAgents } from "../../redux/agent-definition/selectors.js";
|
|
17
|
-
import { fetchAgentsList } from "../../redux/agent-definition/thunks.js";
|
|
15
|
+
import { useAppDispatch } from "../../../store/hooks.js";
|
|
18
16
|
import { callApi } from "../../../host/server/call-api.js";
|
|
19
17
|
import { resolveRunWait } from "../../../host/server/run-wait.js";
|
|
20
18
|
import { peekSelectedOrganizationId } from "../../../host/server/organization-admission.js";
|
|
@@ -26,6 +24,7 @@ import { AGENT_ICON } from "@ai-matrx/icons/domain";
|
|
|
26
24
|
import { formatCount } from "@ai-matrx/kit/format";
|
|
27
25
|
import { getUserId } from "../../../host/identity.js";
|
|
28
26
|
import { humanizeIdentifier } from "@ai-matrx/kit/text-case";
|
|
27
|
+
import { useAgentName } from "../../identity/agent-identity.js";
|
|
29
28
|
const CLASS_LOOK = {
|
|
30
29
|
defect: {
|
|
31
30
|
label: "Defect",
|
|
@@ -409,12 +408,7 @@ function AnswerAgentPicker({
|
|
|
409
408
|
agentId,
|
|
410
409
|
onAgentChange
|
|
411
410
|
}) {
|
|
412
|
-
const
|
|
413
|
-
const agents = useAppSelector(selectAllAgents);
|
|
414
|
-
useEffect(() => {
|
|
415
|
-
void dispatch(fetchAgentsList());
|
|
416
|
-
}, [dispatch]);
|
|
417
|
-
const chosenName = agentId ? agents?.[agentId]?.name ?? null : null;
|
|
411
|
+
const chosenName = useAgentName(agentId) ?? null;
|
|
418
412
|
return /* @__PURE__ */ jsx("div", { "data-answer-agent": agentId ?? "", children: /* @__PURE__ */ jsx(
|
|
419
413
|
AgentListDropdown,
|
|
420
414
|
{
|
|
@@ -441,8 +435,7 @@ function AnswerBoth({
|
|
|
441
435
|
const [running, setRunning] = useState(false);
|
|
442
436
|
const [error, setError] = useState(null);
|
|
443
437
|
const [result, setResult] = useState(null);
|
|
444
|
-
const
|
|
445
|
-
const agentName = agentId ? agents?.[agentId]?.name ?? null : null;
|
|
438
|
+
const agentName = useAgentName(agentId) ?? null;
|
|
446
439
|
usePageCaptureContribution(
|
|
447
440
|
"context-compare:answer-both",
|
|
448
441
|
() => [
|
|
@@ -6,8 +6,7 @@ import { useAppDispatch, useAppSelector } from "../../../../../store/hooks.js";
|
|
|
6
6
|
import { useMandate } from "../../../../../mandates/useMandate.js";
|
|
7
7
|
import { selectAgentIdFromInstance } from "../../../../redux/execution-system/conversations/conversations.selectors.js";
|
|
8
8
|
import {
|
|
9
|
-
selectAgentModelId
|
|
10
|
-
selectAgentName
|
|
9
|
+
selectAgentModelId
|
|
11
10
|
} from "../../../../redux/agent-definition/selectors.js";
|
|
12
11
|
import { selectInstanceOverrideState } from "../../../../redux/execution-system/instance-model-overrides/instance-model-overrides.selectors.js";
|
|
13
12
|
import {
|
|
@@ -17,7 +16,7 @@ import {
|
|
|
17
16
|
import { useModelOptions } from "../../../../../host/ui-slots.js";
|
|
18
17
|
import { useModelClassLabels } from "../../../../../host/model-class.js";
|
|
19
18
|
import { useEffectiveClassPin } from "../../../../redux/execution-system/instance-model-overrides/useEffectiveClassPin.js";
|
|
20
|
-
import {
|
|
19
|
+
import { ensureAgentCatalog, useAgentName } from "../../../../identity/agent-identity.js";
|
|
21
20
|
const CHAT_AGENT_TAG = "chat-agent";
|
|
22
21
|
function isPresetRow(row) {
|
|
23
22
|
return !row.isArchived && row.isActive !== false && row.tags.includes(CHAT_AGENT_TAG);
|
|
@@ -41,10 +40,10 @@ function useComposerAgent(conversationId) {
|
|
|
41
40
|
const dispatch = useAppDispatch();
|
|
42
41
|
useModelOptions();
|
|
43
42
|
useEffect(() => {
|
|
44
|
-
|
|
43
|
+
void ensureAgentCatalog();
|
|
45
44
|
}, [dispatch]);
|
|
46
45
|
const agentId = useAppSelector(selectAgentIdFromInstance(conversationId)) ?? null;
|
|
47
|
-
const agentName =
|
|
46
|
+
const agentName = useAgentName(agentId) ?? null;
|
|
48
47
|
const effectiveModelId = useEffectiveModelId(conversationId);
|
|
49
48
|
useModelClassLabels();
|
|
50
49
|
const classPins = useEffectiveClassPin(conversationId);
|
|
@@ -6,8 +6,7 @@ import { useSearchParams } from "../../../host/navigation.js";
|
|
|
6
6
|
import { useAppDispatch, useAppSelector, useAppStore } from "../../../store/hooks.js";
|
|
7
7
|
import { fetchAgentExecutionMinimal } from "../../redux/agent-definition/thunks.js";
|
|
8
8
|
import {
|
|
9
|
-
selectAgentExecutionPayload
|
|
10
|
-
selectAgentName
|
|
9
|
+
selectAgentExecutionPayload
|
|
11
10
|
} from "../../redux/agent-definition/selectors.js";
|
|
12
11
|
import { selectAuthReady } from "../../../host/identity.js";
|
|
13
12
|
import { useAgentLauncher } from "../../hooks/useAgentLauncher.js";
|
|
@@ -42,6 +41,7 @@ import { selectInstanceVariableDefinitions } from "../../redux/execution-system/
|
|
|
42
41
|
import { useAgentRunSurfaceScope } from "../../hooks/useAgentRunSurfaceScope.js";
|
|
43
42
|
import { createAgentRunVariableValuesHandler } from "./agent-run-variable-write.js";
|
|
44
43
|
import { ErrorAlchemyMenu } from "../../../host/ui-slots.js";
|
|
44
|
+
import { useAgentName } from "../../identity/agent-identity.js";
|
|
45
45
|
const RUN_INITIAL_MESSAGE_LIMIT = 12;
|
|
46
46
|
function AgentRunnerPage({
|
|
47
47
|
agentId,
|
|
@@ -128,7 +128,7 @@ function AgentRunnerPage({
|
|
|
128
128
|
conversationId: conversationIdFromUrl ?? conversationId ?? void 0,
|
|
129
129
|
sourceFeature
|
|
130
130
|
});
|
|
131
|
-
const agentName =
|
|
131
|
+
const agentName = useAgentName(agentId);
|
|
132
132
|
const authReady = useAppSelector(selectAuthReady);
|
|
133
133
|
const lastSyncedUrl = useRef(null);
|
|
134
134
|
useEffect(() => {
|
|
@@ -9,14 +9,18 @@ import {
|
|
|
9
9
|
selectModelLabelWithClass
|
|
10
10
|
} from "../model-registry/modelRegistrySlice.js";
|
|
11
11
|
import { useModelClassLabels } from "../../host/model-class.js";
|
|
12
|
+
import { useAgentSummaryRow } from "../identity/agent-identity.js";
|
|
12
13
|
function useAgentModelLabel(agentId) {
|
|
13
14
|
useModelClassLabels();
|
|
14
|
-
const
|
|
15
|
+
const summary = useAgentSummaryRow(agentId);
|
|
16
|
+
const ownModelId = useAppSelector(
|
|
15
17
|
(state) => agentId ? selectAgentModelId(state, agentId) : null
|
|
16
18
|
);
|
|
17
|
-
const
|
|
19
|
+
const ownOfferingId = useAppSelector(
|
|
18
20
|
(state) => agentId ? selectAgentOfferingPin(state, agentId) : void 0
|
|
19
21
|
);
|
|
22
|
+
const modelId = ownModelId ?? summary?.modelId ?? null;
|
|
23
|
+
const offeringId = ownOfferingId !== void 0 ? ownOfferingId : summary?.offeringId;
|
|
20
24
|
const label = useAppSelector(
|
|
21
25
|
(state) => offeringId === void 0 ? selectModelLabelById(state, modelId) : selectModelLabelWithClass(state, modelId, offeringId)
|
|
22
26
|
);
|
|
@@ -4,9 +4,7 @@ import { createAgentRunScope } from "../../surfaces/manifests/agent-run.manifest
|
|
|
4
4
|
import { extractAgentSystemInstruction } from "../utils/agent-system-instruction.js";
|
|
5
5
|
import {
|
|
6
6
|
selectAgentDefinition,
|
|
7
|
-
selectAgentDescription,
|
|
8
7
|
selectAgentModelId,
|
|
9
|
-
selectAgentName,
|
|
10
8
|
selectAgentSystemMessage,
|
|
11
9
|
selectAgentTools,
|
|
12
10
|
selectAgentVariableDefinitions,
|
|
@@ -31,6 +29,7 @@ import {
|
|
|
31
29
|
selectLatestError,
|
|
32
30
|
selectLatestToolLifecycles
|
|
33
31
|
} from "../redux/execution-system/selectors/aggregate.selectors.js";
|
|
32
|
+
import { readAgentDescription, readAgentName } from "../identity/agent-identity.js";
|
|
34
33
|
function useAgentRunSurfaceScope({
|
|
35
34
|
agentId,
|
|
36
35
|
conversationId,
|
|
@@ -42,8 +41,8 @@ function useAgentRunSurfaceScope({
|
|
|
42
41
|
const definition = selectAgentDefinition(state, agentId);
|
|
43
42
|
const agentScope = {
|
|
44
43
|
agent_id: agentId,
|
|
45
|
-
agent_name:
|
|
46
|
-
agent_description:
|
|
44
|
+
agent_name: readAgentName(state, agentId) ?? void 0,
|
|
45
|
+
agent_description: readAgentDescription(state, agentId) ?? void 0,
|
|
47
46
|
agent_version: selectAgentVersion(state, agentId) ?? void 0,
|
|
48
47
|
agent_system_instruction: extractAgentSystemInstruction(
|
|
49
48
|
selectAgentSystemMessage(state, agentId)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { AgentCatalogState, AgentSummary } from "@ai-matrx/agents/catalog";
|
|
2
|
+
/** Every agent the person can see (owned, shared, organization, system). */
|
|
3
|
+
export declare function useCatalogAgents(): AgentSummary[];
|
|
4
|
+
export declare function useAgentsById(): Record<string, AgentSummary>;
|
|
5
|
+
export declare const isBuiltinAgent: (a: AgentSummary) => boolean;
|
|
6
|
+
export declare const isActiveAgent: (a: AgentSummary) => boolean;
|
|
7
|
+
export declare const isOwnedAgent: (a: AgentSummary) => boolean;
|
|
8
|
+
export declare const isSharedWithMeAgent: (a: AgentSummary) => boolean;
|
|
9
|
+
export declare function useBuiltinAgents(): AgentSummary[];
|
|
10
|
+
export declare function useActiveAgents(): AgentSummary[];
|
|
11
|
+
export declare function useOwnedAgents(): AgentSummary[];
|
|
12
|
+
export declare function useSharedWithMeAgents(): AgentSummary[];
|
|
13
|
+
export interface AgentCatalogLoad {
|
|
14
|
+
status: AgentCatalogState["status"];
|
|
15
|
+
error: string | null;
|
|
16
|
+
loading: boolean;
|
|
17
|
+
reload: () => Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
/** The catalog's load state, plus a forced reload for retry buttons. */
|
|
20
|
+
export declare function useAgentCatalogLoad(): AgentCatalogLoad;
|
|
21
|
+
/** The catalog's load status (`idle` | `loading` | `succeeded` | `failed`) — was `selectAgentsSliceStatus`. */
|
|
22
|
+
export declare function useAgentCatalogStatus(): AgentCatalogState["status"];
|
|
23
|
+
/** The catalog's last load error — was `selectAgentsSliceError`. */
|
|
24
|
+
export declare function useAgentCatalogError(): string | null;
|
|
25
|
+
export declare function readCatalogAgents(): AgentSummary[];
|
|
26
|
+
export declare function readBuiltinAgents(): AgentSummary[];
|
|
27
|
+
export declare function readOwnedAgents(): AgentSummary[];
|
|
28
|
+
export interface AgentLineageRef {
|
|
29
|
+
id: string;
|
|
30
|
+
name: string;
|
|
31
|
+
agentType: string | null;
|
|
32
|
+
isSystem: boolean;
|
|
33
|
+
}
|
|
34
|
+
export interface AgentLineage {
|
|
35
|
+
/** The agent this one was copied FROM, when visible. */
|
|
36
|
+
parent: AgentLineageRef | null;
|
|
37
|
+
/** Agents copied FROM this one. */
|
|
38
|
+
children: AgentLineageRef[];
|
|
39
|
+
/** The system (builtin) agent in this agent's immediate lineage — always rendered WITH a door. */
|
|
40
|
+
systemTwin: AgentLineageRef | null;
|
|
41
|
+
}
|
|
42
|
+
export declare const EMPTY_LINEAGE: AgentLineage;
|
|
43
|
+
/** agentId → lineage for every agent in the catalog, built once per catalog change. */
|
|
44
|
+
export declare function buildAgentLineageIndex(agents: readonly AgentSummary[]): Record<string, AgentLineage>;
|
|
45
|
+
export declare function useAgentLineageIndex(): Record<string, AgentLineage>;
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useEffect, useMemo, useSyncExternalStore } from "react";
|
|
3
|
+
import { getAgentCatalog } from "../../host/ui-slots.js";
|
|
4
|
+
import { ensureAgentCatalog } from "./agent-identity.js";
|
|
5
|
+
const EMPTY_ROWS = [];
|
|
6
|
+
const EMPTY_BY_ID = {};
|
|
7
|
+
const noopSubscribe = () => () => void 0;
|
|
8
|
+
function catalogOrNull() {
|
|
9
|
+
try {
|
|
10
|
+
return getAgentCatalog();
|
|
11
|
+
} catch {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function useCatalogSelector(select, fallback) {
|
|
16
|
+
const catalog = catalogOrNull();
|
|
17
|
+
const value = useSyncExternalStore(
|
|
18
|
+
catalog ? catalog.subscribe : noopSubscribe,
|
|
19
|
+
() => catalog ? select(catalog.getState()) : fallback,
|
|
20
|
+
() => catalog ? select(catalog.getState()) : fallback
|
|
21
|
+
);
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
void ensureAgentCatalog();
|
|
24
|
+
}, []);
|
|
25
|
+
return value;
|
|
26
|
+
}
|
|
27
|
+
function useCatalogAgents() {
|
|
28
|
+
return useCatalogSelector((s) => s.rows, EMPTY_ROWS);
|
|
29
|
+
}
|
|
30
|
+
function useAgentsById() {
|
|
31
|
+
return useCatalogSelector((s) => s.byId, EMPTY_BY_ID);
|
|
32
|
+
}
|
|
33
|
+
const isBuiltinAgent = (a) => a.agentType === "builtin";
|
|
34
|
+
const isActiveAgent = (a) => a.isActive && !a.isArchived;
|
|
35
|
+
const isOwnedAgent = (a) => a.isOwner === true;
|
|
36
|
+
const isSharedWithMeAgent = (a) => a.isOwner === false && a.accessLevel != null;
|
|
37
|
+
function useFiltered(pred) {
|
|
38
|
+
const rows = useCatalogAgents();
|
|
39
|
+
return useMemo(() => rows.filter(pred), [rows, pred]);
|
|
40
|
+
}
|
|
41
|
+
function useBuiltinAgents() {
|
|
42
|
+
return useFiltered(isBuiltinAgent);
|
|
43
|
+
}
|
|
44
|
+
function useActiveAgents() {
|
|
45
|
+
return useFiltered(isActiveAgent);
|
|
46
|
+
}
|
|
47
|
+
function useOwnedAgents() {
|
|
48
|
+
return useFiltered(isOwnedAgent);
|
|
49
|
+
}
|
|
50
|
+
function useSharedWithMeAgents() {
|
|
51
|
+
return useFiltered(isSharedWithMeAgent);
|
|
52
|
+
}
|
|
53
|
+
function useAgentCatalogLoad() {
|
|
54
|
+
const status = useCatalogSelector((s) => s.status, "idle");
|
|
55
|
+
const error = useCatalogSelector((s) => s.error, null);
|
|
56
|
+
return {
|
|
57
|
+
status,
|
|
58
|
+
error,
|
|
59
|
+
loading: status === "loading",
|
|
60
|
+
reload: () => ensureAgentCatalog({ force: true })
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function useAgentCatalogStatus() {
|
|
64
|
+
return useCatalogSelector((s) => s.status, "idle");
|
|
65
|
+
}
|
|
66
|
+
function useAgentCatalogError() {
|
|
67
|
+
return useCatalogSelector((s) => s.error, null);
|
|
68
|
+
}
|
|
69
|
+
function readCatalogAgents() {
|
|
70
|
+
return catalogOrNull()?.getState().rows ?? EMPTY_ROWS;
|
|
71
|
+
}
|
|
72
|
+
function readBuiltinAgents() {
|
|
73
|
+
return readCatalogAgents().filter(isBuiltinAgent);
|
|
74
|
+
}
|
|
75
|
+
function readOwnedAgents() {
|
|
76
|
+
return readCatalogAgents().filter(isOwnedAgent);
|
|
77
|
+
}
|
|
78
|
+
const EMPTY_LINEAGE = { parent: null, children: [], systemTwin: null };
|
|
79
|
+
function toLineageRef(a) {
|
|
80
|
+
return { id: a.id, name: a.name ?? a.id, agentType: a.agentType ?? null, isSystem: a.agentType === "builtin" };
|
|
81
|
+
}
|
|
82
|
+
function buildAgentLineageIndex(agents) {
|
|
83
|
+
const byId = new Map(agents.map((a) => [a.id, a]));
|
|
84
|
+
const childrenByParent = /* @__PURE__ */ new Map();
|
|
85
|
+
for (const a of agents) {
|
|
86
|
+
if (!a.sourceAgentId) continue;
|
|
87
|
+
const bucket = childrenByParent.get(a.sourceAgentId);
|
|
88
|
+
if (bucket) bucket.push(a);
|
|
89
|
+
else childrenByParent.set(a.sourceAgentId, [a]);
|
|
90
|
+
}
|
|
91
|
+
const index = {};
|
|
92
|
+
for (const a of agents) {
|
|
93
|
+
const parentRow = a.sourceAgentId ? byId.get(a.sourceAgentId) ?? null : null;
|
|
94
|
+
const parent = parentRow ? toLineageRef(parentRow) : null;
|
|
95
|
+
const children = (childrenByParent.get(a.id) ?? []).map(toLineageRef);
|
|
96
|
+
index[a.id] = {
|
|
97
|
+
parent,
|
|
98
|
+
children,
|
|
99
|
+
systemTwin: parent?.isSystem === true ? parent : children.find((c) => c.isSystem) ?? null
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
return index;
|
|
103
|
+
}
|
|
104
|
+
function useAgentLineageIndex() {
|
|
105
|
+
const rows = useCatalogAgents();
|
|
106
|
+
return useMemo(() => buildAgentLineageIndex(rows), [rows]);
|
|
107
|
+
}
|
|
108
|
+
export {
|
|
109
|
+
EMPTY_LINEAGE,
|
|
110
|
+
buildAgentLineageIndex,
|
|
111
|
+
isActiveAgent,
|
|
112
|
+
isBuiltinAgent,
|
|
113
|
+
isOwnedAgent,
|
|
114
|
+
isSharedWithMeAgent,
|
|
115
|
+
readBuiltinAgents,
|
|
116
|
+
readCatalogAgents,
|
|
117
|
+
readOwnedAgents,
|
|
118
|
+
useActiveAgents,
|
|
119
|
+
useAgentCatalogError,
|
|
120
|
+
useAgentCatalogLoad,
|
|
121
|
+
useAgentCatalogStatus,
|
|
122
|
+
useAgentLineageIndex,
|
|
123
|
+
useAgentsById,
|
|
124
|
+
useBuiltinAgents,
|
|
125
|
+
useCatalogAgents,
|
|
126
|
+
useOwnedAgents,
|
|
127
|
+
useSharedWithMeAgents
|
|
128
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { AgentSummary } from "@ai-matrx/agents/catalog";
|
|
2
|
+
import type { ChatRootState } from "../../store/root-state.js";
|
|
3
|
+
import type { AgentDefinitionRecord } from "../types/agent-definition.types.js";
|
|
4
|
+
/** Load the agent catalog (its own TTL + in-flight dedupe make this safe on every mount). */
|
|
5
|
+
export declare function ensureAgentCatalog(options?: {
|
|
6
|
+
force?: boolean;
|
|
7
|
+
}): Promise<void>;
|
|
8
|
+
/** True when the catalog's last load is older than the tab-restore threshold. */
|
|
9
|
+
export declare function isAgentCatalogStale(): boolean;
|
|
10
|
+
export interface AgentIdentity {
|
|
11
|
+
name: string | undefined;
|
|
12
|
+
description: string | null;
|
|
13
|
+
/** The catalog row, when the list carries this agent. */
|
|
14
|
+
summary: AgentSummary | undefined;
|
|
15
|
+
}
|
|
16
|
+
/** One agent's catalog row, loading the catalog when it is missing. */
|
|
17
|
+
export declare function useAgentSummaryRow(agentId: string | null | undefined): AgentSummary | undefined;
|
|
18
|
+
type MaybeRecord = AgentDefinitionRecord | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* The agent's record completed from its catalog row: every field the record has READ wins; the
|
|
21
|
+
* list fields it has not read (name, description, category, tags, star, access, lineage, dates)
|
|
22
|
+
* come from the catalog. Derived on read — the catalog stays the one holder of list data.
|
|
23
|
+
*/
|
|
24
|
+
export declare function agentViewOf(record: MaybeRecord, summary: AgentSummary | undefined): MaybeRecord;
|
|
25
|
+
/** One agent as surfaces show it: its record completed from the catalog row (see `agentViewOf`). */
|
|
26
|
+
export declare function useAgentView(agentId: string | null | undefined): MaybeRecord;
|
|
27
|
+
export declare function readAgentView(state: ChatRootState, agentId: string | null | undefined): MaybeRecord;
|
|
28
|
+
export declare function useAgentName(agentId: string | null | undefined): string | undefined;
|
|
29
|
+
export declare function useAgentDescription(agentId: string | null | undefined): string | null;
|
|
30
|
+
export declare function useAgentIdentity(agentId: string | null | undefined): AgentIdentity;
|
|
31
|
+
/** Non-reactive: the record's read name, else the catalog row. */
|
|
32
|
+
export declare function readAgentName(state: ChatRootState, agentId: string | null | undefined): string | undefined;
|
|
33
|
+
export declare function readAgentDescription(state: ChatRootState, agentId: string | null | undefined): string | null;
|
|
34
|
+
export {};
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useAgentSummary } from "@ai-matrx/agents/catalog/react";
|
|
3
|
+
import { getAgentCatalog } from "../../host/ui-slots.js";
|
|
4
|
+
import { useAppSelector } from "../../store/hooks.js";
|
|
5
|
+
import { useMemo } from "react";
|
|
6
|
+
import { hasField } from "@ai-matrx/agents/field-flags";
|
|
7
|
+
import { selectAgentById } from "../redux/agent-definition/selectors.js";
|
|
8
|
+
import { makeEmptyRecord } from "../redux/agent-definition/slice.js";
|
|
9
|
+
function recordOf(state, agentId) {
|
|
10
|
+
return agentId ? selectAgentById(state, agentId) : void 0;
|
|
11
|
+
}
|
|
12
|
+
function catalogRow(agentId) {
|
|
13
|
+
if (!agentId) return void 0;
|
|
14
|
+
try {
|
|
15
|
+
return getAgentCatalog().getAgent(agentId);
|
|
16
|
+
} catch {
|
|
17
|
+
return void 0;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function useCatalog() {
|
|
21
|
+
try {
|
|
22
|
+
return getAgentCatalog();
|
|
23
|
+
} catch {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function ensureAgentCatalog(options) {
|
|
28
|
+
try {
|
|
29
|
+
return getAgentCatalog().ensureLoaded(options).catch(() => void 0);
|
|
30
|
+
} catch {
|
|
31
|
+
return Promise.resolve();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function isAgentCatalogStale() {
|
|
35
|
+
try {
|
|
36
|
+
return getAgentCatalog().isStale();
|
|
37
|
+
} catch {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function useAgentSummaryRow(agentId) {
|
|
42
|
+
return useAgentSummary(useCatalog(), agentId);
|
|
43
|
+
}
|
|
44
|
+
function loaded(record, field) {
|
|
45
|
+
return !!record?._loadedFields && hasField(record._loadedFields, field);
|
|
46
|
+
}
|
|
47
|
+
function nameOf(record, summary) {
|
|
48
|
+
return loaded(record, "name") && record?.name || summary?.name || record?.name || void 0;
|
|
49
|
+
}
|
|
50
|
+
function descriptionOf(record, summary) {
|
|
51
|
+
if (loaded(record, "description")) return record?.description ?? null;
|
|
52
|
+
return summary?.description ?? record?.description ?? null;
|
|
53
|
+
}
|
|
54
|
+
const ACCESS_LEVELS = ["owner", "admin", "editor", "viewer", "system"];
|
|
55
|
+
function toRecordAccessLevel(value) {
|
|
56
|
+
return ACCESS_LEVELS.find((l) => l === value) ?? null;
|
|
57
|
+
}
|
|
58
|
+
function agentViewOf(record, summary) {
|
|
59
|
+
if (!summary) return record;
|
|
60
|
+
const base = record ?? makeEmptyRecord(summary.id);
|
|
61
|
+
const pick = (field, fromSummary) => loaded(record, field) ? base[field] : fromSummary;
|
|
62
|
+
return {
|
|
63
|
+
...base,
|
|
64
|
+
name: nameOf(record, summary) ?? "",
|
|
65
|
+
description: descriptionOf(record, summary),
|
|
66
|
+
category: pick("category", summary.category),
|
|
67
|
+
tags: pick("tags", summary.tags),
|
|
68
|
+
agentType: pick("agentType", summary.agentType),
|
|
69
|
+
modelId: pick("modelId", summary.modelId),
|
|
70
|
+
isActive: pick("isActive", summary.isActive),
|
|
71
|
+
isArchived: pick("isArchived", summary.isArchived),
|
|
72
|
+
// The star is per-person state the catalog owns (its ONE write).
|
|
73
|
+
isFavorite: summary.isFavorite,
|
|
74
|
+
createdBy: pick("createdBy", summary.createdBy),
|
|
75
|
+
organizationId: pick("organizationId", summary.organizationId),
|
|
76
|
+
taskId: pick("taskId", summary.taskId),
|
|
77
|
+
sourceAgentId: pick("sourceAgentId", summary.sourceAgentId),
|
|
78
|
+
createdAt: pick("createdAt", summary.createdAt ?? ""),
|
|
79
|
+
updatedAt: pick("updatedAt", summary.updatedAt ?? ""),
|
|
80
|
+
isOwner: base.isOwner ?? summary.isOwner,
|
|
81
|
+
accessLevel: base.accessLevel ?? toRecordAccessLevel(summary.accessLevel),
|
|
82
|
+
sharedByEmail: base.sharedByEmail ?? summary.sharedByEmail,
|
|
83
|
+
...summary.offeringId === void 0 ? {} : { listOfferingPin: summary.offeringId }
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function useAgentView(agentId) {
|
|
87
|
+
const summary = useAgentSummaryRow(agentId);
|
|
88
|
+
const record = useAppSelector((s) => recordOf(s, agentId));
|
|
89
|
+
return useMemo(() => agentViewOf(record, summary), [record, summary]);
|
|
90
|
+
}
|
|
91
|
+
function readAgentView(state, agentId) {
|
|
92
|
+
return agentViewOf(recordOf(state, agentId), catalogRow(agentId));
|
|
93
|
+
}
|
|
94
|
+
function useAgentName(agentId) {
|
|
95
|
+
const row = useAgentSummaryRow(agentId);
|
|
96
|
+
const record = useAppSelector((s) => recordOf(s, agentId));
|
|
97
|
+
return nameOf(record, row);
|
|
98
|
+
}
|
|
99
|
+
function useAgentDescription(agentId) {
|
|
100
|
+
const row = useAgentSummaryRow(agentId);
|
|
101
|
+
const record = useAppSelector((s) => recordOf(s, agentId));
|
|
102
|
+
return descriptionOf(record, row);
|
|
103
|
+
}
|
|
104
|
+
function useAgentIdentity(agentId) {
|
|
105
|
+
const summary = useAgentSummaryRow(agentId);
|
|
106
|
+
const record = useAppSelector((s) => recordOf(s, agentId));
|
|
107
|
+
return { name: nameOf(record, summary), description: descriptionOf(record, summary), summary };
|
|
108
|
+
}
|
|
109
|
+
function readAgentName(state, agentId) {
|
|
110
|
+
return nameOf(recordOf(state, agentId), catalogRow(agentId));
|
|
111
|
+
}
|
|
112
|
+
function readAgentDescription(state, agentId) {
|
|
113
|
+
return descriptionOf(recordOf(state, agentId), catalogRow(agentId));
|
|
114
|
+
}
|
|
115
|
+
export {
|
|
116
|
+
agentViewOf,
|
|
117
|
+
ensureAgentCatalog,
|
|
118
|
+
isAgentCatalogStale,
|
|
119
|
+
readAgentDescription,
|
|
120
|
+
readAgentName,
|
|
121
|
+
readAgentView,
|
|
122
|
+
useAgentDescription,
|
|
123
|
+
useAgentIdentity,
|
|
124
|
+
useAgentName,
|
|
125
|
+
useAgentSummaryRow,
|
|
126
|
+
useAgentView
|
|
127
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chat's binding of the core RUN TIER store (agent core B2). `agx_get_run_tier`,
|
|
3
|
+
* `agx_get_run_controls`, `agx_get_access_level` and the shared lists are read ONLY through
|
|
4
|
+
* `createRunTierStore` (`@ai-matrx/agents/runtime`); chat's run thunks ask this store and project
|
|
5
|
+
* the answer onto the agent's record for the execution selectors.
|
|
6
|
+
*
|
|
7
|
+
* One store per page, held on `globalThis` (dual-loader graphs split module state).
|
|
8
|
+
*/
|
|
9
|
+
import { type RunTierStore } from "@ai-matrx/agents/runtime";
|
|
10
|
+
/**
|
|
11
|
+
* The run tier store over the host's database client. Chat's thunks always read fresh
|
|
12
|
+
* (`force`) — the agent record's fetch status is chat's cache — so the store is the ONE
|
|
13
|
+
* reader (dedupe, timeout, retry, refusal) and the holder of the last answer.
|
|
14
|
+
*/
|
|
15
|
+
export declare function getRunTierStore(): RunTierStore;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { createRunTierStore } from "@ai-matrx/agents/runtime";
|
|
2
|
+
import { supabase } from "../../host/db.js";
|
|
3
|
+
import { runWithSessionRetry } from "../../host/session-retry.js";
|
|
4
|
+
const KEY = /* @__PURE__ */ Symbol.for("ai-matrx.chat.run-tier-stores");
|
|
5
|
+
function getRunTierStore() {
|
|
6
|
+
const db = supabase;
|
|
7
|
+
const g = globalThis;
|
|
8
|
+
const stores = g[KEY] ??= /* @__PURE__ */ new WeakMap();
|
|
9
|
+
const existing = stores.get(db);
|
|
10
|
+
if (existing) return existing;
|
|
11
|
+
const client = {
|
|
12
|
+
// The access level read is the one that runs at sign-in boundaries (the builder opens
|
|
13
|
+
// straight from a link), so it rides the session retry; the run tier and run controls
|
|
14
|
+
// refuse a signed-out visitor before they read (isSignedOutVisitor in the thunks).
|
|
15
|
+
rpc: (fn, args) => fn === "agx_get_access_level" ? runWithSessionRetry(() => Promise.resolve(db.rpc(fn, args))) : db.rpc(fn, args)
|
|
16
|
+
};
|
|
17
|
+
const store = createRunTierStore({ client });
|
|
18
|
+
stores.set(db, store);
|
|
19
|
+
return store;
|
|
20
|
+
}
|
|
21
|
+
export {
|
|
22
|
+
getRunTierStore
|
|
23
|
+
};
|