@tangle-network/sandbox-ui 0.58.0 → 0.59.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chat.d.ts +128 -2
- package/dist/chat.js +5 -1
- package/dist/{chunk-WLMLD2CZ.js → chunk-4XOZGMJC.js} +482 -70
- package/dist/globals.css +43 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +5 -1
- package/dist/styles.css +43 -0
- package/package.json +1 -1
package/dist/chat.d.ts
CHANGED
|
@@ -48,6 +48,69 @@ interface ReasoningLevelPickerProps {
|
|
|
48
48
|
declare const DEFAULT_REASONING_LEVEL_OPTIONS: ReadonlyArray<ReasoningLevelOption>;
|
|
49
49
|
declare function ReasoningLevelPicker({ value, onChange, disabled, className, triggerClassName, options, available, side, avoidCollisions, }: ReasoningLevelPickerProps): react_jsx_runtime.JSX.Element;
|
|
50
50
|
|
|
51
|
+
/**
|
|
52
|
+
* An agent profile: a named bundle of toolset + persona layered over the same
|
|
53
|
+
* model and session. `builtin` profiles are the product's shipped modes (e.g.
|
|
54
|
+
* Studio / Assistant); the rest are user-saved custom agents. The concept is
|
|
55
|
+
* backend-agnostic — it applies to a router-backed agent and a sandbox-backed
|
|
56
|
+
* one alike, which is why it lives beside the model control rather than under
|
|
57
|
+
* the harness.
|
|
58
|
+
*/
|
|
59
|
+
interface AgentProfileOption {
|
|
60
|
+
id: string;
|
|
61
|
+
name: string;
|
|
62
|
+
/** Builtin: a one-line description. Custom: derived "N tools" if omitted. */
|
|
63
|
+
description?: string;
|
|
64
|
+
/** Capability/tool-group ids this profile enables. */
|
|
65
|
+
capabilities?: ReadonlyArray<string>;
|
|
66
|
+
/** Persona / extra system instructions. */
|
|
67
|
+
instructions?: string;
|
|
68
|
+
/** A shipped mode vs a user-saved custom agent. */
|
|
69
|
+
builtin?: boolean;
|
|
70
|
+
}
|
|
71
|
+
/** A selectable tool group offered by the create/edit form. */
|
|
72
|
+
interface AgentProfileCapability {
|
|
73
|
+
id: string;
|
|
74
|
+
label: string;
|
|
75
|
+
description?: string;
|
|
76
|
+
}
|
|
77
|
+
/** The editable shape the create/edit form emits. */
|
|
78
|
+
interface AgentProfileDraft {
|
|
79
|
+
id?: string;
|
|
80
|
+
name: string;
|
|
81
|
+
capabilities: string[];
|
|
82
|
+
instructions: string;
|
|
83
|
+
}
|
|
84
|
+
interface AgentProfilePickerProps {
|
|
85
|
+
/** Selected profile id. */
|
|
86
|
+
value: string;
|
|
87
|
+
onChange: (id: string) => void;
|
|
88
|
+
profiles: ReadonlyArray<AgentProfileOption>;
|
|
89
|
+
/**
|
|
90
|
+
* Tool catalog for the create/edit form. Provide together with at least one
|
|
91
|
+
* write callback to enable authoring custom agents; omit for a
|
|
92
|
+
* selection-only picker (the New / edit / delete affordances stay hidden).
|
|
93
|
+
*/
|
|
94
|
+
capabilities?: ReadonlyArray<AgentProfileCapability>;
|
|
95
|
+
onCreate?: (draft: AgentProfileDraft) => void | Promise<void>;
|
|
96
|
+
onUpdate?: (id: string, draft: AgentProfileDraft) => void | Promise<void>;
|
|
97
|
+
onDelete?: (id: string) => void | Promise<void>;
|
|
98
|
+
disabled?: boolean;
|
|
99
|
+
className?: string;
|
|
100
|
+
/** Side the menu opens toward. Defaults to up (composer-anchored). */
|
|
101
|
+
side?: "top" | "bottom";
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Agent / mode switcher styled to match the chat control strip's pills
|
|
105
|
+
* (harness, model, effort). The pill shows the active profile; the menu lists
|
|
106
|
+
* builtin modes and saved custom agents. When a capability catalog and a write
|
|
107
|
+
* callback are supplied it also authors agents inline (name + tool toggles +
|
|
108
|
+
* persona) — a self-contained click-outside popover rather than a Radix menu,
|
|
109
|
+
* because the inline form needs its own focus and typing without the menu
|
|
110
|
+
* stealing keystrokes.
|
|
111
|
+
*/
|
|
112
|
+
declare function AgentProfilePicker({ value, onChange, profiles, capabilities, onCreate, onUpdate, onDelete, disabled, className, side, }: AgentProfilePickerProps): react_jsx_runtime.JSX.Element;
|
|
113
|
+
|
|
51
114
|
interface AgentSessionHarnessControl {
|
|
52
115
|
value: HarnessType;
|
|
53
116
|
onChange: (next: HarnessType) => void;
|
|
@@ -86,12 +149,33 @@ interface AgentSessionReasoningControl {
|
|
|
86
149
|
*/
|
|
87
150
|
available?: ReadonlyArray<ReasoningEffort>;
|
|
88
151
|
}
|
|
152
|
+
/**
|
|
153
|
+
* Agent-profile (mode / toolset / persona) selection. Backend-agnostic — it
|
|
154
|
+
* sits beside the model in both router-backed and sandbox-backed modes, so the
|
|
155
|
+
* same session can switch the agent's identity without touching the harness.
|
|
156
|
+
*/
|
|
157
|
+
interface AgentSessionProfileControl {
|
|
158
|
+
value: string;
|
|
159
|
+
onChange: (id: string) => void;
|
|
160
|
+
profiles: ReadonlyArray<AgentProfileOption>;
|
|
161
|
+
/** Tool catalog for inline authoring; pair with a write callback to enable it. */
|
|
162
|
+
capabilities?: ReadonlyArray<AgentProfileCapability>;
|
|
163
|
+
onCreate?: (draft: AgentProfileDraft) => void | Promise<void>;
|
|
164
|
+
onUpdate?: (id: string, draft: AgentProfileDraft) => void | Promise<void>;
|
|
165
|
+
onDelete?: (id: string) => void | Promise<void>;
|
|
166
|
+
disabled?: boolean;
|
|
167
|
+
}
|
|
89
168
|
interface AgentSessionControlsProps {
|
|
90
169
|
/**
|
|
91
170
|
* Harness (agent backend) selection. Switching harness usually means
|
|
92
171
|
* re-creating the agent session — the consumer owns that lifecycle.
|
|
93
172
|
*/
|
|
94
173
|
harness?: AgentSessionHarnessControl;
|
|
174
|
+
/**
|
|
175
|
+
* Agent profile (mode / toolset / persona). Universal — present in both
|
|
176
|
+
* router-backed and sandbox-backed composers, independent of the harness.
|
|
177
|
+
*/
|
|
178
|
+
profile?: AgentSessionProfileControl;
|
|
95
179
|
/** Per-turn model override, fed by the router's model catalog. */
|
|
96
180
|
model?: AgentSessionModelControl;
|
|
97
181
|
/** Thinking-effort level applied to subsequent turns. */
|
|
@@ -139,7 +223,49 @@ interface AgentSessionControlsProps {
|
|
|
139
223
|
*
|
|
140
224
|
* Designed to slot into `SandboxWorkbench`'s `session.composerControls`.
|
|
141
225
|
*/
|
|
142
|
-
declare function AgentSessionControls({ harness, model, reasoning, trailing, className, context, layout, menuPlacement, }: AgentSessionControlsProps): react_jsx_runtime.JSX.Element | null;
|
|
226
|
+
declare function AgentSessionControls({ harness, profile, model, reasoning, trailing, className, context, layout, menuPlacement, }: AgentSessionControlsProps): react_jsx_runtime.JSX.Element | null;
|
|
227
|
+
|
|
228
|
+
interface AgentComposerProps {
|
|
229
|
+
/** Composer text (controlled). */
|
|
230
|
+
value: string;
|
|
231
|
+
onChange: (value: string) => void;
|
|
232
|
+
/** Fired on Enter (without Shift) or the send button. */
|
|
233
|
+
onSubmit: () => void;
|
|
234
|
+
placeholder?: string;
|
|
235
|
+
/** Disables typing and sending — e.g. while a turn is streaming. */
|
|
236
|
+
disabled?: boolean;
|
|
237
|
+
/** Spins the send button and blocks submit, without disabling the textarea. */
|
|
238
|
+
busy?: boolean;
|
|
239
|
+
/**
|
|
240
|
+
* Agent backend. Present → sandbox-backed (the harness pill shows and snaps
|
|
241
|
+
* with the model); omitted → router-backed (no harness, just model/effort).
|
|
242
|
+
*/
|
|
243
|
+
harness?: AgentSessionHarnessControl;
|
|
244
|
+
/** Agent profile (mode / toolset / persona) — universal across both modes. */
|
|
245
|
+
profile?: AgentSessionProfileControl;
|
|
246
|
+
model?: AgentSessionModelControl;
|
|
247
|
+
reasoning?: AgentSessionReasoningControl;
|
|
248
|
+
/** Forwarded to the control strip (chat hides shell-only harnesses). */
|
|
249
|
+
context?: "chat" | "all";
|
|
250
|
+
/** Extra content left of the send button (token meter, cost, status). */
|
|
251
|
+
trailing?: React.ReactNode;
|
|
252
|
+
/** Minimum textarea rows before it grows. Default 2. */
|
|
253
|
+
minRows?: number;
|
|
254
|
+
/** Max pixel height before the textarea scrolls. Default 200. */
|
|
255
|
+
maxHeight?: number;
|
|
256
|
+
className?: string;
|
|
257
|
+
sendLabel?: string;
|
|
258
|
+
autoFocus?: boolean;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* The canonical agent chat input: one rounded surface holding an auto-growing
|
|
262
|
+
* textarea, the embedded control strip (profile · harness · model · effort) at
|
|
263
|
+
* the bottom-left, and the send button at the bottom-right. The strip's pickers
|
|
264
|
+
* snap the harness↔model pair automatically; which controls appear is driven
|
|
265
|
+
* purely by which control objects are passed, so the same component is the
|
|
266
|
+
* router-backed composer (no harness) and the sandbox-backed one (with harness).
|
|
267
|
+
*/
|
|
268
|
+
declare function AgentComposer({ value, onChange, onSubmit, placeholder, disabled, busy, harness, profile, model, reasoning, context, trailing, minRows, maxHeight, className, sendLabel, autoFocus, }: AgentComposerProps): react_jsx_runtime.JSX.Element;
|
|
143
269
|
|
|
144
270
|
/**
|
|
145
271
|
* Whether `harness` can run `modelId`. Router-backed harnesses, and provider-less
|
|
@@ -253,4 +379,4 @@ declare function createFetchTransport(opts: {
|
|
|
253
379
|
fetchImpl?: typeof fetch;
|
|
254
380
|
}): ArtifactAgentDockTransport;
|
|
255
381
|
|
|
256
|
-
export { AgentSessionControls, type AgentSessionControlsProps, type AgentSessionHarnessControl, type AgentSessionModelControl, type AgentSessionReasoningControl, ArtifactAgentDock, type ArtifactAgentDockProps, type ArtifactAgentDockTransport, type ArtifactDockMessage, type ArtifactDockStreamEvent, type ArtifactKind, type ArtifactScope, DEFAULT_REASONING_LEVEL_OPTIONS, type ReasoningLevel, type ReasoningLevelOption, ReasoningLevelPicker, type ReasoningLevelPickerProps, createFetchTransport, isModelCompatibleWithHarness, snapModelToHarness };
|
|
382
|
+
export { AgentComposer, type AgentComposerProps, type AgentProfileCapability, type AgentProfileDraft, type AgentProfileOption, AgentProfilePicker, type AgentProfilePickerProps, AgentSessionControls, type AgentSessionControlsProps, type AgentSessionHarnessControl, type AgentSessionModelControl, type AgentSessionProfileControl, type AgentSessionReasoningControl, ArtifactAgentDock, type ArtifactAgentDockProps, type ArtifactAgentDockTransport, type ArtifactDockMessage, type ArtifactDockStreamEvent, type ArtifactKind, type ArtifactScope, DEFAULT_REASONING_LEVEL_OPTIONS, type ReasoningLevel, type ReasoningLevelOption, ReasoningLevelPicker, type ReasoningLevelPickerProps, createFetchTransport, isModelCompatibleWithHarness, snapModelToHarness };
|
package/dist/chat.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
|
+
AgentComposer,
|
|
3
|
+
AgentProfilePicker,
|
|
2
4
|
AgentSessionControls,
|
|
3
5
|
AgentTimeline,
|
|
4
6
|
ArtifactAgentDock,
|
|
@@ -15,12 +17,14 @@ import {
|
|
|
15
17
|
modelProvider,
|
|
16
18
|
snapHarnessToModel,
|
|
17
19
|
snapModelToHarness
|
|
18
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-4XOZGMJC.js";
|
|
19
21
|
import "./chunk-HU4B2M4K.js";
|
|
20
22
|
import "./chunk-SF6LPMMN.js";
|
|
21
23
|
import "./chunk-EI44GEQ5.js";
|
|
22
24
|
import "./chunk-U67V476Y.js";
|
|
23
25
|
export {
|
|
26
|
+
AgentComposer,
|
|
27
|
+
AgentProfilePicker,
|
|
24
28
|
AgentSessionControls,
|
|
25
29
|
AgentTimeline,
|
|
26
30
|
ArtifactAgentDock,
|
|
@@ -146,7 +146,7 @@ function ReasoningLevelPicker({
|
|
|
146
146
|
// src/chat/agent-session-controls.tsx
|
|
147
147
|
import { reasoningEffortsFor } from "@tangle-network/agent-interface";
|
|
148
148
|
import * as DropdownMenu2 from "@radix-ui/react-dropdown-menu";
|
|
149
|
-
import { ChevronDown as
|
|
149
|
+
import { ChevronDown as ChevronDown3, Lock, SlidersHorizontal } from "lucide-react";
|
|
150
150
|
|
|
151
151
|
// src/chat/harness-model-compat.ts
|
|
152
152
|
import {
|
|
@@ -161,8 +161,293 @@ function snapModelToHarness(harness, modelId, models) {
|
|
|
161
161
|
return snapModelIdToHarness(harness, modelId, models.map(canonicalModelId));
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
-
// src/chat/agent-
|
|
164
|
+
// src/chat/agent-profile-picker.tsx
|
|
165
|
+
import { Bot, Check, ChevronDown as ChevronDown2, Pencil, Plus, Trash2 } from "lucide-react";
|
|
166
|
+
import * as React from "react";
|
|
165
167
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
168
|
+
function useClickOutside(onOutside) {
|
|
169
|
+
const ref = React.useRef(null);
|
|
170
|
+
React.useEffect(() => {
|
|
171
|
+
function handler(event) {
|
|
172
|
+
if (ref.current && !ref.current.contains(event.target)) {
|
|
173
|
+
onOutside();
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
document.addEventListener("mousedown", handler);
|
|
177
|
+
return () => document.removeEventListener("mousedown", handler);
|
|
178
|
+
}, [onOutside]);
|
|
179
|
+
return ref;
|
|
180
|
+
}
|
|
181
|
+
function profileSubtitle(profile) {
|
|
182
|
+
if (profile.description) return profile.description;
|
|
183
|
+
const count = profile.capabilities?.length ?? 0;
|
|
184
|
+
return `${count} ${count === 1 ? "tool group" : "tool groups"}`;
|
|
185
|
+
}
|
|
186
|
+
function AgentProfilePicker({
|
|
187
|
+
value,
|
|
188
|
+
onChange,
|
|
189
|
+
profiles,
|
|
190
|
+
capabilities,
|
|
191
|
+
onCreate,
|
|
192
|
+
onUpdate,
|
|
193
|
+
onDelete,
|
|
194
|
+
disabled,
|
|
195
|
+
className,
|
|
196
|
+
side = "top"
|
|
197
|
+
}) {
|
|
198
|
+
const [open, setOpen] = React.useState(false);
|
|
199
|
+
const [composing, setComposing] = React.useState(
|
|
200
|
+
null
|
|
201
|
+
);
|
|
202
|
+
const ref = useClickOutside(() => {
|
|
203
|
+
setOpen(false);
|
|
204
|
+
setComposing(null);
|
|
205
|
+
});
|
|
206
|
+
const canAuthor = Boolean(capabilities && (onCreate || onUpdate));
|
|
207
|
+
const builtins = profiles.filter((profile) => profile.builtin);
|
|
208
|
+
const custom = profiles.filter((profile) => !profile.builtin);
|
|
209
|
+
const selected = profiles.find((profile) => profile.id === value);
|
|
210
|
+
function select(id) {
|
|
211
|
+
onChange(id);
|
|
212
|
+
setOpen(false);
|
|
213
|
+
}
|
|
214
|
+
async function save(draft) {
|
|
215
|
+
if (draft.id) await onUpdate?.(draft.id, draft);
|
|
216
|
+
else await onCreate?.(draft);
|
|
217
|
+
setComposing(null);
|
|
218
|
+
}
|
|
219
|
+
return /* @__PURE__ */ jsxs2("div", { ref, className: cn("relative inline-flex", className), children: [
|
|
220
|
+
/* @__PURE__ */ jsxs2(
|
|
221
|
+
"button",
|
|
222
|
+
{
|
|
223
|
+
type: "button",
|
|
224
|
+
disabled,
|
|
225
|
+
onClick: () => setOpen((v) => !v),
|
|
226
|
+
className: cn(
|
|
227
|
+
"inline-flex h-8 items-center gap-1.5 rounded-lg border border-[var(--md3-outline-variant)] bg-surface-container px-2.5",
|
|
228
|
+
"text-xs font-medium text-foreground shadow-sm transition-colors",
|
|
229
|
+
"hover:border-[var(--md3-outline-variant)] hover:bg-surface-container-high focus:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
230
|
+
"data-[state=open]:border-[var(--md3-outline-variant)] data-[state=open]:bg-surface-container-high",
|
|
231
|
+
"disabled:cursor-not-allowed disabled:opacity-60"
|
|
232
|
+
),
|
|
233
|
+
"data-state": open ? "open" : "closed",
|
|
234
|
+
"aria-label": "Agent profile",
|
|
235
|
+
children: [
|
|
236
|
+
/* @__PURE__ */ jsx2(Bot, { className: "h-3.5 w-3.5 text-muted-foreground" }),
|
|
237
|
+
/* @__PURE__ */ jsx2("span", { className: "max-w-[140px] truncate", children: selected?.name ?? value }),
|
|
238
|
+
/* @__PURE__ */ jsx2(ChevronDown2, { className: "h-3.5 w-3.5 text-muted-foreground" })
|
|
239
|
+
]
|
|
240
|
+
}
|
|
241
|
+
),
|
|
242
|
+
open && /* @__PURE__ */ jsx2(
|
|
243
|
+
"div",
|
|
244
|
+
{
|
|
245
|
+
className: cn(
|
|
246
|
+
"absolute left-0 z-50 w-[320px] overflow-hidden rounded-[var(--radius-md)] border border-[var(--md3-outline-variant)] bg-surface-container-highest p-1",
|
|
247
|
+
"shadow-[0_8px_30px_rgba(0,0,0,0.45)] ring-1 ring-[#ffffff14]",
|
|
248
|
+
side === "top" ? "bottom-full mb-2" : "top-full mt-2"
|
|
249
|
+
),
|
|
250
|
+
children: composing ? /* @__PURE__ */ jsx2(
|
|
251
|
+
ProfileForm,
|
|
252
|
+
{
|
|
253
|
+
capabilities: capabilities ?? [],
|
|
254
|
+
initial: composing === "new" ? void 0 : composing,
|
|
255
|
+
onCancel: () => setComposing(null),
|
|
256
|
+
onSave: save
|
|
257
|
+
}
|
|
258
|
+
) : /* @__PURE__ */ jsxs2("div", { className: "max-h-[min(60vh,420px)] overflow-y-auto", children: [
|
|
259
|
+
/* @__PURE__ */ jsx2(SectionHeader, { children: "Modes" }),
|
|
260
|
+
builtins.map((profile) => /* @__PURE__ */ jsx2(
|
|
261
|
+
ProfileRow,
|
|
262
|
+
{
|
|
263
|
+
active: profile.id === value,
|
|
264
|
+
title: profile.name,
|
|
265
|
+
subtitle: profileSubtitle(profile),
|
|
266
|
+
onSelect: () => select(profile.id)
|
|
267
|
+
},
|
|
268
|
+
profile.id
|
|
269
|
+
)),
|
|
270
|
+
custom.length > 0 && /* @__PURE__ */ jsx2(SectionHeader, { children: "Your agents" }),
|
|
271
|
+
custom.map((profile) => /* @__PURE__ */ jsx2(
|
|
272
|
+
ProfileRow,
|
|
273
|
+
{
|
|
274
|
+
active: profile.id === value,
|
|
275
|
+
title: profile.name,
|
|
276
|
+
subtitle: profileSubtitle(profile),
|
|
277
|
+
onSelect: () => select(profile.id),
|
|
278
|
+
onEdit: canAuthor ? () => setComposing(profile) : void 0,
|
|
279
|
+
onDelete: onDelete ? () => void onDelete(profile.id) : void 0
|
|
280
|
+
},
|
|
281
|
+
profile.id
|
|
282
|
+
)),
|
|
283
|
+
canAuthor && /* @__PURE__ */ jsxs2(
|
|
284
|
+
"button",
|
|
285
|
+
{
|
|
286
|
+
type: "button",
|
|
287
|
+
onClick: () => setComposing("new"),
|
|
288
|
+
className: "mt-1 flex w-full items-center gap-2 rounded-md px-2.5 py-2 text-left text-sm text-[var(--accent-text)] transition-colors hover:bg-accent/40",
|
|
289
|
+
children: [
|
|
290
|
+
/* @__PURE__ */ jsx2(Plus, { className: "h-4 w-4" }),
|
|
291
|
+
" New agent\u2026"
|
|
292
|
+
]
|
|
293
|
+
}
|
|
294
|
+
)
|
|
295
|
+
] })
|
|
296
|
+
}
|
|
297
|
+
)
|
|
298
|
+
] });
|
|
299
|
+
}
|
|
300
|
+
function SectionHeader({ children }) {
|
|
301
|
+
return /* @__PURE__ */ jsx2("div", { className: "px-2.5 pb-1 pt-2 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground/70", children });
|
|
302
|
+
}
|
|
303
|
+
function ProfileRow({
|
|
304
|
+
active,
|
|
305
|
+
title,
|
|
306
|
+
subtitle,
|
|
307
|
+
onSelect,
|
|
308
|
+
onEdit,
|
|
309
|
+
onDelete
|
|
310
|
+
}) {
|
|
311
|
+
return /* @__PURE__ */ jsxs2(
|
|
312
|
+
"div",
|
|
313
|
+
{
|
|
314
|
+
className: cn(
|
|
315
|
+
"group flex items-center gap-2 rounded-md px-2.5 py-2 text-sm transition-colors",
|
|
316
|
+
active ? "bg-[var(--accent-surface-soft)] text-[var(--accent-text)]" : "hover:bg-accent/40"
|
|
317
|
+
),
|
|
318
|
+
children: [
|
|
319
|
+
/* @__PURE__ */ jsxs2(
|
|
320
|
+
"button",
|
|
321
|
+
{
|
|
322
|
+
type: "button",
|
|
323
|
+
onClick: onSelect,
|
|
324
|
+
className: "flex min-w-0 flex-1 items-center gap-2 text-left",
|
|
325
|
+
children: [
|
|
326
|
+
/* @__PURE__ */ jsx2("span", { className: "flex h-4 w-4 shrink-0 items-center justify-center", children: active && /* @__PURE__ */ jsx2(Check, { className: "h-3.5 w-3.5" }) }),
|
|
327
|
+
/* @__PURE__ */ jsxs2("span", { className: "min-w-0", children: [
|
|
328
|
+
/* @__PURE__ */ jsx2("span", { className: "block truncate font-medium", children: title }),
|
|
329
|
+
/* @__PURE__ */ jsx2("span", { className: "block truncate text-xs text-muted-foreground", children: subtitle })
|
|
330
|
+
] })
|
|
331
|
+
]
|
|
332
|
+
}
|
|
333
|
+
),
|
|
334
|
+
(onEdit || onDelete) && /* @__PURE__ */ jsxs2("span", { className: "flex shrink-0 items-center gap-1 opacity-0 transition-opacity group-hover:opacity-100", children: [
|
|
335
|
+
onEdit && /* @__PURE__ */ jsx2(
|
|
336
|
+
"button",
|
|
337
|
+
{
|
|
338
|
+
type: "button",
|
|
339
|
+
onClick: onEdit,
|
|
340
|
+
title: "Edit",
|
|
341
|
+
className: "rounded p-1 text-muted-foreground hover:text-foreground",
|
|
342
|
+
children: /* @__PURE__ */ jsx2(Pencil, { className: "h-3 w-3" })
|
|
343
|
+
}
|
|
344
|
+
),
|
|
345
|
+
onDelete && /* @__PURE__ */ jsx2(
|
|
346
|
+
"button",
|
|
347
|
+
{
|
|
348
|
+
type: "button",
|
|
349
|
+
onClick: onDelete,
|
|
350
|
+
title: "Delete",
|
|
351
|
+
className: "rounded p-1 text-muted-foreground hover:text-[var(--status-error,#ff4d6d)]",
|
|
352
|
+
children: /* @__PURE__ */ jsx2(Trash2, { className: "h-3 w-3" })
|
|
353
|
+
}
|
|
354
|
+
)
|
|
355
|
+
] })
|
|
356
|
+
]
|
|
357
|
+
}
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
function ProfileForm({
|
|
361
|
+
capabilities,
|
|
362
|
+
initial,
|
|
363
|
+
onCancel,
|
|
364
|
+
onSave
|
|
365
|
+
}) {
|
|
366
|
+
const [name, setName] = React.useState(initial?.name ?? "");
|
|
367
|
+
const [caps, setCaps] = React.useState(
|
|
368
|
+
initial?.capabilities ? [...initial.capabilities] : capabilities.map((c) => c.id)
|
|
369
|
+
);
|
|
370
|
+
const [instructions, setInstructions] = React.useState(initial?.instructions ?? "");
|
|
371
|
+
const toggle = (id) => setCaps(
|
|
372
|
+
(prev) => prev.includes(id) ? prev.filter((c) => c !== id) : [...prev, id]
|
|
373
|
+
);
|
|
374
|
+
return /* @__PURE__ */ jsxs2("div", { className: "space-y-3 p-2.5", children: [
|
|
375
|
+
/* @__PURE__ */ jsx2(
|
|
376
|
+
"input",
|
|
377
|
+
{
|
|
378
|
+
autoFocus: true,
|
|
379
|
+
value: name,
|
|
380
|
+
onChange: (event) => setName(event.target.value),
|
|
381
|
+
placeholder: "Agent name (e.g. Tax Reviewer)",
|
|
382
|
+
className: "w-full rounded-lg border border-[var(--md3-outline-variant)] bg-surface-container px-3 py-2 text-sm outline-none focus:border-primary"
|
|
383
|
+
}
|
|
384
|
+
),
|
|
385
|
+
capabilities.length > 0 && /* @__PURE__ */ jsxs2("div", { children: [
|
|
386
|
+
/* @__PURE__ */ jsx2("p", { className: "mb-1.5 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground/70", children: "Tools" }),
|
|
387
|
+
/* @__PURE__ */ jsx2("div", { className: "space-y-0.5", children: capabilities.map((cap) => /* @__PURE__ */ jsxs2(
|
|
388
|
+
"label",
|
|
389
|
+
{
|
|
390
|
+
className: "flex cursor-pointer items-start gap-2 rounded-md px-2 py-1.5 hover:bg-accent/40",
|
|
391
|
+
children: [
|
|
392
|
+
/* @__PURE__ */ jsx2(
|
|
393
|
+
"input",
|
|
394
|
+
{
|
|
395
|
+
type: "checkbox",
|
|
396
|
+
checked: caps.includes(cap.id),
|
|
397
|
+
onChange: () => toggle(cap.id),
|
|
398
|
+
className: "mt-0.5"
|
|
399
|
+
}
|
|
400
|
+
),
|
|
401
|
+
/* @__PURE__ */ jsxs2("span", { className: "min-w-0", children: [
|
|
402
|
+
/* @__PURE__ */ jsx2("span", { className: "block text-sm font-medium", children: cap.label }),
|
|
403
|
+
cap.description && /* @__PURE__ */ jsx2("span", { className: "block text-xs text-muted-foreground", children: cap.description })
|
|
404
|
+
] })
|
|
405
|
+
]
|
|
406
|
+
},
|
|
407
|
+
cap.id
|
|
408
|
+
)) })
|
|
409
|
+
] }),
|
|
410
|
+
/* @__PURE__ */ jsx2(
|
|
411
|
+
"textarea",
|
|
412
|
+
{
|
|
413
|
+
value: instructions,
|
|
414
|
+
onChange: (event) => setInstructions(event.target.value),
|
|
415
|
+
rows: 2,
|
|
416
|
+
placeholder: "Instructions (optional) \u2014 how this agent should behave",
|
|
417
|
+
className: "w-full resize-none rounded-lg border border-[var(--md3-outline-variant)] bg-surface-container px-3 py-2 text-sm outline-none focus:border-primary"
|
|
418
|
+
}
|
|
419
|
+
),
|
|
420
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex justify-end gap-2", children: [
|
|
421
|
+
/* @__PURE__ */ jsx2(
|
|
422
|
+
"button",
|
|
423
|
+
{
|
|
424
|
+
type: "button",
|
|
425
|
+
onClick: onCancel,
|
|
426
|
+
className: "rounded-lg px-3 py-1.5 text-sm text-muted-foreground hover:bg-accent/40",
|
|
427
|
+
children: "Cancel"
|
|
428
|
+
}
|
|
429
|
+
),
|
|
430
|
+
/* @__PURE__ */ jsx2(
|
|
431
|
+
"button",
|
|
432
|
+
{
|
|
433
|
+
type: "button",
|
|
434
|
+
disabled: !name.trim(),
|
|
435
|
+
onClick: () => onSave({
|
|
436
|
+
id: initial?.id,
|
|
437
|
+
name: name.trim(),
|
|
438
|
+
capabilities: caps,
|
|
439
|
+
instructions: instructions.trim()
|
|
440
|
+
}),
|
|
441
|
+
className: "rounded-lg bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground transition-opacity hover:opacity-90 disabled:opacity-40",
|
|
442
|
+
children: "Save agent"
|
|
443
|
+
}
|
|
444
|
+
)
|
|
445
|
+
] })
|
|
446
|
+
] });
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
// src/chat/agent-session-controls.tsx
|
|
450
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
166
451
|
function HarnessDropdown({
|
|
167
452
|
value,
|
|
168
453
|
onChange,
|
|
@@ -179,8 +464,8 @@ function HarnessDropdown({
|
|
|
179
464
|
);
|
|
180
465
|
const options = HARNESS_OPTIONS.filter((h) => allowed.has(h.type));
|
|
181
466
|
const selected = options.find((option) => option.type === value);
|
|
182
|
-
return /* @__PURE__ */
|
|
183
|
-
/* @__PURE__ */
|
|
467
|
+
return /* @__PURE__ */ jsxs3(DropdownMenu2.Root, { children: [
|
|
468
|
+
/* @__PURE__ */ jsx3(DropdownMenu2.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs3(
|
|
184
469
|
"button",
|
|
185
470
|
{
|
|
186
471
|
type: "button",
|
|
@@ -195,13 +480,13 @@ function HarnessDropdown({
|
|
|
195
480
|
),
|
|
196
481
|
"aria-label": "Agent harness",
|
|
197
482
|
children: [
|
|
198
|
-
locked ? /* @__PURE__ */
|
|
199
|
-
/* @__PURE__ */
|
|
200
|
-
!locked && /* @__PURE__ */
|
|
483
|
+
locked ? /* @__PURE__ */ jsx3(Lock, { className: "h-3 w-3 text-muted-foreground" }) : /* @__PURE__ */ jsx3(HarnessLogo, { type: value, size: 16 }),
|
|
484
|
+
/* @__PURE__ */ jsx3("span", { children: selected?.label ?? value }),
|
|
485
|
+
!locked && /* @__PURE__ */ jsx3(ChevronDown3, { className: "h-3.5 w-3.5 text-muted-foreground" })
|
|
201
486
|
]
|
|
202
487
|
}
|
|
203
488
|
) }),
|
|
204
|
-
/* @__PURE__ */
|
|
489
|
+
/* @__PURE__ */ jsx3(DropdownMenu2.Portal, { children: /* @__PURE__ */ jsx3(
|
|
205
490
|
DropdownMenu2.Content,
|
|
206
491
|
{
|
|
207
492
|
side,
|
|
@@ -219,7 +504,7 @@ function HarnessDropdown({
|
|
|
219
504
|
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
220
505
|
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95"
|
|
221
506
|
),
|
|
222
|
-
children: options.map((option) => /* @__PURE__ */
|
|
507
|
+
children: options.map((option) => /* @__PURE__ */ jsxs3(
|
|
223
508
|
DropdownMenu2.Item,
|
|
224
509
|
{
|
|
225
510
|
onSelect: (event) => {
|
|
@@ -232,10 +517,10 @@ function HarnessDropdown({
|
|
|
232
517
|
option.type === value && "bg-primary/10 font-medium text-foreground ring-1 ring-inset ring-primary/25 hover:bg-primary/15 focus:bg-primary/15"
|
|
233
518
|
),
|
|
234
519
|
children: [
|
|
235
|
-
/* @__PURE__ */
|
|
236
|
-
/* @__PURE__ */
|
|
237
|
-
/* @__PURE__ */
|
|
238
|
-
option.description && /* @__PURE__ */
|
|
520
|
+
/* @__PURE__ */ jsx3(HarnessLogo, { type: option.type, size: 20, className: "mt-0.5" }),
|
|
521
|
+
/* @__PURE__ */ jsxs3("span", { className: "flex min-w-0 flex-col gap-0.5", children: [
|
|
522
|
+
/* @__PURE__ */ jsx3("span", { className: "text-sm font-medium", children: option.label }),
|
|
523
|
+
option.description && /* @__PURE__ */ jsx3("span", { className: "text-xs text-muted-foreground", children: option.description })
|
|
239
524
|
] })
|
|
240
525
|
]
|
|
241
526
|
},
|
|
@@ -247,6 +532,7 @@ function HarnessDropdown({
|
|
|
247
532
|
}
|
|
248
533
|
function AgentSessionControls({
|
|
249
534
|
harness,
|
|
535
|
+
profile,
|
|
250
536
|
model,
|
|
251
537
|
reasoning,
|
|
252
538
|
trailing,
|
|
@@ -255,7 +541,7 @@ function AgentSessionControls({
|
|
|
255
541
|
layout = "inline",
|
|
256
542
|
menuPlacement = "auto"
|
|
257
543
|
}) {
|
|
258
|
-
if (!harness && !model && !reasoning && !trailing) return null;
|
|
544
|
+
if (!harness && !profile && !model && !reasoning && !trailing) return null;
|
|
259
545
|
const handleHarnessChange = (next) => {
|
|
260
546
|
harness?.onChange(next);
|
|
261
547
|
if (model) {
|
|
@@ -281,7 +567,7 @@ function AgentSessionControls({
|
|
|
281
567
|
const menuAlign = layout === "gear" ? "end" : "start";
|
|
282
568
|
const inlineForceDown = menuPlacement === "down" && layout !== "gear";
|
|
283
569
|
const avoidCollisions = inlineForceDown ? false : void 0;
|
|
284
|
-
const harnessNode = harness && /* @__PURE__ */
|
|
570
|
+
const harnessNode = harness && /* @__PURE__ */ jsx3(
|
|
285
571
|
HarnessDropdown,
|
|
286
572
|
{
|
|
287
573
|
...harness,
|
|
@@ -292,7 +578,21 @@ function AgentSessionControls({
|
|
|
292
578
|
avoidCollisions
|
|
293
579
|
}
|
|
294
580
|
);
|
|
295
|
-
const
|
|
581
|
+
const profileNode = profile && /* @__PURE__ */ jsx3(
|
|
582
|
+
AgentProfilePicker,
|
|
583
|
+
{
|
|
584
|
+
value: profile.value,
|
|
585
|
+
onChange: profile.onChange,
|
|
586
|
+
profiles: profile.profiles,
|
|
587
|
+
capabilities: profile.capabilities,
|
|
588
|
+
onCreate: profile.onCreate,
|
|
589
|
+
onUpdate: profile.onUpdate,
|
|
590
|
+
onDelete: profile.onDelete,
|
|
591
|
+
disabled: profile.disabled,
|
|
592
|
+
side: inlineForceDown || layout === "gear" ? "bottom" : "top"
|
|
593
|
+
}
|
|
594
|
+
);
|
|
595
|
+
const modelNode = model && /* @__PURE__ */ jsx3(
|
|
296
596
|
ModelPicker,
|
|
297
597
|
{
|
|
298
598
|
variant: "pill",
|
|
@@ -315,7 +615,7 @@ function AgentSessionControls({
|
|
|
315
615
|
supportsReasoning: selectedModel.supportsReasoning,
|
|
316
616
|
maxEffort: selectedModel.maxReasoningEffort
|
|
317
617
|
} : null;
|
|
318
|
-
const reasoningNode = reasoning && /* @__PURE__ */
|
|
618
|
+
const reasoningNode = reasoning && /* @__PURE__ */ jsx3(
|
|
319
619
|
ReasoningLevelPicker,
|
|
320
620
|
{
|
|
321
621
|
value: reasoning.value,
|
|
@@ -328,10 +628,11 @@ function AgentSessionControls({
|
|
|
328
628
|
}
|
|
329
629
|
);
|
|
330
630
|
if (layout === "gear") {
|
|
331
|
-
return /* @__PURE__ */
|
|
631
|
+
return /* @__PURE__ */ jsx3(
|
|
332
632
|
GearControls,
|
|
333
633
|
{
|
|
334
634
|
className,
|
|
635
|
+
profileNode,
|
|
335
636
|
harnessNode,
|
|
336
637
|
modelNode,
|
|
337
638
|
reasoningNode,
|
|
@@ -339,36 +640,38 @@ function AgentSessionControls({
|
|
|
339
640
|
}
|
|
340
641
|
);
|
|
341
642
|
}
|
|
342
|
-
return /* @__PURE__ */
|
|
643
|
+
return /* @__PURE__ */ jsxs3(
|
|
343
644
|
"div",
|
|
344
645
|
{
|
|
345
646
|
className: cn("flex flex-wrap items-center gap-2", className),
|
|
346
647
|
"data-testid": "agent-session-controls",
|
|
347
648
|
children: [
|
|
649
|
+
profileNode,
|
|
348
650
|
harnessNode,
|
|
349
651
|
modelNode,
|
|
350
652
|
reasoningNode,
|
|
351
|
-
trailing && /* @__PURE__ */
|
|
653
|
+
trailing && /* @__PURE__ */ jsx3("div", { className: "ml-auto flex items-center gap-2", children: trailing })
|
|
352
654
|
]
|
|
353
655
|
}
|
|
354
656
|
);
|
|
355
657
|
}
|
|
356
658
|
function GearControls({
|
|
357
659
|
className,
|
|
660
|
+
profileNode,
|
|
358
661
|
harnessNode,
|
|
359
662
|
modelNode,
|
|
360
663
|
reasoningNode,
|
|
361
664
|
trailing
|
|
362
665
|
}) {
|
|
363
|
-
return /* @__PURE__ */
|
|
666
|
+
return /* @__PURE__ */ jsxs3(
|
|
364
667
|
"div",
|
|
365
668
|
{
|
|
366
669
|
className: cn("flex items-center gap-2", className),
|
|
367
670
|
"data-testid": "agent-session-controls",
|
|
368
671
|
children: [
|
|
369
|
-
trailing && /* @__PURE__ */
|
|
370
|
-
/* @__PURE__ */
|
|
371
|
-
/* @__PURE__ */
|
|
672
|
+
trailing && /* @__PURE__ */ jsx3("div", { className: "flex items-center gap-2", children: trailing }),
|
|
673
|
+
/* @__PURE__ */ jsxs3(DropdownMenu2.Root, { children: [
|
|
674
|
+
/* @__PURE__ */ jsx3(DropdownMenu2.Trigger, { asChild: true, children: /* @__PURE__ */ jsx3(
|
|
372
675
|
"button",
|
|
373
676
|
{
|
|
374
677
|
type: "button",
|
|
@@ -379,10 +682,10 @@ function GearControls({
|
|
|
379
682
|
"hover:border-[var(--md3-outline-variant)] hover:bg-surface-container-high focus:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
380
683
|
"data-[state=open]:border-[var(--md3-outline-variant)] data-[state=open]:bg-surface-container-high"
|
|
381
684
|
),
|
|
382
|
-
children: /* @__PURE__ */
|
|
685
|
+
children: /* @__PURE__ */ jsx3(SlidersHorizontal, { className: "h-4 w-4 text-muted-foreground" })
|
|
383
686
|
}
|
|
384
687
|
) }),
|
|
385
|
-
/* @__PURE__ */
|
|
688
|
+
/* @__PURE__ */ jsx3(DropdownMenu2.Portal, { children: /* @__PURE__ */ jsxs3(
|
|
386
689
|
DropdownMenu2.Content,
|
|
387
690
|
{
|
|
388
691
|
side: "top",
|
|
@@ -404,9 +707,10 @@ function GearControls({
|
|
|
404
707
|
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95"
|
|
405
708
|
),
|
|
406
709
|
children: [
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
710
|
+
profileNode && /* @__PURE__ */ jsx3(GearSection, { label: "Agent", children: profileNode }),
|
|
711
|
+
harnessNode && /* @__PURE__ */ jsx3(GearSection, { label: "Harness", children: harnessNode }),
|
|
712
|
+
modelNode && /* @__PURE__ */ jsx3(GearSection, { label: "Model", children: modelNode }),
|
|
713
|
+
reasoningNode && /* @__PURE__ */ jsx3(GearSection, { label: "Effort", children: reasoningNode })
|
|
410
714
|
]
|
|
411
715
|
}
|
|
412
716
|
) })
|
|
@@ -419,17 +723,123 @@ function GearSection({
|
|
|
419
723
|
label,
|
|
420
724
|
children
|
|
421
725
|
}) {
|
|
422
|
-
return /* @__PURE__ */
|
|
423
|
-
/* @__PURE__ */
|
|
726
|
+
return /* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-1", children: [
|
|
727
|
+
/* @__PURE__ */ jsx3("span", { className: "px-0.5 text-[10px] font-medium uppercase tracking-wide text-muted-foreground/70", children: label }),
|
|
424
728
|
children
|
|
425
729
|
] });
|
|
426
730
|
}
|
|
427
731
|
|
|
732
|
+
// src/chat/agent-composer.tsx
|
|
733
|
+
import { ArrowUp, Loader2 } from "lucide-react";
|
|
734
|
+
import * as React2 from "react";
|
|
735
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
736
|
+
function AgentComposer({
|
|
737
|
+
value,
|
|
738
|
+
onChange,
|
|
739
|
+
onSubmit,
|
|
740
|
+
placeholder = "Send a message\u2026",
|
|
741
|
+
disabled,
|
|
742
|
+
busy,
|
|
743
|
+
harness,
|
|
744
|
+
profile,
|
|
745
|
+
model,
|
|
746
|
+
reasoning,
|
|
747
|
+
context = "chat",
|
|
748
|
+
trailing,
|
|
749
|
+
minRows = 2,
|
|
750
|
+
maxHeight = 200,
|
|
751
|
+
className,
|
|
752
|
+
sendLabel = "Send",
|
|
753
|
+
autoFocus
|
|
754
|
+
}) {
|
|
755
|
+
const textareaRef = React2.useRef(null);
|
|
756
|
+
const resize = React2.useCallback(
|
|
757
|
+
(el) => {
|
|
758
|
+
el.style.height = "auto";
|
|
759
|
+
el.style.height = `${Math.min(el.scrollHeight, maxHeight)}px`;
|
|
760
|
+
},
|
|
761
|
+
[maxHeight]
|
|
762
|
+
);
|
|
763
|
+
React2.useEffect(() => {
|
|
764
|
+
if (textareaRef.current) resize(textareaRef.current);
|
|
765
|
+
}, [value, resize]);
|
|
766
|
+
const canSend = !disabled && !busy && value.trim().length > 0;
|
|
767
|
+
const submit = () => {
|
|
768
|
+
if (!canSend) return;
|
|
769
|
+
onSubmit();
|
|
770
|
+
};
|
|
771
|
+
return /* @__PURE__ */ jsxs4(
|
|
772
|
+
"div",
|
|
773
|
+
{
|
|
774
|
+
"data-testid": "agent-composer",
|
|
775
|
+
className: cn(
|
|
776
|
+
"flex flex-col gap-2 rounded-2xl border border-[var(--md3-outline-variant)] bg-surface-container-high p-2.5 shadow-sm transition-colors",
|
|
777
|
+
"focus-within:border-primary/60",
|
|
778
|
+
disabled && "opacity-60",
|
|
779
|
+
className
|
|
780
|
+
),
|
|
781
|
+
children: [
|
|
782
|
+
/* @__PURE__ */ jsx4(
|
|
783
|
+
"textarea",
|
|
784
|
+
{
|
|
785
|
+
ref: textareaRef,
|
|
786
|
+
rows: minRows,
|
|
787
|
+
value,
|
|
788
|
+
disabled,
|
|
789
|
+
autoFocus,
|
|
790
|
+
onChange: (event) => onChange(event.target.value),
|
|
791
|
+
onInput: (event) => resize(event.currentTarget),
|
|
792
|
+
onKeyDown: (event) => {
|
|
793
|
+
if (event.key === "Enter" && !event.shiftKey && !event.nativeEvent.isComposing && event.keyCode !== 229) {
|
|
794
|
+
event.preventDefault();
|
|
795
|
+
submit();
|
|
796
|
+
}
|
|
797
|
+
},
|
|
798
|
+
placeholder,
|
|
799
|
+
className: cn(
|
|
800
|
+
"w-full resize-none bg-transparent px-2 py-1 text-sm leading-relaxed text-foreground outline-none",
|
|
801
|
+
"placeholder:text-muted-foreground"
|
|
802
|
+
)
|
|
803
|
+
}
|
|
804
|
+
),
|
|
805
|
+
/* @__PURE__ */ jsxs4("div", { className: "flex items-end gap-2", children: [
|
|
806
|
+
/* @__PURE__ */ jsx4(
|
|
807
|
+
AgentSessionControls,
|
|
808
|
+
{
|
|
809
|
+
className: "min-w-0 flex-1",
|
|
810
|
+
context,
|
|
811
|
+
harness,
|
|
812
|
+
profile,
|
|
813
|
+
model,
|
|
814
|
+
reasoning
|
|
815
|
+
}
|
|
816
|
+
),
|
|
817
|
+
trailing && /* @__PURE__ */ jsx4("div", { className: "flex shrink-0 items-center gap-2", children: trailing }),
|
|
818
|
+
/* @__PURE__ */ jsx4(
|
|
819
|
+
"button",
|
|
820
|
+
{
|
|
821
|
+
type: "button",
|
|
822
|
+
onClick: submit,
|
|
823
|
+
disabled: !canSend,
|
|
824
|
+
"aria-label": sendLabel,
|
|
825
|
+
className: cn(
|
|
826
|
+
"ml-auto flex size-9 shrink-0 items-center justify-center rounded-full bg-primary text-primary-foreground",
|
|
827
|
+
"transition-opacity hover:opacity-90 disabled:opacity-40"
|
|
828
|
+
),
|
|
829
|
+
children: busy ? /* @__PURE__ */ jsx4(Loader2, { className: "size-4 animate-spin" }) : /* @__PURE__ */ jsx4(ArrowUp, { className: "size-4" })
|
|
830
|
+
}
|
|
831
|
+
)
|
|
832
|
+
] })
|
|
833
|
+
]
|
|
834
|
+
}
|
|
835
|
+
);
|
|
836
|
+
}
|
|
837
|
+
|
|
428
838
|
// src/chat/artifact-agent-dock.tsx
|
|
429
|
-
import * as
|
|
839
|
+
import * as React3 from "react";
|
|
430
840
|
import { Sparkles as Sparkles2, Send, Square, X } from "lucide-react";
|
|
431
841
|
import { ChatMessage } from "@tangle-network/ui/chat";
|
|
432
|
-
import { jsx as
|
|
842
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
433
843
|
function defaultScopeLabel(scope) {
|
|
434
844
|
if (scope.label) return scope.label;
|
|
435
845
|
switch (scope.kind) {
|
|
@@ -475,23 +885,23 @@ function ArtifactAgentDock({
|
|
|
475
885
|
onError,
|
|
476
886
|
className
|
|
477
887
|
}) {
|
|
478
|
-
const [threadId, setThreadId] =
|
|
479
|
-
const [messages, setMessages] =
|
|
480
|
-
const [composer, setComposer] =
|
|
481
|
-
const [streamContent, setStreamContent] =
|
|
482
|
-
const [sending, setSending] =
|
|
483
|
-
const [loading, setLoading] =
|
|
484
|
-
const abortRef =
|
|
485
|
-
const scrollRef =
|
|
486
|
-
const scopeTokenRef =
|
|
487
|
-
const reportError =
|
|
888
|
+
const [threadId, setThreadId] = React3.useState(null);
|
|
889
|
+
const [messages, setMessages] = React3.useState([]);
|
|
890
|
+
const [composer, setComposer] = React3.useState(defaultPrompt ?? "");
|
|
891
|
+
const [streamContent, setStreamContent] = React3.useState("");
|
|
892
|
+
const [sending, setSending] = React3.useState(false);
|
|
893
|
+
const [loading, setLoading] = React3.useState(false);
|
|
894
|
+
const abortRef = React3.useRef(null);
|
|
895
|
+
const scrollRef = React3.useRef(null);
|
|
896
|
+
const scopeTokenRef = React3.useRef(0);
|
|
897
|
+
const reportError = React3.useCallback(
|
|
488
898
|
(message) => {
|
|
489
899
|
if (onError) onError(message);
|
|
490
900
|
else if (typeof console !== "undefined") console.error("[ArtifactAgentDock]", message);
|
|
491
901
|
},
|
|
492
902
|
[onError]
|
|
493
903
|
);
|
|
494
|
-
|
|
904
|
+
React3.useEffect(() => {
|
|
495
905
|
if (!open) return;
|
|
496
906
|
scopeTokenRef.current += 1;
|
|
497
907
|
abortRef.current?.abort();
|
|
@@ -527,11 +937,11 @@ function ArtifactAgentDock({
|
|
|
527
937
|
cancelled = true;
|
|
528
938
|
};
|
|
529
939
|
}, [open, scope.kind, scope.key, transport, reportError]);
|
|
530
|
-
|
|
940
|
+
React3.useEffect(() => {
|
|
531
941
|
if (!scrollRef.current) return;
|
|
532
942
|
scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
|
|
533
943
|
}, [messages.length, streamContent]);
|
|
534
|
-
const send =
|
|
944
|
+
const send = React3.useCallback(async () => {
|
|
535
945
|
const text = composer.trim();
|
|
536
946
|
if (!text || !threadId || sending) return;
|
|
537
947
|
const token = scopeTokenRef.current;
|
|
@@ -581,7 +991,7 @@ function ArtifactAgentDock({
|
|
|
581
991
|
if (abortRef.current === controller) abortRef.current = null;
|
|
582
992
|
}
|
|
583
993
|
}, [composer, threadId, sending, transport, reportError]);
|
|
584
|
-
const cancel =
|
|
994
|
+
const cancel = React3.useCallback(() => {
|
|
585
995
|
if (threadId && transport.cancel) {
|
|
586
996
|
try {
|
|
587
997
|
void Promise.resolve(transport.cancel({ threadId })).catch(() => {
|
|
@@ -595,7 +1005,7 @@ function ArtifactAgentDock({
|
|
|
595
1005
|
}, [threadId, transport]);
|
|
596
1006
|
if (!open) return null;
|
|
597
1007
|
const heading = defaultScopeLabel(scope);
|
|
598
|
-
return /* @__PURE__ */
|
|
1008
|
+
return /* @__PURE__ */ jsxs5(
|
|
599
1009
|
"aside",
|
|
600
1010
|
{
|
|
601
1011
|
className: cn(
|
|
@@ -604,38 +1014,38 @@ function ArtifactAgentDock({
|
|
|
604
1014
|
),
|
|
605
1015
|
"aria-label": `Agent chat about ${heading}`,
|
|
606
1016
|
children: [
|
|
607
|
-
/* @__PURE__ */
|
|
608
|
-
/* @__PURE__ */
|
|
609
|
-
/* @__PURE__ */
|
|
610
|
-
/* @__PURE__ */
|
|
611
|
-
/* @__PURE__ */
|
|
612
|
-
/* @__PURE__ */
|
|
1017
|
+
/* @__PURE__ */ jsxs5("header", { className: "flex items-center justify-between border-b border-[var(--md3-outline-variant)] bg-surface-container-low px-4 py-3", children: [
|
|
1018
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
1019
|
+
/* @__PURE__ */ jsx5(Sparkles2, { className: "h-4 w-4 shrink-0 text-muted-foreground" }),
|
|
1020
|
+
/* @__PURE__ */ jsxs5("div", { className: "min-w-0", children: [
|
|
1021
|
+
/* @__PURE__ */ jsx5("div", { className: "text-[10px] font-medium uppercase tracking-wider text-muted-foreground", children: "Discussing" }),
|
|
1022
|
+
/* @__PURE__ */ jsx5("div", { className: "truncate text-sm font-semibold text-foreground", children: heading })
|
|
613
1023
|
] })
|
|
614
1024
|
] }),
|
|
615
|
-
/* @__PURE__ */
|
|
1025
|
+
/* @__PURE__ */ jsx5(
|
|
616
1026
|
"button",
|
|
617
1027
|
{
|
|
618
1028
|
type: "button",
|
|
619
1029
|
onClick: () => onOpenChange(false),
|
|
620
1030
|
"aria-label": "Close artifact chat",
|
|
621
1031
|
className: "rounded-md p-1 text-muted-foreground transition-colors hover:bg-surface-container-high hover:text-foreground",
|
|
622
|
-
children: /* @__PURE__ */
|
|
1032
|
+
children: /* @__PURE__ */ jsx5(X, { className: "h-4 w-4" })
|
|
623
1033
|
}
|
|
624
1034
|
)
|
|
625
1035
|
] }),
|
|
626
|
-
/* @__PURE__ */
|
|
627
|
-
/* @__PURE__ */
|
|
628
|
-
/* @__PURE__ */
|
|
1036
|
+
/* @__PURE__ */ jsx5("div", { ref: scrollRef, className: "flex-1 overflow-y-auto px-3 py-4", children: loading ? /* @__PURE__ */ jsx5("div", { className: "px-3 py-8 text-center text-xs text-muted-foreground", children: "Loading conversation\u2026" }) : messages.length === 0 && !streamContent ? /* @__PURE__ */ jsxs5("div", { className: "px-3 py-12 text-center", children: [
|
|
1037
|
+
/* @__PURE__ */ jsx5(Sparkles2, { className: "mx-auto mb-3 h-5 w-5 text-muted-foreground/40" }),
|
|
1038
|
+
/* @__PURE__ */ jsxs5("p", { className: "text-sm text-foreground", children: [
|
|
629
1039
|
"Ask the agent about this ",
|
|
630
1040
|
scope.kind === "vault-file" ? "document" : scope.kind,
|
|
631
1041
|
"."
|
|
632
1042
|
] }),
|
|
633
|
-
/* @__PURE__ */
|
|
634
|
-
] }) : /* @__PURE__ */
|
|
635
|
-
messages.map((m) => /* @__PURE__ */
|
|
636
|
-
streamContent && /* @__PURE__ */
|
|
1043
|
+
/* @__PURE__ */ jsx5("p", { className: "mt-1 text-xs text-muted-foreground", children: "It can read the current contents and propose edits, rewrites, or follow-ups." })
|
|
1044
|
+
] }) : /* @__PURE__ */ jsxs5("div", { className: "space-y-3", children: [
|
|
1045
|
+
messages.map((m) => /* @__PURE__ */ jsx5(ChatMessage, { role: m.role, content: m.content, timestamp: m.createdAt }, m.id)),
|
|
1046
|
+
streamContent && /* @__PURE__ */ jsx5(ChatMessage, { role: "assistant", content: streamContent, isStreaming: true })
|
|
637
1047
|
] }) }),
|
|
638
|
-
/* @__PURE__ */
|
|
1048
|
+
/* @__PURE__ */ jsx5(
|
|
639
1049
|
"form",
|
|
640
1050
|
{
|
|
641
1051
|
className: "border-t border-[var(--md3-outline-variant)] bg-surface-container-low p-3",
|
|
@@ -643,8 +1053,8 @@ function ArtifactAgentDock({
|
|
|
643
1053
|
e.preventDefault();
|
|
644
1054
|
void send();
|
|
645
1055
|
},
|
|
646
|
-
children: /* @__PURE__ */
|
|
647
|
-
/* @__PURE__ */
|
|
1056
|
+
children: /* @__PURE__ */ jsxs5("div", { className: "flex items-end gap-2", children: [
|
|
1057
|
+
/* @__PURE__ */ jsx5(
|
|
648
1058
|
"textarea",
|
|
649
1059
|
{
|
|
650
1060
|
value: composer,
|
|
@@ -661,23 +1071,23 @@ function ArtifactAgentDock({
|
|
|
661
1071
|
className: "min-h-[44px] flex-1 resize-none rounded-[20px] border border-[var(--md3-outline-variant)] bg-surface-dim px-3.5 py-2 text-sm text-foreground placeholder:text-muted-foreground transition-colors focus:outline-none focus:border-[var(--border-accent)] disabled:opacity-50"
|
|
662
1072
|
}
|
|
663
1073
|
),
|
|
664
|
-
sending ? /* @__PURE__ */
|
|
1074
|
+
sending ? /* @__PURE__ */ jsx5(
|
|
665
1075
|
"button",
|
|
666
1076
|
{
|
|
667
1077
|
type: "button",
|
|
668
1078
|
onClick: cancel,
|
|
669
1079
|
"aria-label": "Cancel",
|
|
670
1080
|
className: "inline-flex h-9 w-9 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-surface-container-high hover:text-foreground",
|
|
671
|
-
children: /* @__PURE__ */
|
|
1081
|
+
children: /* @__PURE__ */ jsx5(Square, { className: "h-4 w-4" })
|
|
672
1082
|
}
|
|
673
|
-
) : /* @__PURE__ */
|
|
1083
|
+
) : /* @__PURE__ */ jsx5(
|
|
674
1084
|
"button",
|
|
675
1085
|
{
|
|
676
1086
|
type: "submit",
|
|
677
1087
|
disabled: !composer.trim() || !threadId,
|
|
678
1088
|
"aria-label": "Send",
|
|
679
1089
|
className: "inline-flex h-9 w-9 items-center justify-center rounded-full bg-primary text-primary-foreground transition-colors hover:bg-primary/90 disabled:opacity-50",
|
|
680
|
-
children: /* @__PURE__ */
|
|
1090
|
+
children: /* @__PURE__ */ jsx5(Send, { className: "h-4 w-4" })
|
|
681
1091
|
}
|
|
682
1092
|
)
|
|
683
1093
|
] })
|
|
@@ -770,7 +1180,9 @@ export {
|
|
|
770
1180
|
snapModelToHarness,
|
|
771
1181
|
modelProvider,
|
|
772
1182
|
snapHarnessToModel,
|
|
1183
|
+
AgentProfilePicker,
|
|
773
1184
|
AgentSessionControls,
|
|
1185
|
+
AgentComposer,
|
|
774
1186
|
ArtifactAgentDock,
|
|
775
1187
|
createFetchTransport,
|
|
776
1188
|
AgentTimeline,
|
package/dist/globals.css
CHANGED
|
@@ -404,6 +404,9 @@
|
|
|
404
404
|
.bottom-\[-0\.75rem\] {
|
|
405
405
|
bottom: -0.75rem;
|
|
406
406
|
}
|
|
407
|
+
.bottom-full {
|
|
408
|
+
bottom: 100%;
|
|
409
|
+
}
|
|
407
410
|
.left-0 {
|
|
408
411
|
left: calc(var(--spacing) * 0);
|
|
409
412
|
}
|
|
@@ -660,6 +663,14 @@
|
|
|
660
663
|
width: calc(var(--spacing) * 3);
|
|
661
664
|
height: calc(var(--spacing) * 3);
|
|
662
665
|
}
|
|
666
|
+
.size-4 {
|
|
667
|
+
width: calc(var(--spacing) * 4);
|
|
668
|
+
height: calc(var(--spacing) * 4);
|
|
669
|
+
}
|
|
670
|
+
.size-9 {
|
|
671
|
+
width: calc(var(--spacing) * 9);
|
|
672
|
+
height: calc(var(--spacing) * 9);
|
|
673
|
+
}
|
|
663
674
|
.\!h-2 {
|
|
664
675
|
height: calc(var(--spacing) * 2) !important;
|
|
665
676
|
}
|
|
@@ -825,6 +836,9 @@
|
|
|
825
836
|
.max-h-\[160px\] {
|
|
826
837
|
max-height: 160px;
|
|
827
838
|
}
|
|
839
|
+
.max-h-\[min\(60vh\,420px\)\] {
|
|
840
|
+
max-height: min(60vh, 420px);
|
|
841
|
+
}
|
|
828
842
|
.max-h-\[min\(440px\,var\(--radix-dropdown-menu-content-available-height\)\)\] {
|
|
829
843
|
max-height: min(440px, var(--radix-dropdown-menu-content-available-height));
|
|
830
844
|
}
|
|
@@ -885,6 +899,9 @@
|
|
|
885
899
|
.min-h-\[300px\] {
|
|
886
900
|
min-height: 300px;
|
|
887
901
|
}
|
|
902
|
+
.min-h-\[640px\] {
|
|
903
|
+
min-height: 640px;
|
|
904
|
+
}
|
|
888
905
|
.min-h-full {
|
|
889
906
|
min-height: 100%;
|
|
890
907
|
}
|
|
@@ -1050,6 +1067,9 @@
|
|
|
1050
1067
|
.w-\[300px\] {
|
|
1051
1068
|
width: 300px;
|
|
1052
1069
|
}
|
|
1070
|
+
.w-\[320px\] {
|
|
1071
|
+
width: 320px;
|
|
1072
|
+
}
|
|
1053
1073
|
.w-\[360px\] {
|
|
1054
1074
|
width: 360px;
|
|
1055
1075
|
}
|
|
@@ -3375,6 +3395,9 @@
|
|
|
3375
3395
|
.accent-primary {
|
|
3376
3396
|
accent-color: var(--color-primary);
|
|
3377
3397
|
}
|
|
3398
|
+
.\[color-scheme\:dark\] {
|
|
3399
|
+
color-scheme: dark;
|
|
3400
|
+
}
|
|
3378
3401
|
.opacity-0 {
|
|
3379
3402
|
opacity: 0%;
|
|
3380
3403
|
}
|
|
@@ -3839,6 +3862,14 @@
|
|
|
3839
3862
|
border-color: var(--color-border);
|
|
3840
3863
|
}
|
|
3841
3864
|
}
|
|
3865
|
+
.focus-within\:border-primary\/60 {
|
|
3866
|
+
&:focus-within {
|
|
3867
|
+
border-color: color-mix(in srgb, hsl(var(--primary)) 60%, transparent);
|
|
3868
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
3869
|
+
border-color: color-mix(in oklab, var(--color-primary) 60%, transparent);
|
|
3870
|
+
}
|
|
3871
|
+
}
|
|
3872
|
+
}
|
|
3842
3873
|
.focus-within\:shadow-\[var\(--chat-input-focus-shadow\,0_10px_30px_rgba\(15\,23\,42\,0\.08\)\)\] {
|
|
3843
3874
|
&:focus-within {
|
|
3844
3875
|
--tw-shadow: var(--chat-input-focus-shadow,0 10px 30px rgba(15,23,42,0.08));
|
|
@@ -4355,6 +4386,13 @@
|
|
|
4355
4386
|
}
|
|
4356
4387
|
}
|
|
4357
4388
|
}
|
|
4389
|
+
.hover\:text-\[var\(--status-error\,\#ff4d6d\)\] {
|
|
4390
|
+
&:hover {
|
|
4391
|
+
@media (hover: hover) {
|
|
4392
|
+
color: var(--status-error,#ff4d6d);
|
|
4393
|
+
}
|
|
4394
|
+
}
|
|
4395
|
+
}
|
|
4358
4396
|
.hover\:text-\[var\(--surface-danger-text\)\] {
|
|
4359
4397
|
&:hover {
|
|
4360
4398
|
@media (hover: hover) {
|
|
@@ -4475,6 +4513,11 @@
|
|
|
4475
4513
|
border-color: var(--border-accent-hover);
|
|
4476
4514
|
}
|
|
4477
4515
|
}
|
|
4516
|
+
.focus\:border-primary {
|
|
4517
|
+
&:focus {
|
|
4518
|
+
border-color: var(--color-primary);
|
|
4519
|
+
}
|
|
4520
|
+
}
|
|
4478
4521
|
.focus\:bg-accent {
|
|
4479
4522
|
&:focus {
|
|
4480
4523
|
background-color: var(--color-accent);
|
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export { AgentWorkbench, ApprovalConfidenceStat, ApprovalItem, ApprovalQueue, Ap
|
|
|
5
5
|
export { ArtifactView, BRAND_PRISM_THEME, CodeSurface, CodeSurfaceProps, CodeView, CodeViewProps, DiffStats, DiffView, DiffViewProps, FileBreadcrumb, FileBreadcrumbProps, GitStatusBadge, PanelHeader, PanelHeaderProps, PillTabItem, PillTabs, PillTabsProps, PreviewView, PreviewViewProps, SandboxArtifact, SandboxArtifactPane, SandboxArtifactPaneProps, SandboxArtifactTerminal, buildUnifiedPatch, computeDiffStats, resolveLanguage } from './workbench.js';
|
|
6
6
|
export { OpenUIAction, OpenUIActionsNode, OpenUIArtifactRenderer, OpenUIArtifactRendererProps, OpenUIBadgeNode, OpenUICardNode, OpenUICodeNode, OpenUIComponentNode, OpenUIGridNode, OpenUIHeadingNode, OpenUIKeyValueNode, OpenUIMarkdownNode, OpenUIPrimitive, OpenUISeparatorNode, OpenUIStackNode, OpenUIStatNode, OpenUITableNode, OpenUITextNode } from '@tangle-network/ui/openui';
|
|
7
7
|
export { AgentTimeline, AgentTimelineArtifactItem, AgentTimelineCustomItem, AgentTimelineItem, AgentTimelineMessageItem, AgentTimelineProps, AgentTimelineStatusItem, AgentTimelineTone, AgentTimelineToolGroupItem, AgentTimelineToolItem, ChatContainer, ChatContainerProps, ChatInput, ChatInputProps, ChatMessage, ChatMessageProps, MessageList, MessageListProps, MessageRole, PendingFile, ThinkingIndicator, ThinkingIndicatorProps, UserMessage, UserMessageProps } from '@tangle-network/ui/chat';
|
|
8
|
-
export { AgentSessionControls, AgentSessionControlsProps, AgentSessionHarnessControl, AgentSessionModelControl, AgentSessionReasoningControl, ArtifactAgentDock, ArtifactAgentDockProps, ArtifactAgentDockTransport, ArtifactDockMessage, ArtifactDockStreamEvent, ArtifactKind, ArtifactScope, DEFAULT_REASONING_LEVEL_OPTIONS, ReasoningLevel, ReasoningLevelOption, ReasoningLevelPicker, ReasoningLevelPickerProps, createFetchTransport, isModelCompatibleWithHarness, snapModelToHarness } from './chat.js';
|
|
8
|
+
export { AgentComposer, AgentComposerProps, AgentProfileCapability, AgentProfileDraft, AgentProfileOption, AgentProfilePicker, AgentProfilePickerProps, AgentSessionControls, AgentSessionControlsProps, AgentSessionHarnessControl, AgentSessionModelControl, AgentSessionProfileControl, AgentSessionReasoningControl, ArtifactAgentDock, ArtifactAgentDockProps, ArtifactAgentDockTransport, ArtifactDockMessage, ArtifactDockStreamEvent, ArtifactKind, ArtifactScope, DEFAULT_REASONING_LEVEL_OPTIONS, ReasoningLevel, ReasoningLevelOption, ReasoningLevelPicker, ReasoningLevelPickerProps, createFetchTransport, isModelCompatibleWithHarness, snapModelToHarness } from './chat.js';
|
|
9
9
|
export { ExpandedToolDetail, ExpandedToolDetailProps, InlineThinkingItem, InlineThinkingItemProps, InlineToolItem, InlineToolItemProps, LiveDuration, RunGroup, RunGroupProps } from '@tangle-network/ui/run';
|
|
10
10
|
export { CommandPreview, DiffPreview, GlobResultsPreview, GrepResultsPreview, QuestionPreview, WebSearchPreview, WriteFilePreview } from '@tangle-network/ui/tool-previews';
|
|
11
11
|
export { FileArtifactPane, FileArtifactPaneProps, FileNode, FilePreview, FilePreviewProps, FileTabData, FileTabs, FileTabsProps, FileTree, FileTreeProps, FileTreeVisibilityOptions, RichFileTree, RichFileTreeGitEntry, RichFileTreeGitStatus, RichFileTreeProps, RichFileTreeThemeVars, filterFileTree } from '@tangle-network/ui/files';
|
package/dist/index.js
CHANGED
|
@@ -74,6 +74,8 @@ import {
|
|
|
74
74
|
UserMenu
|
|
75
75
|
} from "./chunk-IOB2PW5Z.js";
|
|
76
76
|
import {
|
|
77
|
+
AgentComposer,
|
|
78
|
+
AgentProfilePicker,
|
|
77
79
|
AgentSessionControls,
|
|
78
80
|
AgentTimeline,
|
|
79
81
|
ArtifactAgentDock,
|
|
@@ -90,7 +92,7 @@ import {
|
|
|
90
92
|
modelProvider,
|
|
91
93
|
snapHarnessToModel,
|
|
92
94
|
snapModelToHarness
|
|
93
|
-
} from "./chunk-
|
|
95
|
+
} from "./chunk-4XOZGMJC.js";
|
|
94
96
|
import {
|
|
95
97
|
TOOL_CATEGORY_ICONS,
|
|
96
98
|
cn,
|
|
@@ -351,6 +353,8 @@ import {
|
|
|
351
353
|
import { Markdown } from "@tangle-network/ui/markdown";
|
|
352
354
|
export {
|
|
353
355
|
ActivityFeed,
|
|
356
|
+
AgentComposer,
|
|
357
|
+
AgentProfilePicker,
|
|
354
358
|
AgentSessionControls,
|
|
355
359
|
AgentTimeline,
|
|
356
360
|
AgentWorkbench,
|
package/dist/styles.css
CHANGED
|
@@ -404,6 +404,9 @@
|
|
|
404
404
|
.bottom-\[-0\.75rem\] {
|
|
405
405
|
bottom: -0.75rem;
|
|
406
406
|
}
|
|
407
|
+
.bottom-full {
|
|
408
|
+
bottom: 100%;
|
|
409
|
+
}
|
|
407
410
|
.left-0 {
|
|
408
411
|
left: calc(var(--spacing) * 0);
|
|
409
412
|
}
|
|
@@ -660,6 +663,14 @@
|
|
|
660
663
|
width: calc(var(--spacing) * 3);
|
|
661
664
|
height: calc(var(--spacing) * 3);
|
|
662
665
|
}
|
|
666
|
+
.size-4 {
|
|
667
|
+
width: calc(var(--spacing) * 4);
|
|
668
|
+
height: calc(var(--spacing) * 4);
|
|
669
|
+
}
|
|
670
|
+
.size-9 {
|
|
671
|
+
width: calc(var(--spacing) * 9);
|
|
672
|
+
height: calc(var(--spacing) * 9);
|
|
673
|
+
}
|
|
663
674
|
.\!h-2 {
|
|
664
675
|
height: calc(var(--spacing) * 2) !important;
|
|
665
676
|
}
|
|
@@ -825,6 +836,9 @@
|
|
|
825
836
|
.max-h-\[160px\] {
|
|
826
837
|
max-height: 160px;
|
|
827
838
|
}
|
|
839
|
+
.max-h-\[min\(60vh\,420px\)\] {
|
|
840
|
+
max-height: min(60vh, 420px);
|
|
841
|
+
}
|
|
828
842
|
.max-h-\[min\(440px\,var\(--radix-dropdown-menu-content-available-height\)\)\] {
|
|
829
843
|
max-height: min(440px, var(--radix-dropdown-menu-content-available-height));
|
|
830
844
|
}
|
|
@@ -885,6 +899,9 @@
|
|
|
885
899
|
.min-h-\[300px\] {
|
|
886
900
|
min-height: 300px;
|
|
887
901
|
}
|
|
902
|
+
.min-h-\[640px\] {
|
|
903
|
+
min-height: 640px;
|
|
904
|
+
}
|
|
888
905
|
.min-h-full {
|
|
889
906
|
min-height: 100%;
|
|
890
907
|
}
|
|
@@ -1050,6 +1067,9 @@
|
|
|
1050
1067
|
.w-\[300px\] {
|
|
1051
1068
|
width: 300px;
|
|
1052
1069
|
}
|
|
1070
|
+
.w-\[320px\] {
|
|
1071
|
+
width: 320px;
|
|
1072
|
+
}
|
|
1053
1073
|
.w-\[360px\] {
|
|
1054
1074
|
width: 360px;
|
|
1055
1075
|
}
|
|
@@ -3375,6 +3395,9 @@
|
|
|
3375
3395
|
.accent-primary {
|
|
3376
3396
|
accent-color: var(--color-primary);
|
|
3377
3397
|
}
|
|
3398
|
+
.\[color-scheme\:dark\] {
|
|
3399
|
+
color-scheme: dark;
|
|
3400
|
+
}
|
|
3378
3401
|
.opacity-0 {
|
|
3379
3402
|
opacity: 0%;
|
|
3380
3403
|
}
|
|
@@ -3839,6 +3862,14 @@
|
|
|
3839
3862
|
border-color: var(--color-border);
|
|
3840
3863
|
}
|
|
3841
3864
|
}
|
|
3865
|
+
.focus-within\:border-primary\/60 {
|
|
3866
|
+
&:focus-within {
|
|
3867
|
+
border-color: color-mix(in srgb, hsl(var(--primary)) 60%, transparent);
|
|
3868
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
3869
|
+
border-color: color-mix(in oklab, var(--color-primary) 60%, transparent);
|
|
3870
|
+
}
|
|
3871
|
+
}
|
|
3872
|
+
}
|
|
3842
3873
|
.focus-within\:shadow-\[var\(--chat-input-focus-shadow\,0_10px_30px_rgba\(15\,23\,42\,0\.08\)\)\] {
|
|
3843
3874
|
&:focus-within {
|
|
3844
3875
|
--tw-shadow: var(--chat-input-focus-shadow,0 10px 30px rgba(15,23,42,0.08));
|
|
@@ -4355,6 +4386,13 @@
|
|
|
4355
4386
|
}
|
|
4356
4387
|
}
|
|
4357
4388
|
}
|
|
4389
|
+
.hover\:text-\[var\(--status-error\,\#ff4d6d\)\] {
|
|
4390
|
+
&:hover {
|
|
4391
|
+
@media (hover: hover) {
|
|
4392
|
+
color: var(--status-error,#ff4d6d);
|
|
4393
|
+
}
|
|
4394
|
+
}
|
|
4395
|
+
}
|
|
4358
4396
|
.hover\:text-\[var\(--surface-danger-text\)\] {
|
|
4359
4397
|
&:hover {
|
|
4360
4398
|
@media (hover: hover) {
|
|
@@ -4475,6 +4513,11 @@
|
|
|
4475
4513
|
border-color: var(--border-accent-hover);
|
|
4476
4514
|
}
|
|
4477
4515
|
}
|
|
4516
|
+
.focus\:border-primary {
|
|
4517
|
+
&:focus {
|
|
4518
|
+
border-color: var(--color-primary);
|
|
4519
|
+
}
|
|
4520
|
+
}
|
|
4478
4521
|
.focus\:bg-accent {
|
|
4479
4522
|
&:focus {
|
|
4480
4523
|
background-color: var(--color-accent);
|
package/package.json
CHANGED