@agent-native/core 0.84.25 → 0.84.27
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/corpus/README.md +1 -1
- package/corpus/core/CHANGELOG.md +12 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/agent/production-agent.ts +4 -2
- package/corpus/core/src/agent/run-manager.ts +4 -3
- package/corpus/core/src/agent/types.ts +9 -2
- package/corpus/core/src/client/AssistantChat.tsx +15 -1
- package/corpus/core/src/client/FeedbackButton.tsx +2 -2
- package/corpus/core/src/client/components/PresenceBar.tsx +7 -2
- package/corpus/core/src/client/composer/ComposerPlusMenu.tsx +23 -9
- package/corpus/core/src/client/sharing/ShareButton.tsx +22 -3
- package/corpus/core/src/client/sharing/ShareDialog.tsx +13 -1
- package/corpus/core/src/client/sse-event-processor.ts +49 -20
- package/corpus/core/src/sharing/actions/set-resource-visibility.ts +3 -3
- package/corpus/templates/design/actions/insert-asset.ts +14 -2
- package/corpus/templates/design/actions/insert-design-native-asset.ts +16 -4
- package/corpus/templates/design/actions/insert-figma-library-asset.ts +14 -2
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +14 -0
- package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +54 -10
- package/corpus/templates/design/app/components/design/EditPanel.tsx +23 -16
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +7 -2
- package/corpus/templates/design/app/components/design/inspector/InspectorAiActions.tsx +9 -5
- package/corpus/templates/design/app/components/layout/Header.tsx +44 -1
- package/corpus/templates/design/app/pages/DesignEditor.tsx +267 -105
- package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +15 -1
- package/corpus/templates/design/app/pages/Index.tsx +20 -9
- package/corpus/templates/design/app/routes/settings.tsx +1 -1
- package/corpus/templates/design/changelog/2026-07-01-design-editor-polish-makes-zoom-assets-sharing-and-agent-handoffs-clearer.md +6 -0
- package/corpus/templates/design/changelog/2026-07-01-design-qa-fixes-make-exports-permissions-and-tools-clearer.md +6 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +4 -3
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +4 -4
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/agent/types.d.ts +3 -0
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +16 -1
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/FeedbackButton.js +2 -2
- package/dist/client/FeedbackButton.js.map +1 -1
- package/dist/client/components/PresenceBar.d.ts.map +1 -1
- package/dist/client/components/PresenceBar.js +6 -2
- package/dist/client/components/PresenceBar.js.map +1 -1
- package/dist/client/composer/ComposerPlusMenu.d.ts.map +1 -1
- package/dist/client/composer/ComposerPlusMenu.js +15 -7
- package/dist/client/composer/ComposerPlusMenu.js.map +1 -1
- package/dist/client/sharing/ShareButton.js +15 -2
- package/dist/client/sharing/ShareButton.js.map +1 -1
- package/dist/client/sharing/ShareDialog.js +16 -1
- package/dist/client/sharing/ShareDialog.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +42 -16
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +6 -6
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/sharing/actions/set-resource-visibility.js +3 -3
- package/dist/sharing/actions/set-resource-visibility.js.map +1 -1
- package/package.json +1 -1
|
@@ -66,6 +66,14 @@ function escapeHtml(value: string): string {
|
|
|
66
66
|
.replace(/"/g, """);
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
function createInsertedNodeId(prefix: string): string {
|
|
70
|
+
const random =
|
|
71
|
+
typeof crypto !== "undefined" && typeof crypto.randomUUID === "function"
|
|
72
|
+
? crypto.randomUUID().replace(/-/g, "").slice(0, 12)
|
|
73
|
+
: Math.random().toString(36).slice(2, 14);
|
|
74
|
+
return `inserted-${prefix}-${random}`;
|
|
75
|
+
}
|
|
76
|
+
|
|
69
77
|
function insertBeforeClosingTag(
|
|
70
78
|
html: string,
|
|
71
79
|
closingTag: "main" | "body",
|
|
@@ -83,6 +91,7 @@ function optionalDataAttribute(name: string, value: string | undefined) {
|
|
|
83
91
|
function appendFigmaAssetMarkup(
|
|
84
92
|
html: string,
|
|
85
93
|
args: z.infer<typeof schemaInput>,
|
|
94
|
+
nodeId: string,
|
|
86
95
|
): string {
|
|
87
96
|
const label = args.name?.trim() || "Figma library asset";
|
|
88
97
|
const description = args.description?.trim();
|
|
@@ -90,7 +99,7 @@ function appendFigmaAssetMarkup(
|
|
|
90
99
|
? `<a href="${escapeHtml(args.sourceUrl)}" target="_blank" rel="noreferrer" class="text-slate-500 underline decoration-slate-300 underline-offset-2 hover:text-slate-800">Open in Figma</a>`
|
|
91
100
|
: "";
|
|
92
101
|
const snippet = `
|
|
93
|
-
<section class="mx-auto my-8 max-w-5xl px-4" data-agent-native-asset-source="figma" data-agent-native-figma-asset data-figma-file-key="${escapeHtml(args.fileKey)}"${optionalDataAttribute("data-figma-node-id", args.nodeId)}${optionalDataAttribute("data-figma-component-key", args.componentKey)} data-figma-asset-kind="${escapeHtml(args.kind)}">
|
|
102
|
+
<section class="mx-auto my-8 max-w-5xl px-4" data-agent-native-asset-source="figma" data-agent-native-figma-asset data-agent-native-node-id="${escapeHtml(nodeId)}" data-agent-native-layer-name="${escapeHtml(label)}" data-figma-file-key="${escapeHtml(args.fileKey)}"${optionalDataAttribute("data-figma-node-id", args.nodeId)}${optionalDataAttribute("data-figma-component-key", args.componentKey)} data-figma-asset-kind="${escapeHtml(args.kind)}">
|
|
94
103
|
<figure class="overflow-hidden rounded-2xl border border-slate-200 bg-white shadow-sm">
|
|
95
104
|
<img src="${escapeHtml(args.renderUrl)}" alt="${escapeHtml(label)}" class="w-full rounded-t-2xl object-contain" />
|
|
96
105
|
<figcaption class="flex flex-wrap items-center gap-x-3 gap-y-1 px-4 py-3 text-sm text-slate-600">
|
|
@@ -201,7 +210,8 @@ export default defineAction({
|
|
|
201
210
|
// Collab read is best-effort; fall back to stored content.
|
|
202
211
|
}
|
|
203
212
|
|
|
204
|
-
const
|
|
213
|
+
const insertedNodeId = createInsertedNodeId("figma");
|
|
214
|
+
const content = appendFigmaAssetMarkup(base, args, insertedNodeId);
|
|
205
215
|
const now = new Date().toISOString();
|
|
206
216
|
await db
|
|
207
217
|
.update(schema.designFiles)
|
|
@@ -223,6 +233,8 @@ export default defineAction({
|
|
|
223
233
|
fileId: file.id,
|
|
224
234
|
filename: file.filename,
|
|
225
235
|
inserted: true,
|
|
236
|
+
insertedNodeId,
|
|
237
|
+
insertedSelector: `[data-agent-native-node-id="${insertedNodeId}"]`,
|
|
226
238
|
source: "figma",
|
|
227
239
|
fileKey: args.fileKey,
|
|
228
240
|
nodeId: args.nodeId ?? null,
|
|
@@ -1775,6 +1775,11 @@ export function DesignCanvas({
|
|
|
1775
1775
|
// explicit viewport width (e.g. 390 / 768 / 1280 side-by-side breakpoints).
|
|
1776
1776
|
const resolvedWidth =
|
|
1777
1777
|
previewWidthPx != null ? `${previewWidthPx}px` : iframeWidth;
|
|
1778
|
+
const focusScrollSurface = useCallback(() => {
|
|
1779
|
+
const surface = scrollContainerRef.current;
|
|
1780
|
+
if (!surface || document.activeElement === surface) return;
|
|
1781
|
+
surface.focus({ preventScroll: true });
|
|
1782
|
+
}, []);
|
|
1778
1783
|
|
|
1779
1784
|
// Wrap the iframe in a positioned container so DrawOverlay /
|
|
1780
1785
|
// CanvasCommentPins can absolutely-position themselves on top of the
|
|
@@ -1901,6 +1906,9 @@ export function DesignCanvas({
|
|
|
1901
1906
|
return (
|
|
1902
1907
|
<div
|
|
1903
1908
|
ref={scrollContainerRef}
|
|
1909
|
+
tabIndex={-1}
|
|
1910
|
+
onPointerEnter={focusScrollSurface}
|
|
1911
|
+
onMouseEnter={focusScrollSurface}
|
|
1904
1912
|
className="relative h-full w-full overflow-hidden"
|
|
1905
1913
|
>
|
|
1906
1914
|
{iframeElement}
|
|
@@ -1915,6 +1923,9 @@ export function DesignCanvas({
|
|
|
1915
1923
|
return (
|
|
1916
1924
|
<div
|
|
1917
1925
|
ref={scrollContainerRef}
|
|
1926
|
+
tabIndex={-1}
|
|
1927
|
+
onPointerEnter={focusScrollSurface}
|
|
1928
|
+
onMouseEnter={focusScrollSurface}
|
|
1918
1929
|
className="relative h-full w-full overflow-hidden"
|
|
1919
1930
|
style={{
|
|
1920
1931
|
width: embeddedFrame.displayWidth,
|
|
@@ -1945,6 +1956,9 @@ export function DesignCanvas({
|
|
|
1945
1956
|
return (
|
|
1946
1957
|
<div
|
|
1947
1958
|
ref={scrollContainerRef}
|
|
1959
|
+
tabIndex={-1}
|
|
1960
|
+
onPointerEnter={focusScrollSurface}
|
|
1961
|
+
onMouseEnter={focusScrollSurface}
|
|
1948
1962
|
className="relative flex-1 h-full overflow-auto"
|
|
1949
1963
|
>
|
|
1950
1964
|
{/* Canvas area. "none" mode fills the canvas (responsive preview);
|
|
@@ -108,6 +108,12 @@ export interface DesignExtensionSlotContext extends Record<string, unknown> {
|
|
|
108
108
|
content: string,
|
|
109
109
|
updatedAt?: string,
|
|
110
110
|
) => void;
|
|
111
|
+
onAssetInserted?: (selection: {
|
|
112
|
+
fileId?: string;
|
|
113
|
+
nodeId?: string;
|
|
114
|
+
selector?: string;
|
|
115
|
+
title?: string;
|
|
116
|
+
}) => void;
|
|
111
117
|
}
|
|
112
118
|
|
|
113
119
|
interface DesignExtensionsPanelProps {
|
|
@@ -301,6 +307,7 @@ interface FirstPartyRowProps {
|
|
|
301
307
|
|
|
302
308
|
function FirstPartyExtRow({
|
|
303
309
|
label,
|
|
310
|
+
description,
|
|
304
311
|
icon,
|
|
305
312
|
badge,
|
|
306
313
|
isOpen,
|
|
@@ -321,14 +328,14 @@ function FirstPartyExtRow({
|
|
|
321
328
|
<span className="block truncate text-sm font-medium leading-tight text-foreground">
|
|
322
329
|
{label}
|
|
323
330
|
</span>
|
|
324
|
-
<span className="mt-0.5
|
|
325
|
-
|
|
331
|
+
<span className="mt-0.5 line-clamp-1 text-xs leading-snug text-muted-foreground">
|
|
332
|
+
{description}
|
|
326
333
|
</span>
|
|
327
334
|
</span>
|
|
328
335
|
{badge}
|
|
329
336
|
</button>
|
|
330
337
|
{isOpen && (
|
|
331
|
-
<div className="mb-2
|
|
338
|
+
<div className="mb-2 mt-1 overflow-hidden rounded-md border border-border/70 bg-background/70">
|
|
332
339
|
{children}
|
|
333
340
|
</div>
|
|
334
341
|
)}
|
|
@@ -348,6 +355,12 @@ function ToolFilterMenu<T extends string>({
|
|
|
348
355
|
onChange: (value: T) => void;
|
|
349
356
|
}) {
|
|
350
357
|
const selected = options.find((option) => option.value === value);
|
|
358
|
+
const triggerLabel =
|
|
359
|
+
value === "all"
|
|
360
|
+
? label === "Category"
|
|
361
|
+
? "All categories"
|
|
362
|
+
: `All ${label.toLowerCase()}s`
|
|
363
|
+
: (selected?.label ?? label);
|
|
351
364
|
return (
|
|
352
365
|
<DropdownMenu>
|
|
353
366
|
<DropdownMenuTrigger asChild>
|
|
@@ -358,7 +371,7 @@ function ToolFilterMenu<T extends string>({
|
|
|
358
371
|
className="h-8 cursor-pointer gap-1.5 rounded-md bg-transparent px-2.5 text-sm font-medium"
|
|
359
372
|
>
|
|
360
373
|
<IconAdjustmentsHorizontal className="size-4 text-muted-foreground" />
|
|
361
|
-
<span>{
|
|
374
|
+
<span>{triggerLabel}</span>
|
|
362
375
|
<IconChevronDown className="size-3.5 text-muted-foreground" />
|
|
363
376
|
</Button>
|
|
364
377
|
</DropdownMenuTrigger>
|
|
@@ -463,6 +476,25 @@ export function AssetLibraryPanel({ context }: AssetLibraryPanelProps) {
|
|
|
463
476
|
: undefined,
|
|
464
477
|
{ enabled: Boolean(figmaRequest) },
|
|
465
478
|
);
|
|
479
|
+
const notifyAssetInserted = useCallback(
|
|
480
|
+
(result: unknown, title: string) => {
|
|
481
|
+
if (!result || typeof result !== "object") return;
|
|
482
|
+
const row = result as Record<string, unknown>;
|
|
483
|
+
context.onAssetInserted?.({
|
|
484
|
+
fileId: typeof row.fileId === "string" ? row.fileId : undefined,
|
|
485
|
+
nodeId:
|
|
486
|
+
typeof row.insertedNodeId === "string"
|
|
487
|
+
? row.insertedNodeId
|
|
488
|
+
: undefined,
|
|
489
|
+
selector:
|
|
490
|
+
typeof row.insertedSelector === "string"
|
|
491
|
+
? row.insertedSelector
|
|
492
|
+
: undefined,
|
|
493
|
+
title,
|
|
494
|
+
});
|
|
495
|
+
},
|
|
496
|
+
[context],
|
|
497
|
+
);
|
|
466
498
|
|
|
467
499
|
const handleReady = useCallback(
|
|
468
500
|
(_payload: unknown, _event: MessageEvent, ref: EmbeddedAppRef) => {
|
|
@@ -508,7 +540,8 @@ export function AssetLibraryPanel({ context }: AssetLibraryPanelProps) {
|
|
|
508
540
|
fileId: context.activeFileId || undefined,
|
|
509
541
|
},
|
|
510
542
|
{
|
|
511
|
-
onSuccess: () => {
|
|
543
|
+
onSuccess: (result) => {
|
|
544
|
+
notifyAssetInserted(result, title ?? altText ?? "Asset");
|
|
512
545
|
toast.success("Asset inserted into design.");
|
|
513
546
|
},
|
|
514
547
|
onError: () => {
|
|
@@ -517,7 +550,7 @@ export function AssetLibraryPanel({ context }: AssetLibraryPanelProps) {
|
|
|
517
550
|
},
|
|
518
551
|
);
|
|
519
552
|
},
|
|
520
|
-
[context.designId, context.activeFileId, insertAsset],
|
|
553
|
+
[context.designId, context.activeFileId, insertAsset, notifyAssetInserted],
|
|
521
554
|
);
|
|
522
555
|
|
|
523
556
|
const handleInsertNativeAsset = (asset: DesignNativeAsset) => {
|
|
@@ -528,7 +561,8 @@ export function AssetLibraryPanel({ context }: AssetLibraryPanelProps) {
|
|
|
528
561
|
fileId: context.activeFileId || undefined,
|
|
529
562
|
},
|
|
530
563
|
{
|
|
531
|
-
onSuccess: () => {
|
|
564
|
+
onSuccess: (result) => {
|
|
565
|
+
notifyAssetInserted(result, asset.title);
|
|
532
566
|
toast.success(`${asset.title} inserted into design.`);
|
|
533
567
|
},
|
|
534
568
|
onError: (error) => {
|
|
@@ -566,7 +600,8 @@ export function AssetLibraryPanel({ context }: AssetLibraryPanelProps) {
|
|
|
566
600
|
fileId: context.activeFileId || undefined,
|
|
567
601
|
},
|
|
568
602
|
{
|
|
569
|
-
onSuccess: () => {
|
|
603
|
+
onSuccess: (result) => {
|
|
604
|
+
notifyAssetInserted(result, asset.name);
|
|
570
605
|
toast.success("Figma asset inserted into design.");
|
|
571
606
|
},
|
|
572
607
|
onError: (error) => {
|
|
@@ -1267,6 +1302,11 @@ export function DesignExtensionsPanel({
|
|
|
1267
1302
|
visibleFirstPartyRows.length > 0 ||
|
|
1268
1303
|
visibleInstalls.length > 0 ||
|
|
1269
1304
|
visibleInstallable.length > 0;
|
|
1305
|
+
const showPluginsEmptyState =
|
|
1306
|
+
!hasAnyVisibleTool &&
|
|
1307
|
+
categoryFilter === "plugins" &&
|
|
1308
|
+
!normalizedSearch &&
|
|
1309
|
+
sourceFilter !== "built-in";
|
|
1270
1310
|
|
|
1271
1311
|
return (
|
|
1272
1312
|
<div className={cn("flex min-h-0 flex-1 flex-col", className)}>
|
|
@@ -1412,10 +1452,14 @@ export function DesignExtensionsPanel({
|
|
|
1412
1452
|
<IconSearch className="size-4 text-muted-foreground" />
|
|
1413
1453
|
</div>
|
|
1414
1454
|
<p className="text-sm font-medium text-foreground">
|
|
1415
|
-
|
|
1455
|
+
{showPluginsEmptyState
|
|
1456
|
+
? "No plugins installed"
|
|
1457
|
+
: "No tools found"}
|
|
1416
1458
|
</p>
|
|
1417
1459
|
<p className="mx-auto mt-1 max-w-52 text-xs leading-5 text-muted-foreground">
|
|
1418
|
-
|
|
1460
|
+
{showPluginsEmptyState
|
|
1461
|
+
? "Create a plugin or clear the Category filter to browse built-in tools."
|
|
1462
|
+
: "Try another search or clear the filters."}
|
|
1419
1463
|
</p>
|
|
1420
1464
|
</div>
|
|
1421
1465
|
) : null}
|
|
@@ -3189,22 +3189,29 @@ function TypographyDetailsPopover({
|
|
|
3189
3189
|
|
|
3190
3190
|
return (
|
|
3191
3191
|
<Popover open={open} onOpenChange={setOpen}>
|
|
3192
|
-
<
|
|
3193
|
-
<
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3192
|
+
<Tooltip>
|
|
3193
|
+
<TooltipTrigger asChild>
|
|
3194
|
+
<PopoverTrigger asChild>
|
|
3195
|
+
<Button
|
|
3196
|
+
type="button"
|
|
3197
|
+
variant="ghost"
|
|
3198
|
+
size="icon"
|
|
3199
|
+
aria-label={"Typography details" /* i18n-ignore design action */}
|
|
3200
|
+
aria-pressed={open}
|
|
3201
|
+
className={cn(
|
|
3202
|
+
"h-6 min-w-6 cursor-pointer rounded-md text-muted-foreground hover:bg-[var(--design-editor-panel-raised-bg)] hover:text-foreground",
|
|
3203
|
+
open &&
|
|
3204
|
+
"bg-[var(--design-editor-accent-color)]/20 text-[var(--design-editor-accent-color)] hover:text-[var(--design-editor-accent-color)]",
|
|
3205
|
+
)}
|
|
3206
|
+
>
|
|
3207
|
+
<IconLayoutSettings className="size-3.5" />
|
|
3208
|
+
</Button>
|
|
3209
|
+
</PopoverTrigger>
|
|
3210
|
+
</TooltipTrigger>
|
|
3211
|
+
<TooltipContent>
|
|
3212
|
+
{"Typography details" /* i18n-ignore design action */}
|
|
3213
|
+
</TooltipContent>
|
|
3214
|
+
</Tooltip>
|
|
3208
3215
|
<PopoverContent
|
|
3209
3216
|
side="left"
|
|
3210
3217
|
align="end"
|
|
@@ -4825,7 +4825,11 @@ export function MultiScreenCanvas({
|
|
|
4825
4825
|
className="relative h-full w-full select-none overflow-hidden outline-none"
|
|
4826
4826
|
onMouseDownCapture={handleMouseDown}
|
|
4827
4827
|
onMouseMove={handleMouseMove}
|
|
4828
|
-
style={{
|
|
4828
|
+
style={{
|
|
4829
|
+
cursor: surfaceCursor,
|
|
4830
|
+
overscrollBehavior: "none",
|
|
4831
|
+
touchAction: "none",
|
|
4832
|
+
}}
|
|
4829
4833
|
>
|
|
4830
4834
|
{showPixelGrid ? (
|
|
4831
4835
|
<div
|
|
@@ -5769,6 +5773,7 @@ const Screen = memo(function Screen({
|
|
|
5769
5773
|
onMouseEnter={() => updateDirectHover(true)}
|
|
5770
5774
|
onMouseLeave={() => updateDirectHover(false)}
|
|
5771
5775
|
style={{
|
|
5776
|
+
width: labelInfoMaxWidth,
|
|
5772
5777
|
maxWidth: labelInfoMaxWidth,
|
|
5773
5778
|
transform: `translateY(-50%) scale(${chromeScale})`,
|
|
5774
5779
|
transformOrigin: "left center",
|
|
@@ -5784,7 +5789,7 @@ const Screen = memo(function Screen({
|
|
|
5784
5789
|
<span
|
|
5785
5790
|
data-frame-title
|
|
5786
5791
|
className={cn(
|
|
5787
|
-
"min-w-0 truncate !text-[11px] font-medium",
|
|
5792
|
+
"min-w-0 flex-1 truncate !text-[11px] font-medium",
|
|
5788
5793
|
emphasized
|
|
5789
5794
|
? "text-[var(--design-editor-accent-color)]"
|
|
5790
5795
|
: activeOrEmphasized
|
|
@@ -63,7 +63,8 @@ export function InspectorAiActions({
|
|
|
63
63
|
routeSourceFile,
|
|
64
64
|
designId,
|
|
65
65
|
};
|
|
66
|
-
const
|
|
66
|
+
const copyDisabled = !request.trim();
|
|
67
|
+
const askDisabled = !canEdit || copyDisabled;
|
|
67
68
|
|
|
68
69
|
return (
|
|
69
70
|
<Collapsible open={open} onOpenChange={setOpen} className="w-full">
|
|
@@ -97,9 +98,12 @@ export function InspectorAiActions({
|
|
|
97
98
|
: t("designEditor.localSourceEdit.describeChange")
|
|
98
99
|
}
|
|
99
100
|
className="min-h-[64px] resize-none text-xs"
|
|
100
|
-
disabled={!canEdit}
|
|
101
101
|
onKeyDown={(e) => {
|
|
102
|
-
if (
|
|
102
|
+
if (
|
|
103
|
+
e.key === "Enter" &&
|
|
104
|
+
(e.metaKey || e.ctrlKey) &&
|
|
105
|
+
!askDisabled
|
|
106
|
+
) {
|
|
103
107
|
e.preventDefault();
|
|
104
108
|
void sendEdit(args);
|
|
105
109
|
setRequest("");
|
|
@@ -112,7 +116,7 @@ export function InspectorAiActions({
|
|
|
112
116
|
size="sm"
|
|
113
117
|
variant="default"
|
|
114
118
|
className="flex-1 gap-1.5 text-xs"
|
|
115
|
-
disabled={
|
|
119
|
+
disabled={askDisabled}
|
|
116
120
|
onClick={() => {
|
|
117
121
|
void sendEdit(args);
|
|
118
122
|
setRequest("");
|
|
@@ -126,7 +130,7 @@ export function InspectorAiActions({
|
|
|
126
130
|
size="sm"
|
|
127
131
|
variant="outline"
|
|
128
132
|
className="gap-1.5 text-xs"
|
|
129
|
-
disabled={
|
|
133
|
+
disabled={copyDisabled}
|
|
130
134
|
onClick={() => {
|
|
131
135
|
void copyPrompt(args);
|
|
132
136
|
}}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useActionQuery, useT } from "@agent-native/core/client";
|
|
2
2
|
import { AgentToggleButton } from "@agent-native/core/client";
|
|
3
3
|
import { RunsTray } from "@agent-native/core/client/progress";
|
|
4
|
+
import { useCallback } from "react";
|
|
4
5
|
import { useLocation } from "react-router";
|
|
5
6
|
|
|
6
7
|
import { useHeaderTitle, useHeaderActions } from "./HeaderActions";
|
|
@@ -12,6 +13,11 @@ const pageTitleKeys: Record<string, string> = {
|
|
|
12
13
|
"/settings": "navigation.settings",
|
|
13
14
|
};
|
|
14
15
|
|
|
16
|
+
type HeaderAgentRun = {
|
|
17
|
+
title?: string;
|
|
18
|
+
metadata?: Record<string, unknown> | null;
|
|
19
|
+
};
|
|
20
|
+
|
|
15
21
|
function DesignTitle({ id }: { id: string }) {
|
|
16
22
|
const { data } = useActionQuery<{ title?: string }>("get-design", { id });
|
|
17
23
|
const title = data?.title ?? "Design";
|
|
@@ -42,6 +48,43 @@ function ResolvedTitle() {
|
|
|
42
48
|
export function Header() {
|
|
43
49
|
const title = useHeaderTitle();
|
|
44
50
|
const actions = useHeaderActions();
|
|
51
|
+
const openRunThread = useCallback(
|
|
52
|
+
(threadId: string, run?: HeaderAgentRun) => {
|
|
53
|
+
window.dispatchEvent(
|
|
54
|
+
new CustomEvent("agent-panel:set-mode", {
|
|
55
|
+
detail: { mode: "chat" },
|
|
56
|
+
}),
|
|
57
|
+
);
|
|
58
|
+
window.dispatchEvent(new CustomEvent("agent-panel:open"));
|
|
59
|
+
const metadata = run?.metadata ?? {};
|
|
60
|
+
const parentThreadId =
|
|
61
|
+
typeof metadata.parentThreadId === "string"
|
|
62
|
+
? metadata.parentThreadId.trim()
|
|
63
|
+
: "";
|
|
64
|
+
const isAgentTeam =
|
|
65
|
+
metadata.kind === "agent-team" || metadata.source === "agent-teams";
|
|
66
|
+
if (isAgentTeam && parentThreadId && parentThreadId !== threadId) {
|
|
67
|
+
window.dispatchEvent(
|
|
68
|
+
new CustomEvent("agent-task-open", {
|
|
69
|
+
detail: {
|
|
70
|
+
threadId,
|
|
71
|
+
parentThreadId,
|
|
72
|
+
description:
|
|
73
|
+
typeof metadata.description === "string"
|
|
74
|
+
? metadata.description
|
|
75
|
+
: run?.title || "",
|
|
76
|
+
name: typeof metadata.name === "string" ? metadata.name : "",
|
|
77
|
+
},
|
|
78
|
+
}),
|
|
79
|
+
);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
window.dispatchEvent(
|
|
83
|
+
new CustomEvent("agent-chat:open-thread", { detail: { threadId } }),
|
|
84
|
+
);
|
|
85
|
+
},
|
|
86
|
+
[],
|
|
87
|
+
);
|
|
45
88
|
|
|
46
89
|
return (
|
|
47
90
|
<header className="flex h-12 items-center gap-3 border-b border-border bg-background px-4 lg:px-6 shrink-0">
|
|
@@ -50,7 +93,7 @@ export function Header() {
|
|
|
50
93
|
</div>
|
|
51
94
|
<div className="flex items-center gap-2 shrink-0">
|
|
52
95
|
{actions}
|
|
53
|
-
<RunsTray pollMs={1500} />
|
|
96
|
+
<RunsTray pollMs={1500} onOpenThread={openRunThread} />
|
|
54
97
|
<AgentToggleButton />
|
|
55
98
|
</div>
|
|
56
99
|
</header>
|