@ai-matrx/chat 0.5.4 → 0.5.6
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 +67 -0
- package/dist/agents/components/chat/ChatIncognitoHeaderButton.js +1 -1
- package/dist/agents/components/chat/SandboxPanel.js +1 -1
- package/dist/agents/components/context-items/context-item-block-types.d.ts +1 -1
- package/dist/agents/components/context-items/context-item-block-types.js +2 -1
- package/dist/agents/components/context-items/registry.js +9 -0
- package/dist/agents/components/conversation-history/ConversationHistorySidebar.js +1 -1
- package/dist/agents/components/inputs/resources/SmartAgentResourceChips.js +4 -1
- package/dist/agents/components/inputs/resources/useAttachRenderedArtifact.d.ts +20 -0
- package/dist/agents/components/inputs/resources/useAttachRenderedArtifact.js +107 -0
- package/dist/agents/components/inputs/smart-input/composer/ComposerAgentPill.js +135 -204
- package/dist/agents/components/inputs/smart-input/composer/already-answering.d.ts +1 -1
- package/dist/agents/components/inputs/smart-input/composer/already-answering.js +1 -1
- package/dist/agents/components/inputs/smart-input/composer/useComposerAgent.d.ts +1 -1
- package/dist/agents/components/inputs/smart-input/composer/useComposerAgent.js +1 -1
- package/dist/agents/components/messages-display/user/UserActionBar.js +1 -1
- package/dist/agents/components/run/AgentRunHeader.js +1 -1
- package/dist/agents/components/run/run-sidebar/SidebarHeader.js +1 -1
- package/dist/agents/components/run-controls/RunModelPicker.d.ts +5 -1
- package/dist/agents/components/run-controls/RunModelPicker.js +23 -1
- package/dist/agents/components/shared/AgentConversationColumn.js +3 -1
- package/dist/agents/components/shared/AgentHeader.js +1 -1
- package/dist/agents/components/shared/AgentHeaderMobile.js +1 -1
- package/dist/agents/components/shared/AgentNewRunButton.js +1 -1
- package/dist/agents/components/shared/assistant-message-layout.d.ts +21 -0
- package/dist/agents/components/shared/assistant-message-layout.js +7 -1
- package/dist/agents/components/working-document/WorkingDocumentVersionHistory.js +1 -1
- package/dist/agents/redux/execution-system/instance-resources/instance-resources.selectors.js +14 -0
- package/dist/agents/types/instance.types.d.ts +18 -3
- package/dist/agents/utils/renderedArtifactContext.d.ts +41 -0
- package/dist/agents/utils/renderedArtifactContext.js +41 -0
- package/dist/conversation/hooks/useDomCapturePrint.js +4 -0
- package/dist/conversation/utils/frame-print.d.ts +11 -0
- package/dist/conversation/utils/frame-print.js +46 -0
- package/dist/conversation/utils/markdown-print.d.ts +9 -1
- package/dist/conversation/utils/markdown-print.js +55 -26
- package/dist/cx-chat/components/ChatMobileHeaderBar.js +1 -1
- package/dist/cx-chat/components/ChatPanelBackButton.js +1 -1
- package/dist/cx-chat/components/ChatSidebarClient.js +1 -1
- package/dist/cx-chat/components/user-input/ConversationInput.js +2 -2
- package/dist/cx-chat/components/user-input/InputActionButtons.js +2 -2
- package/dist/host/frame-print.d.ts +17 -0
- package/dist/host/frame-print.js +13 -0
- package/dist/surfaces/components/chrome/SurfaceAgentsHeaderButton.js +1 -1
- package/dist/voice-agent/components/VoiceAgentSurface.js +2 -2
- package/package.json +6 -7
|
@@ -1,36 +1,30 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useState } from "react";
|
|
4
|
-
import { AppWindow, ChevronDown, Gauge, Layers, Star, Webhook } from "lucide-react";
|
|
5
|
-
import { Button
|
|
3
|
+
import { useContext, useState } from "react";
|
|
4
|
+
import { AppWindow, ChevronDown, Cpu, Gauge, Layers, Star, Webhook } from "lucide-react";
|
|
5
|
+
import { Button } from "@ai-matrx/design-system/controls";
|
|
6
6
|
import { MANDATE_KEYS } from "@ai-matrx/agents/mandates";
|
|
7
7
|
import { Popover, PopoverContent, PopoverTrigger } from "@ai-matrx/design-system";
|
|
8
|
-
import { AgentListDropdown } from "@ai-matrx/agents/catalog/react";
|
|
9
|
-
import {
|
|
8
|
+
import { AgentListDropdown, AgentListPanel } from "@ai-matrx/agents/catalog/react";
|
|
9
|
+
import { useIsMobile } from "@ai-matrx/kit/media-query";
|
|
10
|
+
import { useAppSelector } from "../../../../../store/hooks.js";
|
|
10
11
|
import { cn } from "@ai-matrx/design-system";
|
|
11
|
-
import { toast } from "../../../../../host/notify.js";
|
|
12
12
|
import { announceAlreadyAnswering } from "./already-answering.js";
|
|
13
13
|
import { QuickRunModelSelect } from "../../../run-controls/RunModelPicker.js";
|
|
14
|
-
import {
|
|
15
|
-
import { seedOverrides } from "../../../../redux/execution-system/instance-model-overrides/instance-model-overrides.slice.js";
|
|
16
|
-
import { selectInstanceOverrideState } from "../../../../redux/execution-system/instance-model-overrides/instance-model-overrides.selectors.js";
|
|
17
|
-
import {
|
|
18
|
-
effectiveOfferingPin,
|
|
19
|
-
setOfferingPin
|
|
20
|
-
} from "../../../../redux/execution-system/instance-model-overrides/offering-pin.js";
|
|
21
|
-
import { useSessionKnob } from "../../../../../host/prefs-react.js";
|
|
22
|
-
import { knobRefusalSentence, setKnobOverride } from "../../../../../host/prefs.js";
|
|
23
|
-
import { CHAT_DEFAULT_MODEL_KNOB } from "../../../../../ui/chat-default-model-knob.js";
|
|
24
|
-
import { selectModelLabelWithClass } from "@ai-matrx/agents/models";
|
|
25
|
-
import { useModelRecords } from "../../../../identity/model-catalog.js";
|
|
14
|
+
import { selectIsManualExecutionMode } from "../../../../redux/execution-system/selectors/aggregate.selectors.js";
|
|
26
15
|
import {
|
|
16
|
+
COMPOSER_MENU_NO_ENTRANCE,
|
|
17
|
+
ComposerMenuCloseAllContext,
|
|
27
18
|
ComposerMenuDivider,
|
|
28
|
-
ComposerMenuHelp,
|
|
29
19
|
ComposerMenuLabel,
|
|
20
|
+
ComposerMenuLevel,
|
|
21
|
+
ComposerMenuPresentationContext,
|
|
30
22
|
ComposerMenuRow,
|
|
31
23
|
ComposerSubmenu,
|
|
32
|
-
ComposerFoldedSection
|
|
24
|
+
ComposerFoldedSection,
|
|
25
|
+
ignoreOwnWrapper
|
|
33
26
|
} from "./ComposerMenu.js";
|
|
27
|
+
import { ComposerMenuSheet } from "./ComposerMenuSheet.js";
|
|
34
28
|
import { ComposerOutputPanel } from "./ComposerOutput.js";
|
|
35
29
|
import { ComposerEffortRows, useComposerEffort } from "./ComposerEffortPill.js";
|
|
36
30
|
import { composerShows } from "./composer-mode-visibility.js";
|
|
@@ -38,21 +32,24 @@ import { composerPillClass } from "./composer-chip.js";
|
|
|
38
32
|
import { useComposerAgent, useEffectiveModelId } from "./useComposerAgent.js";
|
|
39
33
|
import { useComposerAgentFilter } from "./useComposerAgentFilter.js";
|
|
40
34
|
import { ComposerAgentPeek } from "./ComposerAgentPeek.js";
|
|
41
|
-
|
|
42
|
-
|
|
35
|
+
const AGENT_PICKER_PANEL = "w-[680px] h-[min(528px,80dvh)] p-0";
|
|
36
|
+
const MODEL_PICKER_PANEL = "w-[min(1060px,calc(100vw-24px))] h-[min(640px,80dvh)] p-0";
|
|
37
|
+
const CUSTOM_AGENT_LABEL = "Custom Agent";
|
|
43
38
|
function pillLabel(info, mode) {
|
|
44
39
|
if (!composerShows(mode, "agent.presets")) return info.agentName ?? "Agent";
|
|
45
|
-
const name = info.isCustom ?
|
|
40
|
+
const name = info.isCustom ? CUSTOM_AGENT_LABEL : info.preset?.name ?? info.agentName ?? "Agent";
|
|
46
41
|
return info.effectiveModelLabel ? `${name} \xB7 ${info.effectiveModelLabel}` : name;
|
|
47
42
|
}
|
|
48
43
|
function ComposerAgentPill({ conversationId, mode, size, agentControl, menuSide, folded = false }) {
|
|
49
44
|
const [open, setOpen] = useState(false);
|
|
45
|
+
const isMobile = useIsMobile();
|
|
50
46
|
const effort = useComposerEffort(conversationId, useEffectiveModelId(conversationId));
|
|
51
47
|
const info = useComposerAgent(conversationId);
|
|
52
48
|
const label = pillLabel(info, mode);
|
|
53
49
|
const onSelectAgent = agentControl?.onSelectAgent;
|
|
54
50
|
const agentFilter = useComposerAgentFilter(conversationId);
|
|
55
|
-
const
|
|
51
|
+
const chatPresets = composerShows(mode, "agent.presets");
|
|
52
|
+
const showOverride = info.modelOverridden && chatPresets;
|
|
56
53
|
const overrideTitle = info.agentModelLabel ? `Agent's own model: ${info.agentModelLabel}` : "Not the agent's own model";
|
|
57
54
|
const pill = /* @__PURE__ */ jsx(
|
|
58
55
|
Button,
|
|
@@ -62,55 +59,12 @@ function ComposerAgentPill({ conversationId, mode, size, agentControl, menuSide,
|
|
|
62
59
|
"aria-label": `Agent: ${label}${showOverride ? " (model changed)" : ""}`,
|
|
63
60
|
title: showOverride ? `${label} \u2014 ${overrideTitle}` : label,
|
|
64
61
|
"data-model-override": showOverride ? "" : void 0,
|
|
62
|
+
onClick: isMobile ? () => setOpen(true) : void 0,
|
|
65
63
|
className: "min-w-0 shrink",
|
|
66
64
|
children: showOverride ? `${label} \xB7 changed` : label
|
|
67
65
|
}
|
|
68
66
|
);
|
|
69
|
-
if (folded) {
|
|
70
|
-
const chatPresets = composerShows(mode, "agent.presets");
|
|
71
|
-
const showEffort = Boolean(effort) && composerShows(mode, "meta.effort");
|
|
72
|
-
return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, modal: false, children: [
|
|
73
|
-
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: pill }),
|
|
74
|
-
/* @__PURE__ */ jsxs(
|
|
75
|
-
PopoverContent,
|
|
76
|
-
{
|
|
77
|
-
side: menuSide,
|
|
78
|
-
align: "end",
|
|
79
|
-
sideOffset: 8,
|
|
80
|
-
className: "flex w-80 max-h-[var(--radix-popover-content-available-height)] flex-col overflow-y-auto p-1",
|
|
81
|
-
children: [
|
|
82
|
-
chatPresets ? /* @__PURE__ */ jsx(
|
|
83
|
-
ChatPresetsPanel,
|
|
84
|
-
{
|
|
85
|
-
conversationId,
|
|
86
|
-
info,
|
|
87
|
-
agentControl,
|
|
88
|
-
close: () => setOpen(false)
|
|
89
|
-
}
|
|
90
|
-
) : onSelectAgent ? /* @__PURE__ */ jsx(
|
|
91
|
-
AgentListDropdown,
|
|
92
|
-
{
|
|
93
|
-
onSelect: (agentId) => {
|
|
94
|
-
setOpen(false);
|
|
95
|
-
if (agentId !== info.agentId) onSelectAgent(agentId);
|
|
96
|
-
else announceAlreadyAnswering(info);
|
|
97
|
-
},
|
|
98
|
-
activeAgentId: info.agentId,
|
|
99
|
-
agentFilter,
|
|
100
|
-
contentSide: "left",
|
|
101
|
-
triggerSlot: /* @__PURE__ */ jsx(Tile, { variant: "quiet", icon: /* @__PURE__ */ jsx(Webhook, {}), title: info.agentName ?? "Agent", end: /* @__PURE__ */ jsx(ChevronDown, {}) })
|
|
102
|
-
}
|
|
103
|
-
) : /* @__PURE__ */ jsx(ComposerMenuRow, { icon: Webhook, label: info.agentName ?? "Agent", checked: true }),
|
|
104
|
-
/* @__PURE__ */ jsxs(ComposerFoldedSection, { children: [
|
|
105
|
-
/* @__PURE__ */ jsx(ComposerSubmenu, { row: { icon: AppWindow, label: "Output" }, panelClassName: "w-80", children: /* @__PURE__ */ jsx(ComposerOutputPanel, { conversationId }) }),
|
|
106
|
-
showEffort && effort ? /* @__PURE__ */ jsx(ComposerSubmenu, { row: { icon: Gauge, label: "Effort", detail: effort.word }, panelClassName: "w-56 p-1", children: (close) => /* @__PURE__ */ jsx(ComposerEffortRows, { effort, onChosen: close }) }) : null
|
|
107
|
-
] })
|
|
108
|
-
]
|
|
109
|
-
}
|
|
110
|
-
)
|
|
111
|
-
] });
|
|
112
|
-
}
|
|
113
|
-
if (!composerShows(mode, "agent.presets")) {
|
|
67
|
+
if (!chatPresets && !folded) {
|
|
114
68
|
if (!onSelectAgent) {
|
|
115
69
|
return /* @__PURE__ */ jsx("span", { className: cn(composerPillClass(size, false), "hover:bg-transparent"), title: "This page always answers with this agent", children: /* @__PURE__ */ jsx("span", { className: "truncate font-medium text-foreground", children: label }) });
|
|
116
70
|
}
|
|
@@ -128,6 +82,39 @@ function ComposerAgentPill({ conversationId, mode, size, agentControl, menuSide,
|
|
|
128
82
|
}
|
|
129
83
|
);
|
|
130
84
|
}
|
|
85
|
+
const close = () => setOpen(false);
|
|
86
|
+
const choose = (agentId) => {
|
|
87
|
+
close();
|
|
88
|
+
if (!onSelectAgent) return;
|
|
89
|
+
if (agentId !== info.agentId) onSelectAgent(agentId);
|
|
90
|
+
else announceAlreadyAnswering(info);
|
|
91
|
+
};
|
|
92
|
+
const showEffort = folded && Boolean(effort) && composerShows(mode, "meta.effort");
|
|
93
|
+
const body = /* @__PURE__ */ jsx(ComposerMenuCloseAllContext.Provider, { value: close, children: /* @__PURE__ */ jsxs(ComposerMenuLevel, { children: [
|
|
94
|
+
chatPresets ? /* @__PURE__ */ jsx(ChatAgentMenu, { conversationId, info, agentControl, choose, close }) : onSelectAgent ? (
|
|
95
|
+
// Work+, narrow: the agent picker is one row of the folded menu.
|
|
96
|
+
/* @__PURE__ */ jsx(
|
|
97
|
+
AnyAgentRow,
|
|
98
|
+
{
|
|
99
|
+
icon: Webhook,
|
|
100
|
+
label: `Agent: ${info.agentName ?? "Agent"}`,
|
|
101
|
+
info,
|
|
102
|
+
agentFilter,
|
|
103
|
+
choose
|
|
104
|
+
}
|
|
105
|
+
)
|
|
106
|
+
) : /* @__PURE__ */ jsx(ComposerMenuRow, { icon: Webhook, label: `Agent: ${info.agentName ?? "Agent"}` }),
|
|
107
|
+
folded ? /* @__PURE__ */ jsxs(ComposerFoldedSection, { children: [
|
|
108
|
+
/* @__PURE__ */ jsx(ComposerSubmenu, { row: { icon: AppWindow, label: "Output" }, panelClassName: "w-80", children: /* @__PURE__ */ jsx(ComposerOutputPanel, { conversationId }) }),
|
|
109
|
+
showEffort && effort ? /* @__PURE__ */ jsx(ComposerSubmenu, { row: { icon: Gauge, label: "Effort", detail: effort.word }, panelClassName: "w-56 p-1", children: (closePanel) => /* @__PURE__ */ jsx(ComposerEffortRows, { effort, onChosen: closePanel }) }) : null
|
|
110
|
+
] }) : null
|
|
111
|
+
] }) });
|
|
112
|
+
if (isMobile) {
|
|
113
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
114
|
+
pill,
|
|
115
|
+
/* @__PURE__ */ jsx(ComposerMenuSheet, { open, onOpenChange: setOpen, accessibleName: "Agent and model", children: body })
|
|
116
|
+
] });
|
|
117
|
+
}
|
|
131
118
|
return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, modal: false, children: [
|
|
132
119
|
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: pill }),
|
|
133
120
|
/* @__PURE__ */ jsx(
|
|
@@ -136,163 +123,107 @@ function ComposerAgentPill({ conversationId, mode, size, agentControl, menuSide,
|
|
|
136
123
|
side: menuSide,
|
|
137
124
|
align: "end",
|
|
138
125
|
sideOffset: 8,
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
agentControl,
|
|
146
|
-
close: () => setOpen(false)
|
|
147
|
-
}
|
|
148
|
-
)
|
|
126
|
+
onPointerDownOutside: ignoreOwnWrapper,
|
|
127
|
+
className: cn(
|
|
128
|
+
"flex w-80 max-h-[var(--radix-popover-content-available-height)] flex-col overflow-y-auto p-1",
|
|
129
|
+
COMPOSER_MENU_NO_ENTRANCE
|
|
130
|
+
),
|
|
131
|
+
children: body
|
|
149
132
|
}
|
|
150
133
|
)
|
|
151
134
|
] });
|
|
152
135
|
}
|
|
153
|
-
function
|
|
154
|
-
if (!info.agentId) return null;
|
|
155
|
-
return /* @__PURE__ */ jsx(
|
|
156
|
-
ComposerSubmenu,
|
|
157
|
-
{
|
|
158
|
-
row: { icon: Webhook, label: info.agentName ?? "Agent", description: "View, open or duplicate" },
|
|
159
|
-
panelClassName: "w-[340px] h-[420px] p-0",
|
|
160
|
-
children: /* @__PURE__ */ jsx(ComposerAgentPeek, { agentId: info.agentId, onDone: close })
|
|
161
|
-
}
|
|
162
|
-
);
|
|
163
|
-
}
|
|
164
|
-
function ChatPresetsPanel({
|
|
136
|
+
function ChatAgentMenu({
|
|
165
137
|
conversationId,
|
|
166
138
|
info,
|
|
167
139
|
agentControl,
|
|
140
|
+
choose,
|
|
168
141
|
close
|
|
169
142
|
}) {
|
|
170
|
-
const
|
|
171
|
-
const
|
|
172
|
-
const userId = useAppSelector((s) => s.userAuth?.id ?? null);
|
|
173
|
-
const personalModel = useSessionKnob(CHAT_DEFAULT_MODEL_KNOB);
|
|
174
|
-
const personalModelId = typeof personalModel === "string" && personalModel.trim() ? personalModel : null;
|
|
175
|
-
const overrideState = useAppSelector(selectInstanceOverrideState(conversationId));
|
|
176
|
-
const pinnedOfferingId = effectiveOfferingPin(overrideState);
|
|
177
|
-
const personalModelLabel = useModelRecords((s) => selectModelLabelWithClass(s, personalModelId, pinnedOfferingId)) ?? null;
|
|
178
|
-
const onSelectAgent = agentControl?.onSelectAgent;
|
|
143
|
+
const isManualMode = useAppSelector(selectIsManualExecutionMode(conversationId));
|
|
144
|
+
const inSheet = useContext(ComposerMenuPresentationContext) === "sheet";
|
|
179
145
|
const agentFilter = useComposerAgentFilter(conversationId);
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
/* @__PURE__ */ jsx(ComposerMenuLabel, { children: "Agent" }),
|
|
183
|
-
/* @__PURE__ */ jsx(ThisAgentRow, { info, close }),
|
|
184
|
-
/* @__PURE__ */ jsx(ComposerMenuHelp, { children: "This page always answers with this agent." }),
|
|
185
|
-
/* @__PURE__ */ jsx(ComposerMenuDivider, {}),
|
|
186
|
-
/* @__PURE__ */ jsx(ComposerMenuLabel, { children: "Model for this chat" }),
|
|
187
|
-
/* @__PURE__ */ jsx("div", { className: "px-1.5 pb-1", children: /* @__PURE__ */ jsx(QuickRunModelSelect, { conversationId, className: "h-8 w-full" }) })
|
|
188
|
-
] });
|
|
189
|
-
}
|
|
190
|
-
const choose = (agentId) => {
|
|
191
|
-
close();
|
|
192
|
-
if (agentId !== info.agentId) onSelectAgent(agentId);
|
|
193
|
-
else announceAlreadyAnswering(info);
|
|
194
|
-
};
|
|
146
|
+
const onSelectAgent = agentControl?.onSelectAgent;
|
|
147
|
+
const agentLabel = info.isCustom ? CUSTOM_AGENT_LABEL : info.agentName ?? "Agent";
|
|
195
148
|
const chooseCustom = () => {
|
|
196
|
-
if (!info.customAgentId) return;
|
|
149
|
+
if (!info.customAgentId || !onSelectAgent) return;
|
|
197
150
|
close();
|
|
198
|
-
if (
|
|
199
|
-
|
|
200
|
-
}
|
|
201
|
-
};
|
|
202
|
-
const savePersonalDefault = async (key, value) => {
|
|
203
|
-
if (!userId) {
|
|
204
|
-
toast.error("Sign in first \u2014 your default model is saved to your account.");
|
|
205
|
-
return false;
|
|
206
|
-
}
|
|
207
|
-
let targetOrganizationId;
|
|
208
|
-
try {
|
|
209
|
-
targetOrganizationId = organizationId ?? await ensureOrgId(null);
|
|
210
|
-
} catch (error) {
|
|
211
|
-
if (isOrganizationSelectionCancelled(error)) return false;
|
|
212
|
-
if (presentOrganizationRefusal(error, { subject: "Your default model", act: "saved" })) return false;
|
|
213
|
-
throw error;
|
|
214
|
-
}
|
|
215
|
-
const result = await setKnobOverride({
|
|
216
|
-
feature: "agents.model_prefs",
|
|
217
|
-
key,
|
|
218
|
-
scopeKind: "user",
|
|
219
|
-
scopeId: userId,
|
|
220
|
-
organizationId: targetOrganizationId,
|
|
221
|
-
value,
|
|
222
|
-
note: "Picked under Custom in the chat composer"
|
|
223
|
-
});
|
|
224
|
-
if (!result.ok) {
|
|
225
|
-
toast.error(`Your default chat model was not saved: ${knobRefusalSentence(result)}`);
|
|
226
|
-
return false;
|
|
227
|
-
}
|
|
228
|
-
return true;
|
|
229
|
-
};
|
|
230
|
-
const setPersonalModel = async (modelId) => {
|
|
231
|
-
if (!await savePersonalDefault("chat_default_model", modelId)) return;
|
|
232
|
-
if (info.isCustom) {
|
|
233
|
-
dispatch(seedOverrides({ conversationId, changes: { model: modelId } }));
|
|
234
|
-
} else {
|
|
235
|
-
chooseCustom();
|
|
236
|
-
}
|
|
237
|
-
};
|
|
238
|
-
const setPersonalClass = (offeringId) => {
|
|
239
|
-
dispatch(setOfferingPin({ conversationId, offeringId, seeded: true }));
|
|
240
|
-
void savePersonalDefault("chat_default_offering", offeringId ?? "");
|
|
151
|
+
if (info.isCustom) announceAlreadyAnswering(info);
|
|
152
|
+
else onSelectAgent(info.customAgentId, { mandateKey: MANDATE_KEYS.chat__cx_default });
|
|
241
153
|
};
|
|
242
154
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
243
|
-
/* @__PURE__ */ jsx(
|
|
244
|
-
/* @__PURE__ */ jsx(
|
|
245
|
-
/* @__PURE__ */ jsx(ComposerMenuDivider, {}),
|
|
246
|
-
/* @__PURE__ */ jsx(ComposerMenuLabel, { children: "Chat agents" }),
|
|
247
|
-
info.presets.map((preset) => /* @__PURE__ */ jsx(
|
|
248
|
-
ComposerMenuRow,
|
|
249
|
-
{
|
|
250
|
-
icon: Star,
|
|
251
|
-
label: preset.name,
|
|
252
|
-
detail: preset.modelLabel ?? void 0,
|
|
253
|
-
checked: preset.id === info.agentId,
|
|
254
|
-
onClick: () => choose(preset.id)
|
|
255
|
-
},
|
|
256
|
-
preset.id
|
|
257
|
-
)),
|
|
258
|
-
/* @__PURE__ */ jsx(
|
|
155
|
+
info.agentId ? /* @__PURE__ */ jsx(ComposerSubmenu, { row: { icon: Webhook, label: `Agent: ${agentLabel}` }, panelClassName: "w-[340px] h-[420px] p-0", children: /* @__PURE__ */ jsx(ComposerAgentPeek, { agentId: info.agentId, onDone: close }) }) : null,
|
|
156
|
+
isManualMode ? /* @__PURE__ */ jsx(
|
|
259
157
|
ComposerMenuRow,
|
|
260
158
|
{
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
onClick: chooseCustom
|
|
159
|
+
icon: Cpu,
|
|
160
|
+
label: `Model: ${info.effectiveModelLabel ?? "Agent's model"}`,
|
|
161
|
+
disabled: true,
|
|
162
|
+
title: "Manual mode runs the agent's own model"
|
|
266
163
|
}
|
|
267
|
-
)
|
|
268
|
-
|
|
269
|
-
AgentListDropdown,
|
|
164
|
+
) : /* @__PURE__ */ jsx(
|
|
165
|
+
ComposerSubmenu,
|
|
270
166
|
{
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
167
|
+
row: { icon: Cpu, label: `Model: ${info.effectiveModelLabel ?? "Choose a model"}` },
|
|
168
|
+
panelClassName: MODEL_PICKER_PANEL,
|
|
169
|
+
children: (closePanel) => /* @__PURE__ */ jsx(
|
|
170
|
+
QuickRunModelSelect,
|
|
171
|
+
{
|
|
172
|
+
conversationId,
|
|
173
|
+
presentation: "inline",
|
|
174
|
+
onChosen: () => {
|
|
175
|
+
closePanel();
|
|
176
|
+
close();
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
)
|
|
276
180
|
}
|
|
277
181
|
),
|
|
278
|
-
/* @__PURE__ */
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
182
|
+
onSelectAgent ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
183
|
+
inSheet ? null : /* @__PURE__ */ jsx(ComposerMenuDivider, {}),
|
|
184
|
+
/* @__PURE__ */ jsx(ComposerMenuLabel, { children: "Choose your chat agent" }),
|
|
185
|
+
info.presets.map((preset) => /* @__PURE__ */ jsx(
|
|
186
|
+
ComposerMenuRow,
|
|
187
|
+
{
|
|
188
|
+
icon: Star,
|
|
189
|
+
label: preset.name,
|
|
190
|
+
checked: preset.id === info.agentId,
|
|
191
|
+
onClick: () => choose(preset.id)
|
|
192
|
+
},
|
|
193
|
+
preset.id
|
|
194
|
+
)),
|
|
195
|
+
/* @__PURE__ */ jsx(
|
|
196
|
+
ComposerMenuRow,
|
|
197
|
+
{
|
|
198
|
+
icon: Star,
|
|
199
|
+
label: CUSTOM_AGENT_LABEL,
|
|
200
|
+
checked: info.isCustom,
|
|
201
|
+
disabled: !info.customAgentId,
|
|
202
|
+
onClick: chooseCustom
|
|
203
|
+
}
|
|
204
|
+
),
|
|
205
|
+
/* @__PURE__ */ jsx(AnyAgentRow, { icon: Layers, label: "Choose any agent", info, agentFilter, choose })
|
|
206
|
+
] }) : null
|
|
294
207
|
] });
|
|
295
208
|
}
|
|
209
|
+
function AnyAgentRow({
|
|
210
|
+
icon,
|
|
211
|
+
label,
|
|
212
|
+
info,
|
|
213
|
+
agentFilter,
|
|
214
|
+
choose
|
|
215
|
+
}) {
|
|
216
|
+
return /* @__PURE__ */ jsx(ComposerSubmenu, { row: { icon, label }, panelClassName: AGENT_PICKER_PANEL, children: /* @__PURE__ */ jsx(
|
|
217
|
+
AgentListPanel,
|
|
218
|
+
{
|
|
219
|
+
consumerId: "composer-agent-pill",
|
|
220
|
+
fill: true,
|
|
221
|
+
onSelect: choose,
|
|
222
|
+
activeAgentId: info.agentId,
|
|
223
|
+
agentFilter
|
|
224
|
+
}
|
|
225
|
+
) });
|
|
226
|
+
}
|
|
296
227
|
export {
|
|
297
228
|
ComposerAgentPill
|
|
298
229
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Choosing the agent that is already answering is never silent: the composer
|
|
3
|
-
* pill says "Custom"
|
|
3
|
+
* pill says "Custom Agent" for the Matrx Chat agent, while the
|
|
4
4
|
* agent list names it by its own name — so the press answers who is in the seat.
|
|
5
5
|
*/
|
|
6
6
|
export declare function announceAlreadyAnswering(info: {
|
|
@@ -2,7 +2,7 @@ import { toast } from "../../../../../host/notify.js";
|
|
|
2
2
|
function announceAlreadyAnswering(info) {
|
|
3
3
|
const name = info.agentName ?? "This agent";
|
|
4
4
|
toast.info(
|
|
5
|
-
info.isCustom ?
|
|
5
|
+
info.isCustom ? `Custom Agent (${name}) is already answering this conversation.` : `${name} is already answering this conversation.`
|
|
6
6
|
);
|
|
7
7
|
}
|
|
8
8
|
export {
|
|
@@ -15,7 +15,7 @@ export interface ComposerAgentInfo {
|
|
|
15
15
|
modelOverridden: boolean;
|
|
16
16
|
/** The agent's own model label — what runs when no override is in force. */
|
|
17
17
|
agentModelLabel: string | null;
|
|
18
|
-
/** The
|
|
18
|
+
/** The Matrx Chat agent (`chat.cx_default`) — shown as "Custom Agent". */
|
|
19
19
|
customAgentId: string | null;
|
|
20
20
|
isCustom: boolean;
|
|
21
21
|
preset: ComposerPreset | null;
|
|
@@ -52,7 +52,7 @@ function useComposerAgent(conversationId) {
|
|
|
52
52
|
const effectiveModelLabel = useModelRecords((state) => selectModelLabelWithClass(state, effectiveModelId, effectivePin)) ?? null;
|
|
53
53
|
const agentOwnModelId = useAgentOwnModelId(conversationId);
|
|
54
54
|
const agentModelLabel = useModelRecords((state) => selectModelLabelWithClass(state, agentOwnModelId, agentOwnPin)) ?? null;
|
|
55
|
-
const { mandate: customMandate } = useMandate(MANDATE_KEYS.
|
|
55
|
+
const { mandate: customMandate } = useMandate(MANDATE_KEYS.chat__cx_default, { optional: true });
|
|
56
56
|
const customAgentId = customMandate?.agentId ?? null;
|
|
57
57
|
const rows = useAgentCatalogRows();
|
|
58
58
|
const presetRows = rows.filter(isPresetRow);
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
import {
|
|
16
16
|
TapTargetButtonForGroup,
|
|
17
17
|
TapTargetButtonGroup
|
|
18
|
-
} from "@ai-matrx/tap-target";
|
|
18
|
+
} from "@ai-matrx/design-system/tap-target";
|
|
19
19
|
import { SpeakerButton } from "../../../../host/ui-slots.js";
|
|
20
20
|
import { CopySplitButton } from "@ai-matrx/rich-content/copy/CopySplitButton";
|
|
21
21
|
import { copyRichContent } from "@ai-matrx/rich-content/copy/copy-commands";
|
|
@@ -3,7 +3,7 @@ import { AgentModeController } from "../shared/AgentModeController.js";
|
|
|
3
3
|
import { AgentSaveStatus, AgentOptionsMenu } from "../../../host/ui-slots.js";
|
|
4
4
|
import { ReviewAnswersLink } from "../../../host/ui-slots.js";
|
|
5
5
|
import { AgentSelectorIsland } from "../shared/AgentSelectorIsland.js";
|
|
6
|
-
import { ChevronLeftTapButton } from "@ai-matrx/tap-target/buttons";
|
|
6
|
+
import { ChevronLeftTapButton } from "@ai-matrx/design-system/tap-target/buttons";
|
|
7
7
|
import { AgentNewRunButton } from "../shared/AgentNewRunButton.js";
|
|
8
8
|
import { AgentHeaderMobile } from "../shared/AgentHeaderMobile.js";
|
|
9
9
|
function AgentRunHeader({
|
|
@@ -4,7 +4,7 @@ import { AgentSelectorIsland } from "../../shared/AgentSelectorIsland.js";
|
|
|
4
4
|
import {
|
|
5
5
|
PanelLeftTapButton,
|
|
6
6
|
ChevronLeftTapButton
|
|
7
|
-
} from "@ai-matrx/tap-target/buttons";
|
|
7
|
+
} from "@ai-matrx/design-system/tap-target/buttons";
|
|
8
8
|
import { PowerTapButton } from "@ai-matrx/icons/tap-buttons";
|
|
9
9
|
import { SearchGroup, SearchGroupTrigger } from "../../../../host/ui-slots.js";
|
|
10
10
|
import { AgentNewRunButton } from "../../shared/AgentNewRunButton.js";
|
|
@@ -4,9 +4,13 @@
|
|
|
4
4
|
* ModelListDropdown as `/agents/[id]/build`; only the write target differs.
|
|
5
5
|
* agent default pinned first; reset icon appears only when overridden.
|
|
6
6
|
*/
|
|
7
|
-
export declare function QuickRunModelSelect({ conversationId, className, }: {
|
|
7
|
+
export declare function QuickRunModelSelect({ conversationId, className, presentation, onChosen, }: {
|
|
8
8
|
conversationId: string;
|
|
9
9
|
className?: string;
|
|
10
|
+
/** `inline`: the picker body fills its parent (a menu's panel or page). */
|
|
11
|
+
presentation?: "picker" | "inline";
|
|
12
|
+
/** A model was picked (an inline host closes its panel). */
|
|
13
|
+
onChosen?: () => void;
|
|
10
14
|
}): import("react").JSX.Element;
|
|
11
15
|
export declare function RunModelPicker({ conversationId }: {
|
|
12
16
|
conversationId: string;
|
|
@@ -50,7 +50,9 @@ function useModelOverride(conversationId) {
|
|
|
50
50
|
}
|
|
51
51
|
function QuickRunModelSelect({
|
|
52
52
|
conversationId,
|
|
53
|
-
className
|
|
53
|
+
className,
|
|
54
|
+
presentation = "picker",
|
|
55
|
+
onChosen
|
|
54
56
|
}) {
|
|
55
57
|
const isManualMode = useAppSelector(
|
|
56
58
|
selectIsManualExecutionMode(conversationId)
|
|
@@ -69,6 +71,26 @@ function QuickRunModelSelect({
|
|
|
69
71
|
handleReset
|
|
70
72
|
} = useModelOverride(conversationId);
|
|
71
73
|
const displayModelId = isManualMode ? agentModelId ?? effectiveModel ?? baseModel ?? null : effectiveModel ?? baseModel ?? null;
|
|
74
|
+
if (presentation === "inline") {
|
|
75
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex h-full min-h-0 min-w-0 flex-col", className), children: [
|
|
76
|
+
isOverridden && !isManualMode ? /* @__PURE__ */ jsx("div", { className: "flex shrink-0 justify-end border-b border-border p-1", children: /* @__PURE__ */ jsx(Button, { variant: "quiet", icon: /* @__PURE__ */ jsx(RotateCcw, {}), onClick: handleReset, children: "Agent's own model" }) }) : null,
|
|
77
|
+
/* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1", children: /* @__PURE__ */ jsx(
|
|
78
|
+
ModelListDropdown,
|
|
79
|
+
{
|
|
80
|
+
presentation: "inline",
|
|
81
|
+
value: displayModelId,
|
|
82
|
+
onValueChange: (modelId) => {
|
|
83
|
+
handleChange(modelId);
|
|
84
|
+
onChosen?.();
|
|
85
|
+
},
|
|
86
|
+
pinnedOfferingId,
|
|
87
|
+
onOfferingPinChange: handleOfferingPinChange,
|
|
88
|
+
inputModalities: [],
|
|
89
|
+
outputModalities: ["text"]
|
|
90
|
+
}
|
|
91
|
+
) })
|
|
92
|
+
] });
|
|
93
|
+
}
|
|
72
94
|
return /* @__PURE__ */ jsxs("div", { className: cn("flex min-w-0 items-center gap-1", className), children: [
|
|
73
95
|
/* @__PURE__ */ jsx(
|
|
74
96
|
ModelListDropdown,
|
|
@@ -33,7 +33,8 @@ import {
|
|
|
33
33
|
} from "./transcript-audience.js";
|
|
34
34
|
import { cn } from "@ai-matrx/design-system";
|
|
35
35
|
import {
|
|
36
|
-
ASSISTANT_MESSAGE_COLUMN_INSET_CLASS
|
|
36
|
+
ASSISTANT_MESSAGE_COLUMN_INSET_CLASS,
|
|
37
|
+
WIDE_FIGURE_SCOPE_ATTRIBUTE
|
|
37
38
|
} from "./assistant-message-layout.js";
|
|
38
39
|
import {
|
|
39
40
|
TranscriptLayoutProvider,
|
|
@@ -246,6 +247,7 @@ function AgentConversationColumn({
|
|
|
246
247
|
{
|
|
247
248
|
ref: scrollRef,
|
|
248
249
|
onScroll: handleScroll,
|
|
250
|
+
...edgeScroll && resolvedLayout.width === "reading" && resolvedLayout.align === "center" ? { [WIDE_FIGURE_SCOPE_ATTRIBUTE]: "" } : {},
|
|
249
251
|
className: cn(
|
|
250
252
|
// A SIZE container: what renders inside (the empty-state hero)
|
|
251
253
|
// answers the pane's real height — a 438px split pane beside
|
|
@@ -5,7 +5,7 @@ import { AgentSaveStatus, AgentOptionsMenu } from "../../../host/ui-slots.js";
|
|
|
5
5
|
import { AgentReferenceCopyButton } from "./AgentReferenceCopyButton.js";
|
|
6
6
|
import { AgentHeaderMobile } from "./AgentHeaderMobile.js";
|
|
7
7
|
import { ReviewAnswersLink } from "../../../host/ui-slots.js";
|
|
8
|
-
import { ChevronLeftTapButton } from "@ai-matrx/tap-target/buttons";
|
|
8
|
+
import { ChevronLeftTapButton } from "@ai-matrx/design-system/tap-target/buttons";
|
|
9
9
|
function AgentHeader({
|
|
10
10
|
agentId,
|
|
11
11
|
agentName,
|
|
@@ -8,7 +8,7 @@ import { selectAgentIsDirty } from "../../redux/agent-definition/selectors.js";
|
|
|
8
8
|
import {
|
|
9
9
|
TapTargetButtonForGroup,
|
|
10
10
|
TapTargetButtonGroup
|
|
11
|
-
} from "@ai-matrx/tap-target";
|
|
11
|
+
} from "@ai-matrx/design-system/tap-target";
|
|
12
12
|
import { AgentListDropdown } from "@ai-matrx/agents/catalog/react";
|
|
13
13
|
import {
|
|
14
14
|
AlertDialog,
|
|
@@ -4,7 +4,7 @@ import { useCallback } from "react";
|
|
|
4
4
|
import { useRouter, usePathname, useSearchParams } from "../../../host/navigation.js";
|
|
5
5
|
import { useAppDispatch, useAppSelector } from "../../../store/hooks.js";
|
|
6
6
|
import { startNewConversation } from "../../redux/execution-system/thunks/create-instance.thunk.js";
|
|
7
|
-
import { PlusTapButton } from "@ai-matrx/tap-target/buttons";
|
|
7
|
+
import { PlusTapButton } from "@ai-matrx/design-system/tap-target/buttons";
|
|
8
8
|
import { selectFocusedConversation } from "../../redux/execution-system/conversation-focus/conversation-focus.selectors.js";
|
|
9
9
|
import { pushAddressWithoutNavigating } from "@ai-matrx/rich-content/utils/addressWithoutNavigating";
|
|
10
10
|
function AgentNewRunButton({ surfaceKey }) {
|
|
@@ -6,3 +6,24 @@
|
|
|
6
6
|
export declare const ASSISTANT_MESSAGE_COLUMN_CLASS = "mx-auto w-full max-w-3xl";
|
|
7
7
|
/** Chat's exact horizontal inset inside the canonical reading column. */
|
|
8
8
|
export declare const ASSISTANT_MESSAGE_COLUMN_INSET_CLASS = "px-2";
|
|
9
|
+
/**
|
|
10
|
+
* WIDE FIGURES — a figure (a rendered web page, a wide visual) is not prose.
|
|
11
|
+
* A transcript that opts in carries `WIDE_FIGURE_SCOPE_ATTRIBUTE` on its scroll
|
|
12
|
+
* area, which is a CSS size container; inside it an element with
|
|
13
|
+
* `WIDE_FIGURE_CLASS` breaks out of the reading column to the transcript's own
|
|
14
|
+
* width (`100cqi`), minus a 1rem gutter each side, centered on the column, and
|
|
15
|
+
* capped at `WIDE_FIGURE_MAX_WIDTH_PX`.
|
|
16
|
+
*
|
|
17
|
+
* 1100px: wide enough that the common 960–1080px layouts AI-written pages use
|
|
18
|
+
* (a 960px `main` plus its padding) render at full size; no wider, so a large
|
|
19
|
+
* monitor never stretches a figure into empty bands. `max(100%, …)` means a
|
|
20
|
+
* transcript no wider than the column (phones, split panes) leaves the figure
|
|
21
|
+
* exactly column-wide. Outside an opted-in transcript (notes, rich-document
|
|
22
|
+
* surfaces, a `width: "fill"` host, a start-aligned column) it does nothing.
|
|
23
|
+
*
|
|
24
|
+
* Classes are literal strings so the host's Tailwind scan of this package
|
|
25
|
+
* finds them; keep 1100px in sync with WIDE_FIGURE_MAX_WIDTH_PX.
|
|
26
|
+
*/
|
|
27
|
+
export declare const WIDE_FIGURE_MAX_WIDTH_PX = 1100;
|
|
28
|
+
export declare const WIDE_FIGURE_SCOPE_ATTRIBUTE = "data-wide-figures";
|
|
29
|
+
export declare const WIDE_FIGURE_CLASS = "[[data-wide-figures]_&]:w-[max(100%,min(1100px,100cqi_-_2rem))] [[data-wide-figures]_&]:ml-[calc((100%_-_max(100%,min(1100px,100cqi_-_2rem)))/2)]";
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
const ASSISTANT_MESSAGE_COLUMN_CLASS = "mx-auto w-full max-w-3xl";
|
|
2
2
|
const ASSISTANT_MESSAGE_COLUMN_INSET_CLASS = "px-2";
|
|
3
|
+
const WIDE_FIGURE_MAX_WIDTH_PX = 1100;
|
|
4
|
+
const WIDE_FIGURE_SCOPE_ATTRIBUTE = "data-wide-figures";
|
|
5
|
+
const WIDE_FIGURE_CLASS = "[[data-wide-figures]_&]:w-[max(100%,min(1100px,100cqi_-_2rem))] [[data-wide-figures]_&]:ml-[calc((100%_-_max(100%,min(1100px,100cqi_-_2rem)))/2)]";
|
|
3
6
|
export {
|
|
4
7
|
ASSISTANT_MESSAGE_COLUMN_CLASS,
|
|
5
|
-
ASSISTANT_MESSAGE_COLUMN_INSET_CLASS
|
|
8
|
+
ASSISTANT_MESSAGE_COLUMN_INSET_CLASS,
|
|
9
|
+
WIDE_FIGURE_CLASS,
|
|
10
|
+
WIDE_FIGURE_MAX_WIDTH_PX,
|
|
11
|
+
WIDE_FIGURE_SCOPE_ATTRIBUTE
|
|
6
12
|
};
|
|
@@ -15,7 +15,7 @@ import { useWorkingDocumentVersions } from "./useWorkingDocumentVersions.js";
|
|
|
15
15
|
import { useWorkingDocument } from "../../hooks/useWorkingDocument.js";
|
|
16
16
|
import { setWorkingDocMainView } from "./workingDocumentViewStore.js";
|
|
17
17
|
import { ErrorAlchemyMenu } from "../../../host/ui-slots.js";
|
|
18
|
-
import { ChevronLeftTapButton, ChevronRightTapButton } from "@ai-matrx/tap-target/buttons";
|
|
18
|
+
import { ChevronLeftTapButton, ChevronRightTapButton } from "@ai-matrx/design-system/tap-target/buttons";
|
|
19
19
|
function formatWhen(iso) {
|
|
20
20
|
if (!iso) return "Now";
|
|
21
21
|
try {
|