ai-design-system 0.1.77 → 0.1.78
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/components/blocks/AIConversation/AIConversation.stories.tsx +86 -0
- package/components/blocks/AIConversation/AIConversation.tsx +17 -0
- package/components/composites/AdjustableLayout/AdjustableLayout.tsx +8 -10
- package/components/composites/AgentIndicator/AgentIndicator.tsx +1 -0
- package/components/composites/MediaPreview/MediaPreview.stories.tsx +60 -0
- package/components/composites/MediaPreview/MediaPreview.tsx +186 -0
- package/components/composites/MediaPreview/index.ts +9 -0
- package/components/composites/SpecialistMessage/SpecialistMessage.tsx +37 -1
- package/components/composites/StreamingMarkdown.tsx +11 -5
- package/components/composites/SystemMessage/SystemMessage.tsx +49 -1
- package/components/composites/index.ts +3 -1
- package/components/features/TextEditor/TextEditor.tsx +25 -23
- package/components/features/TextEditor/index.ts +3 -0
- package/components/features/TextEditor/useTextEditor.mock.ts +1 -14
- package/dist/index.cjs +283 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +38 -0
- package/dist/index.d.ts +45 -25
- package/dist/index.js +283 -35
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -41,13 +41,9 @@ import type { FileDownloadResult, FileTreeNode } from '@/components/composites/F
|
|
|
41
41
|
import { cn } from '@/lib/utils'
|
|
42
42
|
import type { JSONContent } from '@tiptap/core'
|
|
43
43
|
import type { Annotation, User } from '@/types/ai-editor/annotations'
|
|
44
|
+
import type { DocumentFile, DocumentWithAnnotations } from '@/types/ai-editor/editor'
|
|
44
45
|
import { StreamingMarkdown } from '@/components/composites/StreamingMarkdown'
|
|
45
|
-
|
|
46
|
-
interface DocumentWithAnnotations {
|
|
47
|
-
file: { id: string; name: string; isDirty?: boolean; format?: 'json' | 'markdown' | string; lastModified?: number }
|
|
48
|
-
content: JSONContent | string
|
|
49
|
-
annotations: Annotation[]
|
|
50
|
-
}
|
|
46
|
+
import { MediaPreview, isMediaFile } from '@/components/composites/MediaPreview'
|
|
51
47
|
|
|
52
48
|
/**
|
|
53
49
|
* Props for TextEditor feature component - Single document mode (backward compatible)
|
|
@@ -298,13 +294,6 @@ export const TextEditor = React.memo<TextEditorProps>(
|
|
|
298
294
|
targetId = targetId.slice(2)
|
|
299
295
|
}
|
|
300
296
|
|
|
301
|
-
console.log('[TextEditor:LinkComponent:handleClick]', {
|
|
302
|
-
href,
|
|
303
|
-
activeDocumentId: props.activeDocumentId,
|
|
304
|
-
computedTargetId: targetId,
|
|
305
|
-
documentsCount: props.documents?.length
|
|
306
|
-
})
|
|
307
|
-
|
|
308
297
|
if (isMultiTab && props.documents) {
|
|
309
298
|
const cleanTarget = targetId.replace(/^\.\//, '').replace(/^\//, '')
|
|
310
299
|
const matchedDoc = props.documents.find((doc) => {
|
|
@@ -316,18 +305,12 @@ export const TextEditor = React.memo<TextEditorProps>(
|
|
|
316
305
|
doc.file.name === targetId
|
|
317
306
|
)
|
|
318
307
|
})
|
|
319
|
-
console.log('[TextEditor:LinkComponent:matching]', {
|
|
320
|
-
cleanTarget,
|
|
321
|
-
matchedDocId: matchedDoc?.file?.id,
|
|
322
|
-
availableDocIds: props.documents.map(d => d.file.id)
|
|
323
|
-
})
|
|
324
308
|
if (matchedDoc) {
|
|
325
309
|
targetId = matchedDoc.file.id
|
|
326
310
|
}
|
|
327
311
|
}
|
|
328
312
|
|
|
329
313
|
if (handleTabSelect) {
|
|
330
|
-
console.log('[TextEditor:LinkComponent:onTabSelect]', targetId)
|
|
331
314
|
handleTabSelect(targetId)
|
|
332
315
|
}
|
|
333
316
|
}
|
|
@@ -339,6 +322,8 @@ export const TextEditor = React.memo<TextEditorProps>(
|
|
|
339
322
|
return <a href={href} onClick={handleClick} className="text-primary hover:underline cursor-pointer" {...rest} />
|
|
340
323
|
}, [handleTabSelect, isMultiTab, props.activeDocumentId, props.documents])
|
|
341
324
|
|
|
325
|
+
const markdownComponents = useMemo(() => ({ a: LinkComponent }), [LinkComponent])
|
|
326
|
+
|
|
342
327
|
/**
|
|
343
328
|
* Single-document mode
|
|
344
329
|
*/
|
|
@@ -354,7 +339,7 @@ export const TextEditor = React.memo<TextEditorProps>(
|
|
|
354
339
|
: contentStr
|
|
355
340
|
return (
|
|
356
341
|
<div className={cn('text-editor p-6 flex flex-col h-screen w-full flex-1', className)}>
|
|
357
|
-
<StreamingMarkdown mode="
|
|
342
|
+
<StreamingMarkdown mode="static" isAnimating={false} components={markdownComponents}>
|
|
358
343
|
{content}
|
|
359
344
|
</StreamingMarkdown>
|
|
360
345
|
</div>
|
|
@@ -402,6 +387,23 @@ export const TextEditor = React.memo<TextEditorProps>(
|
|
|
402
387
|
</div>
|
|
403
388
|
</div>
|
|
404
389
|
)
|
|
390
|
+
} else if (isMediaFile(currentDocument.file)) {
|
|
391
|
+
editorPane = (
|
|
392
|
+
<div className="text-editor flex flex-col h-full w-full">
|
|
393
|
+
{!hideTabBar && (
|
|
394
|
+
<DocumentTabBar
|
|
395
|
+
className="w-full"
|
|
396
|
+
tabs={props.documents?.map((doc) => doc.file) || []}
|
|
397
|
+
activeTabId={props.activeDocumentId}
|
|
398
|
+
onTabSelect={props.onTabSelect}
|
|
399
|
+
onTabClose={props.onTabClose}
|
|
400
|
+
/>
|
|
401
|
+
)}
|
|
402
|
+
<div className="flex-1 overflow-auto">
|
|
403
|
+
<MediaPreview file={currentDocument.file} />
|
|
404
|
+
</div>
|
|
405
|
+
</div>
|
|
406
|
+
)
|
|
405
407
|
} else {
|
|
406
408
|
const format = currentDocument.file.format || 'markdown'
|
|
407
409
|
const isMarkdownMulti = format === 'markdown' || format === 'md' || format === 'mdx'
|
|
@@ -435,10 +437,10 @@ export const TextEditor = React.memo<TextEditorProps>(
|
|
|
435
437
|
) : renderAsStreamdown ? (
|
|
436
438
|
<div className="p-6">
|
|
437
439
|
<StreamingMarkdown
|
|
438
|
-
mode="
|
|
439
|
-
isAnimating
|
|
440
|
+
mode="static"
|
|
441
|
+
isAnimating={false}
|
|
440
442
|
className="[&>*:first-child]:mt-0 [&>*:last-child]:mb-0"
|
|
441
|
-
components={
|
|
443
|
+
components={markdownComponents}
|
|
442
444
|
>
|
|
443
445
|
{isCodeMulti
|
|
444
446
|
? `\`\`\`${format}\n${format === 'json' ? formatJson(currentDocument.content as string) : currentDocument.content}\n\`\`\``
|
|
@@ -22,3 +22,6 @@ export {
|
|
|
22
22
|
sampleDocumentFiles,
|
|
23
23
|
sampleMultiTabDocuments,
|
|
24
24
|
} from './TextEditor.mocks'
|
|
25
|
+
|
|
26
|
+
export { MediaPreview, isMediaFile, isVideoFile, isAudioFile, isImageFile, isPdfFile } from '@/components/composites/MediaPreview'
|
|
27
|
+
export type { MediaPreviewProps } from '@/components/composites/MediaPreview'
|
|
@@ -8,24 +8,11 @@
|
|
|
8
8
|
import React, { useState, useCallback } from 'react'
|
|
9
9
|
import type { JSONContent } from '@tiptap/core'
|
|
10
10
|
import type { Annotation } from '@/types/ai-editor/annotations'
|
|
11
|
+
import type { DocumentFile, DocumentWithAnnotations } from '@/types/ai-editor/editor'
|
|
11
12
|
import type { FileTreeNode } from '@/components/composites/FileTreeExplorer'
|
|
12
13
|
import type { UseTextEditorReturn, UseAIMultiTabDocEditorReturn } from './useTextEditor'
|
|
13
14
|
import { sampleDocumentFiles, sampleMultiTabDocuments } from './TextEditor.mocks'
|
|
14
15
|
|
|
15
|
-
interface DocumentFile {
|
|
16
|
-
id: string
|
|
17
|
-
name: string
|
|
18
|
-
isDirty: boolean
|
|
19
|
-
format?: 'json' | 'markdown' | string
|
|
20
|
-
lastModified: number
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
interface DocumentWithAnnotations {
|
|
24
|
-
file: DocumentFile
|
|
25
|
-
content: JSONContent | string
|
|
26
|
-
annotations: Annotation[]
|
|
27
|
-
}
|
|
28
|
-
|
|
29
16
|
type MultiDocMockConfig = {
|
|
30
17
|
multiDoc: true
|
|
31
18
|
initialDocuments?: DocumentWithAnnotations[]
|
package/dist/index.cjs
CHANGED
|
@@ -1400,6 +1400,38 @@ var defaultIcons = {
|
|
|
1400
1400
|
{ type: "path", attrs: { d: "M3 5v14a2 2 0 0 0 2 2h16v-5" } },
|
|
1401
1401
|
{ type: "path", attrs: { d: "M18 12a2 2 0 0 0 0 4h4v-4Z" } }
|
|
1402
1402
|
]
|
|
1403
|
+
},
|
|
1404
|
+
"film": {
|
|
1405
|
+
name: "film",
|
|
1406
|
+
viewBox: "0 0 24 24",
|
|
1407
|
+
elements: [
|
|
1408
|
+
{ type: "rect", attrs: { width: "18", height: "18", x: "3", y: "3", rx: "2" } },
|
|
1409
|
+
{ type: "path", attrs: { d: "M7 3v18" } },
|
|
1410
|
+
{ type: "path", attrs: { d: "M3 7.5h4" } },
|
|
1411
|
+
{ type: "path", attrs: { d: "M3 12h18" } },
|
|
1412
|
+
{ type: "path", attrs: { d: "M3 16.5h4" } },
|
|
1413
|
+
{ type: "path", attrs: { d: "M17 3v18" } },
|
|
1414
|
+
{ type: "path", attrs: { d: "M17 7.5h4" } },
|
|
1415
|
+
{ type: "path", attrs: { d: "M17 16.5h4" } }
|
|
1416
|
+
]
|
|
1417
|
+
},
|
|
1418
|
+
"music": {
|
|
1419
|
+
name: "music",
|
|
1420
|
+
viewBox: "0 0 24 24",
|
|
1421
|
+
elements: [
|
|
1422
|
+
{ type: "path", attrs: { d: "M9 18V5l12-2v13" } },
|
|
1423
|
+
{ type: "circle", attrs: { cx: "6", cy: "18", r: "3" } },
|
|
1424
|
+
{ type: "circle", attrs: { cx: "18", cy: "16", r: "3" } }
|
|
1425
|
+
]
|
|
1426
|
+
},
|
|
1427
|
+
"image": {
|
|
1428
|
+
name: "image",
|
|
1429
|
+
viewBox: "0 0 24 24",
|
|
1430
|
+
elements: [
|
|
1431
|
+
{ type: "rect", attrs: { width: "18", height: "18", x: "3", y: "3", rx: "2", ry: "2" } },
|
|
1432
|
+
{ type: "circle", attrs: { cx: "9", cy: "9", r: "2" } },
|
|
1433
|
+
{ type: "path", attrs: { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21" } }
|
|
1434
|
+
]
|
|
1403
1435
|
}
|
|
1404
1436
|
};
|
|
1405
1437
|
var IconRegistry = class {
|
|
@@ -1875,13 +1907,12 @@ var AdjustableLayout = React3__namespace.memo(
|
|
|
1875
1907
|
return raw.map((size) => size / total * 100);
|
|
1876
1908
|
}, [sections]);
|
|
1877
1909
|
const [sizes, setSizes] = React3__namespace.useState(defaultSizes);
|
|
1910
|
+
const prevSectionsLengthRef = React3__namespace.useRef(sections.length);
|
|
1878
1911
|
React3__namespace.useEffect(() => {
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
return prevSizes;
|
|
1884
|
-
});
|
|
1912
|
+
if (prevSectionsLengthRef.current !== sections.length) {
|
|
1913
|
+
prevSectionsLengthRef.current = sections.length;
|
|
1914
|
+
setSizes(defaultSizes);
|
|
1915
|
+
}
|
|
1885
1916
|
}, [sections.length, defaultSizes]);
|
|
1886
1917
|
React3__namespace.useEffect(() => {
|
|
1887
1918
|
if (!storageKey) return;
|
|
@@ -1894,7 +1925,7 @@ var AdjustableLayout = React3__namespace.memo(
|
|
|
1894
1925
|
}
|
|
1895
1926
|
} catch (e) {
|
|
1896
1927
|
}
|
|
1897
|
-
}, [storageKey]);
|
|
1928
|
+
}, [storageKey, sections.length]);
|
|
1898
1929
|
const [draggingIndex, setDraggingIndex] = React3__namespace.useState(null);
|
|
1899
1930
|
const [startX, setStartX] = React3__namespace.useState(0);
|
|
1900
1931
|
const [startSizes, setStartSizes] = React3__namespace.useState([]);
|
|
@@ -3641,6 +3672,14 @@ var customRemarkPlugins = [
|
|
|
3641
3672
|
...Object.values(streamdown.defaultRemarkPlugins),
|
|
3642
3673
|
remarkFrontmatter__default.default
|
|
3643
3674
|
];
|
|
3675
|
+
var DEFAULT_SHIKI_THEME = [
|
|
3676
|
+
"vitesse-light",
|
|
3677
|
+
"vitesse-dark"
|
|
3678
|
+
];
|
|
3679
|
+
var DEFAULT_CONTROLS = {
|
|
3680
|
+
code: true,
|
|
3681
|
+
mermaid: true
|
|
3682
|
+
};
|
|
3644
3683
|
var StreamingMarkdown = React3.memo(
|
|
3645
3684
|
(_a) => {
|
|
3646
3685
|
var _b = _a, {
|
|
@@ -3660,6 +3699,7 @@ var StreamingMarkdown = React3.memo(
|
|
|
3660
3699
|
"status",
|
|
3661
3700
|
"controls"
|
|
3662
3701
|
]);
|
|
3702
|
+
var _a2;
|
|
3663
3703
|
const [copied, setCopied] = React3.useState(false);
|
|
3664
3704
|
let content = children;
|
|
3665
3705
|
let title = propsTitle;
|
|
@@ -3749,11 +3789,8 @@ var StreamingMarkdown = React3.memo(
|
|
|
3749
3789
|
streamdown.Streamdown,
|
|
3750
3790
|
__spreadProps(__spreadValues({
|
|
3751
3791
|
remarkPlugins: remarkPlugins || customRemarkPlugins,
|
|
3752
|
-
shikiTheme:
|
|
3753
|
-
controls: propsControls != null ? propsControls :
|
|
3754
|
-
code: true,
|
|
3755
|
-
mermaid: true
|
|
3756
|
-
}
|
|
3792
|
+
shikiTheme: (_a2 = props.shikiTheme) != null ? _a2 : DEFAULT_SHIKI_THEME,
|
|
3793
|
+
controls: propsControls != null ? propsControls : DEFAULT_CONTROLS
|
|
3757
3794
|
}, props), {
|
|
3758
3795
|
children: content
|
|
3759
3796
|
})
|
|
@@ -3789,6 +3826,10 @@ var SpecialistMessage = React3__namespace.memo(
|
|
|
3789
3826
|
() => message.toolCalls !== void 0 && message.toolCalls.length > 0,
|
|
3790
3827
|
[message.toolCalls]
|
|
3791
3828
|
);
|
|
3829
|
+
const hasSubAgents = React3__namespace.useMemo(
|
|
3830
|
+
() => message.subAgents !== void 0 && message.subAgents.length > 0,
|
|
3831
|
+
[message.subAgents]
|
|
3832
|
+
);
|
|
3792
3833
|
const toolState = React3__namespace.useMemo(() => {
|
|
3793
3834
|
switch (message.status) {
|
|
3794
3835
|
case "pending":
|
|
@@ -3834,7 +3875,22 @@ var SpecialistMessage = React3__namespace.memo(
|
|
|
3834
3875
|
children: message.content
|
|
3835
3876
|
}
|
|
3836
3877
|
),
|
|
3837
|
-
hasToolCalls && /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("space-y-2", hasContent && "mt-4"), children: message.toolCalls.map((toolCall) => /* @__PURE__ */ jsxRuntime.jsx(ToolCallDisplay, { toolCall }, toolCall.id)) })
|
|
3878
|
+
hasToolCalls && /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("space-y-2", hasContent && "mt-4"), children: message.toolCalls.map((toolCall) => /* @__PURE__ */ jsxRuntime.jsx(ToolCallDisplay, { toolCall }, toolCall.id)) }),
|
|
3879
|
+
hasSubAgents && /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("space-y-2 pl-3 border-l border-border/50", (hasContent || hasToolCalls) && "mt-4"), children: message.subAgents.map((sa) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
3880
|
+
SpecialistMessage,
|
|
3881
|
+
{
|
|
3882
|
+
isNested: true,
|
|
3883
|
+
message: {
|
|
3884
|
+
id: sa.id,
|
|
3885
|
+
name: sa.subAgentName,
|
|
3886
|
+
content: typeof sa.output === "string" ? sa.output : "",
|
|
3887
|
+
status: sa.status,
|
|
3888
|
+
input: sa.input,
|
|
3889
|
+
subAgents: sa.subAgents
|
|
3890
|
+
}
|
|
3891
|
+
},
|
|
3892
|
+
sa.id
|
|
3893
|
+
)) })
|
|
3838
3894
|
] }) })
|
|
3839
3895
|
]
|
|
3840
3896
|
}
|
|
@@ -3864,12 +3920,51 @@ var OrchestratorMessage = React3__namespace.memo(
|
|
|
3864
3920
|
}
|
|
3865
3921
|
);
|
|
3866
3922
|
OrchestratorMessage.displayName = "OrchestratorMessage";
|
|
3923
|
+
function parseSystemMessageContent(content) {
|
|
3924
|
+
try {
|
|
3925
|
+
const parsed = JSON.parse(content);
|
|
3926
|
+
if (parsed && typeof parsed === "object") {
|
|
3927
|
+
const url = typeof parsed.url === "string" ? parsed.url : void 0;
|
|
3928
|
+
const mediaType = typeof parsed.mediaType === "string" ? parsed.mediaType : typeof parsed.type === "string" ? parsed.type : void 0;
|
|
3929
|
+
const title = typeof parsed.title === "string" ? parsed.title : typeof parsed.message === "string" ? parsed.message : void 0;
|
|
3930
|
+
if (url) {
|
|
3931
|
+
if ((mediaType == null ? void 0 : mediaType.startsWith("video/")) || /\.(mp4|webm|mov)(\?.*)?$/i.test(url)) {
|
|
3932
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-2", children: [
|
|
3933
|
+
title && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: title }),
|
|
3934
|
+
/* @__PURE__ */ jsxRuntime.jsxs("video", { controls: true, className: "w-full max-w-[360px] rounded-md shadow-sm", children: [
|
|
3935
|
+
/* @__PURE__ */ jsxRuntime.jsx("source", { src: url, type: mediaType || "video/mp4" }),
|
|
3936
|
+
"Your browser does not support the video element."
|
|
3937
|
+
] })
|
|
3938
|
+
] });
|
|
3939
|
+
}
|
|
3940
|
+
if ((mediaType == null ? void 0 : mediaType.startsWith("audio/")) || /\.(wav|mp3|ogg|m4a)(\?.*)?$/i.test(url)) {
|
|
3941
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-2", children: [
|
|
3942
|
+
title && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: title }),
|
|
3943
|
+
/* @__PURE__ */ jsxRuntime.jsxs("audio", { controls: true, className: "w-full max-w-[360px] h-8", children: [
|
|
3944
|
+
/* @__PURE__ */ jsxRuntime.jsx("source", { src: url, type: mediaType || "audio/wav" }),
|
|
3945
|
+
"Your browser does not support the audio element."
|
|
3946
|
+
] })
|
|
3947
|
+
] });
|
|
3948
|
+
}
|
|
3949
|
+
if ((mediaType == null ? void 0 : mediaType.startsWith("image/")) || /\.(png|jpg|jpeg|webp|gif)(\?.*)?$/i.test(url)) {
|
|
3950
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-2", children: [
|
|
3951
|
+
title && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: title }),
|
|
3952
|
+
/* @__PURE__ */ jsxRuntime.jsx("img", { src: url, alt: title || "Image output", className: "max-w-[360px] rounded-md shadow-sm" })
|
|
3953
|
+
] });
|
|
3954
|
+
}
|
|
3955
|
+
}
|
|
3956
|
+
if (title) return /* @__PURE__ */ jsxRuntime.jsx("span", { children: title });
|
|
3957
|
+
}
|
|
3958
|
+
} catch (e) {
|
|
3959
|
+
}
|
|
3960
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { children: content });
|
|
3961
|
+
}
|
|
3867
3962
|
var SystemMessage = React3__namespace.memo(
|
|
3868
3963
|
({ message, renderContent }) => {
|
|
3869
3964
|
if (!message.content || !message.content.trim()) {
|
|
3870
3965
|
return null;
|
|
3871
3966
|
}
|
|
3872
|
-
const contentNode = renderContent ? renderContent(message.content) :
|
|
3967
|
+
const contentNode = renderContent ? renderContent(message.content) : parseSystemMessageContent(message.content);
|
|
3873
3968
|
if (!contentNode) {
|
|
3874
3969
|
return null;
|
|
3875
3970
|
}
|
|
@@ -4088,6 +4183,16 @@ var ReasoningDisplay = ({
|
|
|
4088
4183
|
)
|
|
4089
4184
|
] });
|
|
4090
4185
|
};
|
|
4186
|
+
function toNestedSubAgents(agents) {
|
|
4187
|
+
return agents == null ? void 0 : agents.map((a) => ({
|
|
4188
|
+
id: a.id,
|
|
4189
|
+
subAgentName: a.subAgentName,
|
|
4190
|
+
status: a.status,
|
|
4191
|
+
input: a.input,
|
|
4192
|
+
output: typeof a.output === "string" ? a.output : a.output ? JSON.stringify(a.output) : void 0,
|
|
4193
|
+
subAgents: toNestedSubAgents(a.subAgents)
|
|
4194
|
+
}));
|
|
4195
|
+
}
|
|
4091
4196
|
var AIConversation = React3__namespace.memo(
|
|
4092
4197
|
(_a) => {
|
|
4093
4198
|
var _b = _a, {
|
|
@@ -4312,7 +4417,8 @@ ${newStr}` : newStr;
|
|
|
4312
4417
|
input: subAgent.input,
|
|
4313
4418
|
content: typeof subAgent.output === "string" ? subAgent.output : subAgent.output ? JSON.stringify(subAgent.output) : "",
|
|
4314
4419
|
status: subAgent.status,
|
|
4315
|
-
toolCalls: []
|
|
4420
|
+
toolCalls: [],
|
|
4421
|
+
subAgents: toNestedSubAgents(subAgent.subAgents)
|
|
4316
4422
|
},
|
|
4317
4423
|
isNested: true
|
|
4318
4424
|
},
|
|
@@ -4332,7 +4438,8 @@ ${newStr}` : newStr;
|
|
|
4332
4438
|
input: subAgent.input,
|
|
4333
4439
|
content: typeof subAgent.output === "string" ? subAgent.output : subAgent.output ? JSON.stringify(subAgent.output) : "",
|
|
4334
4440
|
status: subAgent.status,
|
|
4335
|
-
toolCalls: []
|
|
4441
|
+
toolCalls: [],
|
|
4442
|
+
subAgents: toNestedSubAgents(subAgent.subAgents)
|
|
4336
4443
|
},
|
|
4337
4444
|
isNested: true
|
|
4338
4445
|
},
|
|
@@ -12638,6 +12745,145 @@ var AuthCard = React3__namespace.memo(
|
|
|
12638
12745
|
}
|
|
12639
12746
|
);
|
|
12640
12747
|
AuthCard.displayName = "AuthCard";
|
|
12748
|
+
function isVideoFile(file) {
|
|
12749
|
+
var _a, _b, _c, _d;
|
|
12750
|
+
const format = ((_a = file.format) == null ? void 0 : _a.toLowerCase()) || "";
|
|
12751
|
+
const ext = ((_c = (_b = file.name) == null ? void 0 : _b.split(".").pop()) == null ? void 0 : _c.toLowerCase()) || "";
|
|
12752
|
+
if (["mp4", "webm", "mov", "mkv", "avi"].includes(format) || ["mp4", "webm", "mov", "mkv", "avi"].includes(ext)) return true;
|
|
12753
|
+
if ((_d = file.mediaType) == null ? void 0 : _d.startsWith("video/")) return true;
|
|
12754
|
+
if (file.url && /\.(mp4|webm|mov|mkv)(\?.*)?$/i.test(file.url)) return true;
|
|
12755
|
+
return false;
|
|
12756
|
+
}
|
|
12757
|
+
function isAudioFile(file) {
|
|
12758
|
+
var _a, _b, _c, _d;
|
|
12759
|
+
const format = ((_a = file.format) == null ? void 0 : _a.toLowerCase()) || "";
|
|
12760
|
+
const ext = ((_c = (_b = file.name) == null ? void 0 : _b.split(".").pop()) == null ? void 0 : _c.toLowerCase()) || "";
|
|
12761
|
+
if (["wav", "mp3", "ogg", "m4a", "flac", "aac", "wma"].includes(format) || ["wav", "mp3", "ogg", "m4a", "flac", "aac", "wma"].includes(ext)) return true;
|
|
12762
|
+
if ((_d = file.mediaType) == null ? void 0 : _d.startsWith("audio/")) return true;
|
|
12763
|
+
if (file.url && /\.(wav|mp3|ogg|m4a|flac|aac)(\?.*)?$/i.test(file.url)) return true;
|
|
12764
|
+
return false;
|
|
12765
|
+
}
|
|
12766
|
+
function isImageFile(file) {
|
|
12767
|
+
var _a, _b, _c, _d;
|
|
12768
|
+
const format = ((_a = file.format) == null ? void 0 : _a.toLowerCase()) || "";
|
|
12769
|
+
const ext = ((_c = (_b = file.name) == null ? void 0 : _b.split(".").pop()) == null ? void 0 : _c.toLowerCase()) || "";
|
|
12770
|
+
if (["png", "jpg", "jpeg", "webp", "gif", "svg", "ico", "bmp"].includes(format) || ["png", "jpg", "jpeg", "webp", "gif", "svg", "ico", "bmp"].includes(ext)) return true;
|
|
12771
|
+
if ((_d = file.mediaType) == null ? void 0 : _d.startsWith("image/")) return true;
|
|
12772
|
+
if (file.url && /\.(png|jpg|jpeg|webp|gif|svg)(\?.*)?$/i.test(file.url)) return true;
|
|
12773
|
+
return false;
|
|
12774
|
+
}
|
|
12775
|
+
function isPdfFile(file) {
|
|
12776
|
+
var _a, _b, _c;
|
|
12777
|
+
const format = ((_a = file.format) == null ? void 0 : _a.toLowerCase()) || "";
|
|
12778
|
+
const ext = ((_c = (_b = file.name) == null ? void 0 : _b.split(".").pop()) == null ? void 0 : _c.toLowerCase()) || "";
|
|
12779
|
+
return format === "pdf" || ext === "pdf" || file.mediaType === "application/pdf";
|
|
12780
|
+
}
|
|
12781
|
+
function isMediaFile(file) {
|
|
12782
|
+
return isVideoFile(file) || isAudioFile(file) || isImageFile(file) || isPdfFile(file);
|
|
12783
|
+
}
|
|
12784
|
+
var MediaPreview = ({ file, className }) => {
|
|
12785
|
+
var _a;
|
|
12786
|
+
const isVideo = isVideoFile(file);
|
|
12787
|
+
const isAudio = isAudioFile(file);
|
|
12788
|
+
const isImage = isImageFile(file);
|
|
12789
|
+
const isPdf = isPdfFile(file);
|
|
12790
|
+
const mediaUrl = file.url;
|
|
12791
|
+
if (!mediaUrl) {
|
|
12792
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col items-center justify-center h-full p-8 text-center", className), children: [
|
|
12793
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-16 w-16 items-center justify-center rounded-2xl bg-muted/60 mb-4 text-muted-foreground", children: [
|
|
12794
|
+
isVideo && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "film", className: "h-8 w-8" }),
|
|
12795
|
+
isAudio && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "music", className: "h-8 w-8" }),
|
|
12796
|
+
isImage && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "image", className: "h-8 w-8" }),
|
|
12797
|
+
isPdf && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "file-text", className: "h-8 w-8" }),
|
|
12798
|
+
!isVideo && !isAudio && !isImage && !isPdf && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "alert-circle", className: "h-8 w-8" })
|
|
12799
|
+
] }),
|
|
12800
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-base font-medium text-foreground mb-1", children: file.name || "Media File" }),
|
|
12801
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground max-w-sm", children: "No direct stream URL is available for this file yet." })
|
|
12802
|
+
] });
|
|
12803
|
+
}
|
|
12804
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col h-full w-full overflow-y-auto p-6 bg-background/50", className), children: [
|
|
12805
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between pb-4 mb-6 border-b border-border", children: [
|
|
12806
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
12807
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-10 w-10 items-center justify-center rounded-xl bg-primary/10 text-primary", children: [
|
|
12808
|
+
isVideo && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "film", className: "h-5 w-5" }),
|
|
12809
|
+
isAudio && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "music", className: "h-5 w-5" }),
|
|
12810
|
+
isImage && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "image", className: "h-5 w-5" }),
|
|
12811
|
+
isPdf && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "file-text", className: "h-5 w-5" })
|
|
12812
|
+
] }),
|
|
12813
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
12814
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-sm font-semibold text-foreground tracking-tight", children: file.name }),
|
|
12815
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: file.mediaType || ((_a = file.format) == null ? void 0 : _a.toUpperCase()) || "Binary Media" })
|
|
12816
|
+
] })
|
|
12817
|
+
] }),
|
|
12818
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
12819
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
12820
|
+
"a",
|
|
12821
|
+
{
|
|
12822
|
+
href: mediaUrl,
|
|
12823
|
+
target: "_blank",
|
|
12824
|
+
rel: "noopener noreferrer",
|
|
12825
|
+
download: file.name,
|
|
12826
|
+
className: "inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-lg border border-border bg-background hover:bg-muted text-foreground transition-colors shadow-sm",
|
|
12827
|
+
children: [
|
|
12828
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "download", className: "h-3.5 w-3.5" }),
|
|
12829
|
+
"Download"
|
|
12830
|
+
]
|
|
12831
|
+
}
|
|
12832
|
+
),
|
|
12833
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
12834
|
+
"a",
|
|
12835
|
+
{
|
|
12836
|
+
href: mediaUrl,
|
|
12837
|
+
target: "_blank",
|
|
12838
|
+
rel: "noopener noreferrer",
|
|
12839
|
+
className: "inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-lg border border-border bg-background hover:bg-muted text-foreground transition-colors shadow-sm",
|
|
12840
|
+
children: [
|
|
12841
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "external-link", className: "h-3.5 w-3.5" }),
|
|
12842
|
+
"Open"
|
|
12843
|
+
]
|
|
12844
|
+
}
|
|
12845
|
+
)
|
|
12846
|
+
] })
|
|
12847
|
+
] }),
|
|
12848
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 flex flex-col items-center justify-center min-h-[300px]", children: [
|
|
12849
|
+
isVideo && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full max-w-4xl flex flex-col items-center justify-center bg-black/95 rounded-2xl overflow-hidden shadow-lg border border-border/40", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
12850
|
+
"video",
|
|
12851
|
+
{
|
|
12852
|
+
controls: true,
|
|
12853
|
+
playsInline: true,
|
|
12854
|
+
preload: "metadata",
|
|
12855
|
+
src: mediaUrl,
|
|
12856
|
+
className: "max-h-[65vh] w-auto max-w-full rounded-2xl",
|
|
12857
|
+
children: "Your browser does not support the video tag."
|
|
12858
|
+
}
|
|
12859
|
+
) }),
|
|
12860
|
+
isAudio && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full max-w-xl p-8 rounded-2xl border border-border bg-card shadow-sm flex flex-col items-center gap-6", children: [
|
|
12861
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-20 w-20 items-center justify-center rounded-full bg-primary/10 text-primary", children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "music", className: "h-10 w-10 animate-pulse" }) }),
|
|
12862
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
|
|
12863
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-base font-semibold text-foreground mb-1", children: file.name }),
|
|
12864
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground uppercase tracking-wider", children: "Audio Playback" })
|
|
12865
|
+
] }),
|
|
12866
|
+
/* @__PURE__ */ jsxRuntime.jsx("audio", { controls: true, preload: "metadata", src: mediaUrl, className: "w-full h-12", children: "Your browser does not support the audio element." })
|
|
12867
|
+
] }),
|
|
12868
|
+
isImage && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center w-full max-w-4xl rounded-2xl border border-border bg-muted/20 p-4 shadow-sm", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
12869
|
+
"img",
|
|
12870
|
+
{
|
|
12871
|
+
src: mediaUrl,
|
|
12872
|
+
alt: file.name,
|
|
12873
|
+
className: "max-h-[68vh] w-auto max-w-full rounded-xl object-contain shadow-md"
|
|
12874
|
+
}
|
|
12875
|
+
) }),
|
|
12876
|
+
isPdf && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full min-h-[500px] rounded-2xl overflow-hidden border border-border shadow-sm", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
12877
|
+
"iframe",
|
|
12878
|
+
{
|
|
12879
|
+
src: mediaUrl,
|
|
12880
|
+
title: file.name,
|
|
12881
|
+
className: "w-full h-full min-h-[500px]"
|
|
12882
|
+
}
|
|
12883
|
+
) })
|
|
12884
|
+
] })
|
|
12885
|
+
] });
|
|
12886
|
+
};
|
|
12641
12887
|
var SpecNavigator = React3__namespace.memo(
|
|
12642
12888
|
({ groups, selectedFileId, onFileSelect, className }) => {
|
|
12643
12889
|
var _a, _b;
|
|
@@ -13674,7 +13920,7 @@ function formatJson(text) {
|
|
|
13674
13920
|
}
|
|
13675
13921
|
var TextEditor = React3__namespace.default.memo(
|
|
13676
13922
|
(props) => {
|
|
13677
|
-
var _a, _b;
|
|
13923
|
+
var _a, _b, _c;
|
|
13678
13924
|
const {
|
|
13679
13925
|
mode = "review",
|
|
13680
13926
|
currentUser: currentUser2,
|
|
@@ -13748,7 +13994,6 @@ var TextEditor = React3__namespace.default.memo(
|
|
|
13748
13994
|
const isExternal = (href == null ? void 0 : href.startsWith("http://")) || (href == null ? void 0 : href.startsWith("https://")) || (href == null ? void 0 : href.startsWith("mailto:"));
|
|
13749
13995
|
const isAnchor = href == null ? void 0 : href.startsWith("#");
|
|
13750
13996
|
const handleClick = (e) => {
|
|
13751
|
-
var _a3, _b2;
|
|
13752
13997
|
if (!isExternal && !isAnchor && href) {
|
|
13753
13998
|
e.preventDefault();
|
|
13754
13999
|
let targetId = href;
|
|
@@ -13778,29 +14023,17 @@ var TextEditor = React3__namespace.default.memo(
|
|
|
13778
14023
|
} else if (targetId.startsWith("./")) {
|
|
13779
14024
|
targetId = targetId.slice(2);
|
|
13780
14025
|
}
|
|
13781
|
-
console.log("[TextEditor:LinkComponent:handleClick]", {
|
|
13782
|
-
href,
|
|
13783
|
-
activeDocumentId: props.activeDocumentId,
|
|
13784
|
-
computedTargetId: targetId,
|
|
13785
|
-
documentsCount: (_a3 = props.documents) == null ? void 0 : _a3.length
|
|
13786
|
-
});
|
|
13787
14026
|
if (isMultiTab && props.documents) {
|
|
13788
14027
|
const cleanTarget = targetId.replace(/^\.\//, "").replace(/^\//, "");
|
|
13789
14028
|
const matchedDoc = props.documents.find((doc) => {
|
|
13790
14029
|
const cleanDocId = doc.file.id.replace(/^\.\//, "").replace(/^\//, "");
|
|
13791
14030
|
return cleanDocId === cleanTarget || cleanDocId.endsWith("/" + cleanTarget) || cleanTarget.endsWith("/" + cleanDocId) || doc.file.name === targetId;
|
|
13792
14031
|
});
|
|
13793
|
-
console.log("[TextEditor:LinkComponent:matching]", {
|
|
13794
|
-
cleanTarget,
|
|
13795
|
-
matchedDocId: (_b2 = matchedDoc == null ? void 0 : matchedDoc.file) == null ? void 0 : _b2.id,
|
|
13796
|
-
availableDocIds: props.documents.map((d) => d.file.id)
|
|
13797
|
-
});
|
|
13798
14032
|
if (matchedDoc) {
|
|
13799
14033
|
targetId = matchedDoc.file.id;
|
|
13800
14034
|
}
|
|
13801
14035
|
}
|
|
13802
14036
|
if (handleTabSelect) {
|
|
13803
|
-
console.log("[TextEditor:LinkComponent:onTabSelect]", targetId);
|
|
13804
14037
|
handleTabSelect(targetId);
|
|
13805
14038
|
}
|
|
13806
14039
|
}
|
|
@@ -13810,6 +14043,7 @@ var TextEditor = React3__namespace.default.memo(
|
|
|
13810
14043
|
}
|
|
13811
14044
|
return /* @__PURE__ */ jsxRuntime.jsx("a", __spreadValues({ href, onClick: handleClick, className: "text-primary hover:underline cursor-pointer" }, rest));
|
|
13812
14045
|
}, [handleTabSelect, isMultiTab, props.activeDocumentId, props.documents]);
|
|
14046
|
+
const markdownComponents = React3.useMemo(() => ({ a: LinkComponent }), [LinkComponent]);
|
|
13813
14047
|
if (!isMultiTab) {
|
|
13814
14048
|
const format = props.format || "markdown";
|
|
13815
14049
|
const isMarkdown = format === "markdown" || format === "md" || format === "mdx";
|
|
@@ -13819,7 +14053,7 @@ var TextEditor = React3__namespace.default.memo(
|
|
|
13819
14053
|
const content = isCode ? `\`\`\`${format}
|
|
13820
14054
|
${format === "json" ? formatJson(contentStr) : contentStr}
|
|
13821
14055
|
\`\`\`` : contentStr;
|
|
13822
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("text-editor p-6 flex flex-col h-screen w-full flex-1", className), children: /* @__PURE__ */ jsxRuntime.jsx(StreamingMarkdown, { mode: "
|
|
14056
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("text-editor p-6 flex flex-col h-screen w-full flex-1", className), children: /* @__PURE__ */ jsxRuntime.jsx(StreamingMarkdown, { mode: "static", isAnimating: false, components: markdownComponents, children: content }) });
|
|
13823
14057
|
}
|
|
13824
14058
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("text-editor flex flex-col h-screen w-full flex-1", className), children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
13825
14059
|
DocumentEditorWithComments,
|
|
@@ -13853,6 +14087,20 @@ ${format === "json" ? formatJson(contentStr) : contentStr}
|
|
|
13853
14087
|
),
|
|
13854
14088
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 flex items-center justify-center p-6 text-muted-foreground", children: "No documents selected" })
|
|
13855
14089
|
] });
|
|
14090
|
+
} else if (isMediaFile(currentDocument.file)) {
|
|
14091
|
+
editorPane = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-editor flex flex-col h-full w-full", children: [
|
|
14092
|
+
!hideTabBar && /* @__PURE__ */ jsxRuntime.jsx(
|
|
14093
|
+
DocumentTabBar,
|
|
14094
|
+
{
|
|
14095
|
+
className: "w-full",
|
|
14096
|
+
tabs: ((_b = props.documents) == null ? void 0 : _b.map((doc) => doc.file)) || [],
|
|
14097
|
+
activeTabId: props.activeDocumentId,
|
|
14098
|
+
onTabSelect: props.onTabSelect,
|
|
14099
|
+
onTabClose: props.onTabClose
|
|
14100
|
+
}
|
|
14101
|
+
),
|
|
14102
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-auto", children: /* @__PURE__ */ jsxRuntime.jsx(MediaPreview, { file: currentDocument.file }) })
|
|
14103
|
+
] });
|
|
13856
14104
|
} else {
|
|
13857
14105
|
const format = currentDocument.file.format || "markdown";
|
|
13858
14106
|
const isMarkdownMulti = format === "markdown" || format === "md" || format === "mdx";
|
|
@@ -13870,7 +14118,7 @@ ${format === "json" ? formatJson(contentStr) : contentStr}
|
|
|
13870
14118
|
DocumentTabBar,
|
|
13871
14119
|
{
|
|
13872
14120
|
className: "w-full",
|
|
13873
|
-
tabs: ((
|
|
14121
|
+
tabs: ((_c = props.documents) == null ? void 0 : _c.map((doc) => doc.file)) || [],
|
|
13874
14122
|
activeTabId: props.activeDocumentId,
|
|
13875
14123
|
onTabSelect: props.onTabSelect,
|
|
13876
14124
|
onTabClose: props.onTabClose
|
|
@@ -13879,10 +14127,10 @@ ${format === "json" ? formatJson(contentStr) : contentStr}
|
|
|
13879
14127
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-auto", children: !hasContent ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center p-8 text-muted-foreground animate-pulse", children: "Loading document content..." }) : renderAsStreamdown ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
13880
14128
|
StreamingMarkdown,
|
|
13881
14129
|
{
|
|
13882
|
-
mode: "
|
|
13883
|
-
isAnimating:
|
|
14130
|
+
mode: "static",
|
|
14131
|
+
isAnimating: false,
|
|
13884
14132
|
className: "[&>*:first-child]:mt-0 [&>*:last-child]:mb-0",
|
|
13885
|
-
components:
|
|
14133
|
+
components: markdownComponents,
|
|
13886
14134
|
children: isCodeMulti ? `\`\`\`${format}
|
|
13887
14135
|
${format === "json" ? formatJson(currentDocument.content) : currentDocument.content}
|
|
13888
14136
|
\`\`\`` : currentDocument.content
|