@malette/agent-sdk 0.1.1-alpha.0 → 0.1.3-beta.1
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/index.js +2741 -162
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2736 -164
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +1451 -1997
- package/package.json +7 -5
package/dist/index.js
CHANGED
|
@@ -13,6 +13,7 @@ var DialogPrimitive = require('@radix-ui/react-dialog');
|
|
|
13
13
|
var reactSlot = require('@radix-ui/react-slot');
|
|
14
14
|
var ScrollAreaPrimitive = require('@radix-ui/react-scroll-area');
|
|
15
15
|
require('react-dom');
|
|
16
|
+
var marked = require('marked');
|
|
16
17
|
|
|
17
18
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
18
19
|
|
|
@@ -426,6 +427,52 @@ AI\u56DE\u590D\u6458\u8981\uFF1A${assistantMessage.slice(0, 200)}` : ""}`
|
|
|
426
427
|
return userMessage.slice(0, 20) + (userMessage.length > 20 ? "..." : "");
|
|
427
428
|
}
|
|
428
429
|
}
|
|
430
|
+
var artifactService = {
|
|
431
|
+
/**
|
|
432
|
+
* 获取会话的所有产物列表
|
|
433
|
+
*/
|
|
434
|
+
list: async (sessionId) => {
|
|
435
|
+
return fetcher(`${API_BASE}/sessions/${sessionId}/artifacts`);
|
|
436
|
+
},
|
|
437
|
+
/**
|
|
438
|
+
* 获取产物详情
|
|
439
|
+
*/
|
|
440
|
+
get: async (artifactId) => {
|
|
441
|
+
return fetcher(`${API_BASE}/artifacts/${artifactId}`);
|
|
442
|
+
},
|
|
443
|
+
/**
|
|
444
|
+
* 更新产物内容(用户编辑后保存)
|
|
445
|
+
*/
|
|
446
|
+
updateContent: async (artifactId, content) => {
|
|
447
|
+
return fetcher(`${API_BASE}/artifacts/${artifactId}/content`, {
|
|
448
|
+
method: "PUT",
|
|
449
|
+
body: JSON.stringify({ content })
|
|
450
|
+
});
|
|
451
|
+
},
|
|
452
|
+
/**
|
|
453
|
+
* 删除产物
|
|
454
|
+
*/
|
|
455
|
+
delete: async (artifactId) => {
|
|
456
|
+
return fetcher(`${API_BASE}/artifacts/${artifactId}`, {
|
|
457
|
+
method: "DELETE"
|
|
458
|
+
});
|
|
459
|
+
},
|
|
460
|
+
/**
|
|
461
|
+
* 获取产物版本历史
|
|
462
|
+
*/
|
|
463
|
+
getVersions: async (artifactId) => {
|
|
464
|
+
return fetcher(`${API_BASE}/artifacts/${artifactId}/versions`);
|
|
465
|
+
},
|
|
466
|
+
/**
|
|
467
|
+
* 回滚到指定版本
|
|
468
|
+
*/
|
|
469
|
+
revert: async (artifactId, version) => {
|
|
470
|
+
return fetcher(`${API_BASE}/artifacts/${artifactId}/revert`, {
|
|
471
|
+
method: "POST",
|
|
472
|
+
body: JSON.stringify({ version })
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
};
|
|
429
476
|
var shareService = {
|
|
430
477
|
/**
|
|
431
478
|
* 创建分享链接
|
|
@@ -814,6 +861,9 @@ var useAgentStore = zustand.create()(
|
|
|
814
861
|
subAgents: [],
|
|
815
862
|
tools: [],
|
|
816
863
|
skills: [],
|
|
864
|
+
artifacts: {},
|
|
865
|
+
artifactOrder: [],
|
|
866
|
+
activeArtifactId: null,
|
|
817
867
|
// ============ Session Actions ============
|
|
818
868
|
setSessions: (sessions) => set({ sessions }, false, "setSessions"),
|
|
819
869
|
setTools: (tools) => set({ tools }, false, "setTools"),
|
|
@@ -1178,19 +1228,99 @@ var useAgentStore = zustand.create()(
|
|
|
1178
1228
|
false,
|
|
1179
1229
|
"setActiveSubAgent"
|
|
1180
1230
|
),
|
|
1231
|
+
// ============ Artifact Actions ============
|
|
1232
|
+
upsertArtifact: (artifact) => set(
|
|
1233
|
+
(state) => {
|
|
1234
|
+
const isNew = !state.artifacts[artifact.id];
|
|
1235
|
+
return {
|
|
1236
|
+
artifacts: {
|
|
1237
|
+
...state.artifacts,
|
|
1238
|
+
[artifact.id]: artifact
|
|
1239
|
+
},
|
|
1240
|
+
artifactOrder: isNew ? [...state.artifactOrder, artifact.id] : state.artifactOrder
|
|
1241
|
+
};
|
|
1242
|
+
},
|
|
1243
|
+
false,
|
|
1244
|
+
"upsertArtifact"
|
|
1245
|
+
),
|
|
1246
|
+
updateArtifactContent: (artifactId, content, source) => set(
|
|
1247
|
+
(state) => {
|
|
1248
|
+
const existing = state.artifacts[artifactId];
|
|
1249
|
+
if (!existing) return state;
|
|
1250
|
+
return {
|
|
1251
|
+
artifacts: {
|
|
1252
|
+
...state.artifacts,
|
|
1253
|
+
[artifactId]: {
|
|
1254
|
+
...existing,
|
|
1255
|
+
currentContent: content,
|
|
1256
|
+
version: existing.version + 1,
|
|
1257
|
+
gmtModified: (/* @__PURE__ */ new Date()).toISOString()
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
};
|
|
1261
|
+
},
|
|
1262
|
+
false,
|
|
1263
|
+
"updateArtifactContent"
|
|
1264
|
+
),
|
|
1265
|
+
setActiveArtifact: (artifactId) => set(
|
|
1266
|
+
{ activeArtifactId: artifactId },
|
|
1267
|
+
false,
|
|
1268
|
+
"setActiveArtifact"
|
|
1269
|
+
),
|
|
1270
|
+
removeArtifact: (artifactId) => set(
|
|
1271
|
+
(state) => {
|
|
1272
|
+
const { [artifactId]: _, ...remaining } = state.artifacts;
|
|
1273
|
+
return {
|
|
1274
|
+
artifacts: remaining,
|
|
1275
|
+
artifactOrder: state.artifactOrder.filter((id) => id !== artifactId),
|
|
1276
|
+
activeArtifactId: state.activeArtifactId === artifactId ? null : state.activeArtifactId
|
|
1277
|
+
};
|
|
1278
|
+
},
|
|
1279
|
+
false,
|
|
1280
|
+
"removeArtifact"
|
|
1281
|
+
),
|
|
1282
|
+
clearArtifacts: () => set(
|
|
1283
|
+
{ artifacts: {}, artifactOrder: [], activeArtifactId: null },
|
|
1284
|
+
false,
|
|
1285
|
+
"clearArtifacts"
|
|
1286
|
+
),
|
|
1287
|
+
setArtifacts: (artifacts) => set(
|
|
1288
|
+
{
|
|
1289
|
+
artifacts: artifacts.reduce((acc, a) => {
|
|
1290
|
+
acc[a.id] = a;
|
|
1291
|
+
return acc;
|
|
1292
|
+
}, {}),
|
|
1293
|
+
artifactOrder: artifacts.map((a) => a.id)
|
|
1294
|
+
},
|
|
1295
|
+
false,
|
|
1296
|
+
"setArtifacts"
|
|
1297
|
+
),
|
|
1298
|
+
reorderArtifacts: (fromIndex, toIndex) => set(
|
|
1299
|
+
(state) => {
|
|
1300
|
+
const newOrder = [...state.artifactOrder];
|
|
1301
|
+
const [movedId] = newOrder.splice(fromIndex, 1);
|
|
1302
|
+
newOrder.splice(toIndex, 0, movedId);
|
|
1303
|
+
return { artifactOrder: newOrder };
|
|
1304
|
+
},
|
|
1305
|
+
false,
|
|
1306
|
+
"reorderArtifacts"
|
|
1307
|
+
),
|
|
1181
1308
|
// ============ 复合操作 ============
|
|
1182
1309
|
startNewChat: (sessionId) => {
|
|
1183
1310
|
set(
|
|
1184
1311
|
(state) => ({
|
|
1185
1312
|
messages: [],
|
|
1186
|
-
chatUI: initialChatUIState
|
|
1313
|
+
chatUI: initialChatUIState,
|
|
1314
|
+
artifacts: {},
|
|
1315
|
+
artifactOrder: [],
|
|
1316
|
+
activeArtifactId: null
|
|
1187
1317
|
}),
|
|
1188
1318
|
false,
|
|
1189
1319
|
"startNewChat"
|
|
1190
1320
|
);
|
|
1191
1321
|
},
|
|
1192
1322
|
resetChatState: () => set(
|
|
1193
|
-
{ chatUI: initialChatUIState },
|
|
1323
|
+
{ chatUI: initialChatUIState, artifacts: {}, artifactOrder: [], activeArtifactId: null },
|
|
1194
1324
|
false,
|
|
1195
1325
|
"resetChatState"
|
|
1196
1326
|
)
|
|
@@ -1217,6 +1347,23 @@ var useCurrentSession = () => useAgentStore((state) => state.currentSession);
|
|
|
1217
1347
|
var useSessions = () => useAgentStore((state) => state.sessions);
|
|
1218
1348
|
var useSubAgents = () => useAgentStore((state) => state.subAgents);
|
|
1219
1349
|
var useChatUI = () => useAgentStore((state) => state.chatUI);
|
|
1350
|
+
var useArtifacts = () => useAgentStore((state) => state.artifacts);
|
|
1351
|
+
var useActiveArtifactId = () => useAgentStore((state) => state.activeArtifactId);
|
|
1352
|
+
var useActiveArtifact = () => {
|
|
1353
|
+
const artifacts = useAgentStore((state) => state.artifacts);
|
|
1354
|
+
const activeId = useAgentStore((state) => state.activeArtifactId);
|
|
1355
|
+
return activeId ? artifacts[activeId] ?? null : null;
|
|
1356
|
+
};
|
|
1357
|
+
var useArtifactList = () => {
|
|
1358
|
+
const artifacts = useAgentStore((state) => state.artifacts);
|
|
1359
|
+
const artifactOrder = useAgentStore((state) => state.artifactOrder);
|
|
1360
|
+
const ordered = artifactOrder.map((id) => artifacts[id]).filter(Boolean);
|
|
1361
|
+
const unordered = Object.values(artifacts).filter(
|
|
1362
|
+
(a) => !artifactOrder.includes(a.id)
|
|
1363
|
+
);
|
|
1364
|
+
return [...ordered, ...unordered];
|
|
1365
|
+
};
|
|
1366
|
+
var useArtifactOrder = () => useAgentStore((state) => state.artifactOrder);
|
|
1220
1367
|
var useSessionsLoading = () => useAgentStore((state) => state.sessionsLoading);
|
|
1221
1368
|
var findMessageById = (messageId) => {
|
|
1222
1369
|
return useAgentStore.getState().messages.find((m) => m.messageId === messageId);
|
|
@@ -1405,7 +1552,11 @@ function useSSE(options) {
|
|
|
1405
1552
|
setShowPlanConfirmDialog,
|
|
1406
1553
|
setShowHumanInputDialog,
|
|
1407
1554
|
setWaitingStepId,
|
|
1408
|
-
clearPlanState
|
|
1555
|
+
clearPlanState,
|
|
1556
|
+
// Artifact actions
|
|
1557
|
+
upsertArtifact,
|
|
1558
|
+
updateArtifactContent,
|
|
1559
|
+
setActiveArtifact
|
|
1409
1560
|
} = useAgentStore();
|
|
1410
1561
|
const clearHeartbeatTimeout = React20.useCallback(() => {
|
|
1411
1562
|
if (heartbeatTimeoutRef.current) {
|
|
@@ -1603,6 +1754,37 @@ function useSSE(options) {
|
|
|
1603
1754
|
});
|
|
1604
1755
|
return;
|
|
1605
1756
|
}
|
|
1757
|
+
if (eventType === "artifact_created") {
|
|
1758
|
+
const sessionId = useAgentStore.getState().currentSession?.sessionId;
|
|
1759
|
+
if (data.artifactId && sessionId) {
|
|
1760
|
+
const artifactType = data.type || "code";
|
|
1761
|
+
const artifactEntry = {
|
|
1762
|
+
id: data.artifactId,
|
|
1763
|
+
sessionId,
|
|
1764
|
+
type: artifactType,
|
|
1765
|
+
title: data.title || "Untitled",
|
|
1766
|
+
currentContent: data.content || "",
|
|
1767
|
+
language: data.language,
|
|
1768
|
+
version: 1,
|
|
1769
|
+
source: "tool",
|
|
1770
|
+
sourceId: data.sourceToolCallId,
|
|
1771
|
+
metadata: data.metadata,
|
|
1772
|
+
gmtCreate: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1773
|
+
gmtModified: (/* @__PURE__ */ new Date()).toISOString()
|
|
1774
|
+
};
|
|
1775
|
+
upsertArtifact(artifactEntry);
|
|
1776
|
+
setActiveArtifact(data.artifactId);
|
|
1777
|
+
console.log("[SSE] Artifact created:", data.artifactId, data.title);
|
|
1778
|
+
}
|
|
1779
|
+
return;
|
|
1780
|
+
}
|
|
1781
|
+
if (eventType === "artifact_updated") {
|
|
1782
|
+
if (data.artifactId && data.content) {
|
|
1783
|
+
updateArtifactContent(data.artifactId, data.content, "ai");
|
|
1784
|
+
console.log("[SSE] Artifact updated:", data.artifactId, "version:", data.version);
|
|
1785
|
+
}
|
|
1786
|
+
return;
|
|
1787
|
+
}
|
|
1606
1788
|
const rawToolCalls = data.toolCalls || data.tool_calls || data.actions || [];
|
|
1607
1789
|
const normalizedToolCalls = rawToolCalls.length > 0 ? normalizeToolCalls2(rawToolCalls) : void 0;
|
|
1608
1790
|
let finalToolCalls = normalizedToolCalls;
|
|
@@ -2308,7 +2490,7 @@ function useSSE(options) {
|
|
|
2308
2490
|
try {
|
|
2309
2491
|
console.log("[SSE] Step 1: Sending message...");
|
|
2310
2492
|
const response = await messageService.sendStream(
|
|
2311
|
-
{ sessionId, content, frontendTools: sendOptions?.frontendTools },
|
|
2493
|
+
{ sessionId, content, frontendTools: sendOptions?.frontendTools, artifactContext: sendOptions?.artifactContext },
|
|
2312
2494
|
abortControllerRef.current.signal
|
|
2313
2495
|
);
|
|
2314
2496
|
const reader = response.body?.getReader();
|
|
@@ -2448,6 +2630,92 @@ function useSSE(options) {
|
|
|
2448
2630
|
isConnected
|
|
2449
2631
|
};
|
|
2450
2632
|
}
|
|
2633
|
+
var CHANNEL_ID = "adic-agent-canvas-bridge";
|
|
2634
|
+
function useCanvasBridge(options = {}) {
|
|
2635
|
+
const {
|
|
2636
|
+
canvasIframeRef,
|
|
2637
|
+
targetOrigin = "*",
|
|
2638
|
+
enabled = false,
|
|
2639
|
+
onArtifactSelected,
|
|
2640
|
+
onArtifactContentChanged
|
|
2641
|
+
} = options;
|
|
2642
|
+
const optionsRef = React20.useRef(options);
|
|
2643
|
+
optionsRef.current = options;
|
|
2644
|
+
const postToCanvas = React20.useCallback((type, payload) => {
|
|
2645
|
+
const iframe = canvasIframeRef?.current;
|
|
2646
|
+
if (!iframe?.contentWindow) {
|
|
2647
|
+
console.warn("[CanvasBridge] Canvas iframe not available");
|
|
2648
|
+
return;
|
|
2649
|
+
}
|
|
2650
|
+
const envelope = {
|
|
2651
|
+
channel: CHANNEL_ID,
|
|
2652
|
+
message: {
|
|
2653
|
+
type,
|
|
2654
|
+
payload,
|
|
2655
|
+
timestamp: Date.now()
|
|
2656
|
+
}
|
|
2657
|
+
};
|
|
2658
|
+
iframe.contentWindow.postMessage(envelope, targetOrigin);
|
|
2659
|
+
console.log("[CanvasBridge] Sent:", type, payload.artifactId || payload.artifact?.id);
|
|
2660
|
+
}, [canvasIframeRef, targetOrigin]);
|
|
2661
|
+
React20.useEffect(() => {
|
|
2662
|
+
if (!enabled) return;
|
|
2663
|
+
const handleMessage = (event) => {
|
|
2664
|
+
if (targetOrigin !== "*" && event.origin !== targetOrigin) return;
|
|
2665
|
+
const envelope = event.data;
|
|
2666
|
+
if (!envelope || envelope.channel !== CHANNEL_ID) return;
|
|
2667
|
+
const { type, payload } = envelope.message;
|
|
2668
|
+
console.log("[CanvasBridge] Received:", type, payload);
|
|
2669
|
+
switch (type) {
|
|
2670
|
+
case "artifact_selected": {
|
|
2671
|
+
if (payload.artifactId) {
|
|
2672
|
+
optionsRef.current.onArtifactSelected?.(payload.artifactId);
|
|
2673
|
+
useAgentStore.getState().setActiveArtifact(payload.artifactId);
|
|
2674
|
+
}
|
|
2675
|
+
break;
|
|
2676
|
+
}
|
|
2677
|
+
case "artifact_content_changed": {
|
|
2678
|
+
if (payload.artifactId && payload.content !== void 0) {
|
|
2679
|
+
optionsRef.current.onArtifactContentChanged?.(payload.artifactId, payload.content);
|
|
2680
|
+
useAgentStore.getState().updateArtifactContent(
|
|
2681
|
+
payload.artifactId,
|
|
2682
|
+
payload.content,
|
|
2683
|
+
"user"
|
|
2684
|
+
);
|
|
2685
|
+
}
|
|
2686
|
+
break;
|
|
2687
|
+
}
|
|
2688
|
+
default:
|
|
2689
|
+
console.log("[CanvasBridge] Unknown message type:", type);
|
|
2690
|
+
}
|
|
2691
|
+
};
|
|
2692
|
+
window.addEventListener("message", handleMessage);
|
|
2693
|
+
return () => window.removeEventListener("message", handleMessage);
|
|
2694
|
+
}, [enabled, targetOrigin]);
|
|
2695
|
+
const notifyArtifactCreated = React20.useCallback((artifact) => {
|
|
2696
|
+
if (!enabled) return;
|
|
2697
|
+
postToCanvas("artifact_created", { artifact });
|
|
2698
|
+
}, [enabled, postToCanvas]);
|
|
2699
|
+
const notifyArtifactUpdated = React20.useCallback((artifact) => {
|
|
2700
|
+
if (!enabled) return;
|
|
2701
|
+
postToCanvas("artifact_updated", { artifact });
|
|
2702
|
+
}, [enabled, postToCanvas]);
|
|
2703
|
+
const notifyArtifactDeleted = React20.useCallback((artifactId) => {
|
|
2704
|
+
if (!enabled) return;
|
|
2705
|
+
postToCanvas("artifact_deleted", { artifactId });
|
|
2706
|
+
}, [enabled, postToCanvas]);
|
|
2707
|
+
const syncAllArtifacts = React20.useCallback(() => {
|
|
2708
|
+
if (!enabled) return;
|
|
2709
|
+
const artifacts = Object.values(useAgentStore.getState().artifacts);
|
|
2710
|
+
postToCanvas("artifacts_sync", { artifacts });
|
|
2711
|
+
}, [enabled, postToCanvas]);
|
|
2712
|
+
return {
|
|
2713
|
+
notifyArtifactCreated,
|
|
2714
|
+
notifyArtifactUpdated,
|
|
2715
|
+
notifyArtifactDeleted,
|
|
2716
|
+
syncAllArtifacts
|
|
2717
|
+
};
|
|
2718
|
+
}
|
|
2451
2719
|
|
|
2452
2720
|
// src/hooks/sseConnection.ts
|
|
2453
2721
|
var SSE_HEARTBEAT_TIMEOUT2 = 45e3;
|
|
@@ -2910,14 +3178,14 @@ function getParamsSummary(params, maxItems = 2) {
|
|
|
2910
3178
|
}
|
|
2911
3179
|
function generateToolCallDescription(toolName, params) {
|
|
2912
3180
|
const formatted = formatParameters(params);
|
|
2913
|
-
const
|
|
3181
|
+
const prompt2 = formatted.find((p) => p.key === "prompt" || p.key === "query" || p.key === "content");
|
|
2914
3182
|
const image2 = formatted.find((p) => p.key === "image" || p.key === "image_url" || p.key === "imageUrl");
|
|
2915
3183
|
const style = formatted.find((p) => p.key === "style");
|
|
2916
3184
|
formatted.find((p) => p.key === "width" || p.key === "size");
|
|
2917
3185
|
const toolLower = toolName.toLowerCase();
|
|
2918
3186
|
if (toolLower.includes("generate") || toolLower.includes("image") || toolLower.includes("art")) {
|
|
2919
|
-
if (
|
|
2920
|
-
return `\u751F\u6210\u56FE\u50CF\uFF1A${
|
|
3187
|
+
if (prompt2) {
|
|
3188
|
+
return `\u751F\u6210\u56FE\u50CF\uFF1A${prompt2.displayValue.slice(0, 50)}${prompt2.displayValue.length > 50 ? "..." : ""}`;
|
|
2921
3189
|
}
|
|
2922
3190
|
if (style) {
|
|
2923
3191
|
return `\u751F\u6210 ${style.displayValue} \u98CE\u683C\u7684\u56FE\u50CF`;
|
|
@@ -2925,14 +3193,14 @@ function generateToolCallDescription(toolName, params) {
|
|
|
2925
3193
|
return "\u751F\u6210\u56FE\u50CF";
|
|
2926
3194
|
}
|
|
2927
3195
|
if (toolLower.includes("search") || toolLower.includes("query")) {
|
|
2928
|
-
if (
|
|
2929
|
-
return `\u641C\u7D22\uFF1A${
|
|
3196
|
+
if (prompt2) {
|
|
3197
|
+
return `\u641C\u7D22\uFF1A${prompt2.displayValue}`;
|
|
2930
3198
|
}
|
|
2931
3199
|
return "\u6267\u884C\u641C\u7D22";
|
|
2932
3200
|
}
|
|
2933
3201
|
if (toolLower.includes("translate")) {
|
|
2934
|
-
if (
|
|
2935
|
-
return `\u7FFB\u8BD1\uFF1A${
|
|
3202
|
+
if (prompt2) {
|
|
3203
|
+
return `\u7FFB\u8BD1\uFF1A${prompt2.displayValue.slice(0, 30)}...`;
|
|
2936
3204
|
}
|
|
2937
3205
|
return "\u6267\u884C\u7FFB\u8BD1";
|
|
2938
3206
|
}
|
|
@@ -2942,8 +3210,8 @@ function generateToolCallDescription(toolName, params) {
|
|
|
2942
3210
|
}
|
|
2943
3211
|
return "\u6267\u884C\u5206\u6790";
|
|
2944
3212
|
}
|
|
2945
|
-
if (
|
|
2946
|
-
return
|
|
3213
|
+
if (prompt2) {
|
|
3214
|
+
return prompt2.displayValue.slice(0, 60) + (prompt2.displayValue.length > 60 ? "..." : "");
|
|
2947
3215
|
}
|
|
2948
3216
|
const paramCount = formatted.length;
|
|
2949
3217
|
if (paramCount === 0) {
|
|
@@ -6938,7 +7206,6 @@ var createAssetFromSource = (options) => {
|
|
|
6938
7206
|
var resolveAssetForDisplay = async (asset, config) => {
|
|
6939
7207
|
let working = asset;
|
|
6940
7208
|
const strategy = config?.asset;
|
|
6941
|
-
console.log("Resolving asset for display:", asset, "with strategy:", strategy);
|
|
6942
7209
|
if (strategy?.resolve && !working.url) {
|
|
6943
7210
|
working = await strategy.resolve(working);
|
|
6944
7211
|
}
|
|
@@ -6953,6 +7220,9 @@ var resolveAssetForDisplay = async (asset, config) => {
|
|
|
6953
7220
|
if (resolved) return resolved;
|
|
6954
7221
|
}
|
|
6955
7222
|
if (working.url) {
|
|
7223
|
+
if (working.url.includes("industryai")) {
|
|
7224
|
+
working.url = working.url.split("?")[0];
|
|
7225
|
+
}
|
|
6956
7226
|
return {
|
|
6957
7227
|
url: working.url,
|
|
6958
7228
|
hdUrl: working.url,
|
|
@@ -6962,7 +7232,7 @@ var resolveAssetForDisplay = async (asset, config) => {
|
|
|
6962
7232
|
return null;
|
|
6963
7233
|
};
|
|
6964
7234
|
|
|
6965
|
-
//
|
|
7235
|
+
// node_modules/clsx/dist/clsx.mjs
|
|
6966
7236
|
function r(e) {
|
|
6967
7237
|
var t, f, n = "";
|
|
6968
7238
|
if ("string" == typeof e || "number" == typeof e) n += e;
|
|
@@ -10571,7 +10841,7 @@ var MessageImageInternal = React20.memo(function MessageImageInternal2({ src, al
|
|
|
10571
10841
|
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "\u56FE\u7247\u52A0\u8F7D\u5931\u8D25" })
|
|
10572
10842
|
] });
|
|
10573
10843
|
}
|
|
10574
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative
|
|
10844
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative inline-block max-w-full overflow-hidden rounded-lg my-2", children: [
|
|
10575
10845
|
previewUrl && /* @__PURE__ */ jsxRuntime.jsx(
|
|
10576
10846
|
ImagePreviewComp,
|
|
10577
10847
|
{
|
|
@@ -10579,7 +10849,7 @@ var MessageImageInternal = React20.memo(function MessageImageInternal2({ src, al
|
|
|
10579
10849
|
onClose: () => setPreviewUrl(null)
|
|
10580
10850
|
}
|
|
10581
10851
|
),
|
|
10582
|
-
!loaded && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
10852
|
+
!loaded && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-zinc-800 animate-pulse rounded-lg", style: { minHeight: "100px", minWidth: "150px" } }),
|
|
10583
10853
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10584
10854
|
"img",
|
|
10585
10855
|
{
|
|
@@ -10589,23 +10859,285 @@ var MessageImageInternal = React20.memo(function MessageImageInternal2({ src, al
|
|
|
10589
10859
|
onLoad: handleLoad,
|
|
10590
10860
|
onError: handleError,
|
|
10591
10861
|
onClick: () => setPreviewUrl(src),
|
|
10592
|
-
className: cn(
|
|
10593
|
-
|
|
10862
|
+
className: cn(
|
|
10863
|
+
"rounded-lg cursor-zoom-in max-w-full h-auto block",
|
|
10864
|
+
className,
|
|
10865
|
+
!loaded && "opacity-0 absolute"
|
|
10866
|
+
),
|
|
10867
|
+
style: { maxHeight: "400px", objectFit: "contain" }
|
|
10594
10868
|
}
|
|
10595
10869
|
)
|
|
10596
10870
|
] });
|
|
10597
10871
|
});
|
|
10598
10872
|
var MessageVideoInternal = React20.memo(function MessageVideoInternal2({ src, className }) {
|
|
10599
|
-
|
|
10600
|
-
|
|
10601
|
-
|
|
10602
|
-
|
|
10603
|
-
|
|
10604
|
-
|
|
10605
|
-
|
|
10606
|
-
|
|
10873
|
+
const videoRef = React20__namespace.default.useRef(null);
|
|
10874
|
+
const canvasRef = React20__namespace.default.useRef(null);
|
|
10875
|
+
const [posterUrl, setPosterUrl] = React20.useState(null);
|
|
10876
|
+
const [isHovering, setIsHovering] = React20.useState(false);
|
|
10877
|
+
const [isPlaying, setIsPlaying] = React20.useState(false);
|
|
10878
|
+
const [isMuted, setIsMuted] = React20.useState(true);
|
|
10879
|
+
const [duration, setDuration] = React20.useState(0);
|
|
10880
|
+
const [currentTime, setCurrentTime] = React20.useState(0);
|
|
10881
|
+
const [isFullPlaying, setIsFullPlaying] = React20.useState(false);
|
|
10882
|
+
const hoverTimerRef = React20__namespace.default.useRef(null);
|
|
10883
|
+
const VideoPreviewComp = useComponent("VideoPreview") || VideoPreviewInternal;
|
|
10884
|
+
const [showPreview, setShowPreview] = React20.useState(false);
|
|
10885
|
+
React20.useEffect(() => {
|
|
10886
|
+
const video = document.createElement("video");
|
|
10887
|
+
video.crossOrigin = "anonymous";
|
|
10888
|
+
video.preload = "metadata";
|
|
10889
|
+
video.muted = true;
|
|
10890
|
+
video.addEventListener("loadeddata", () => {
|
|
10891
|
+
video.currentTime = Math.min(0.5, video.duration * 0.1);
|
|
10892
|
+
});
|
|
10893
|
+
video.addEventListener("seeked", () => {
|
|
10894
|
+
try {
|
|
10895
|
+
const canvas = document.createElement("canvas");
|
|
10896
|
+
canvas.width = video.videoWidth;
|
|
10897
|
+
canvas.height = video.videoHeight;
|
|
10898
|
+
const ctx = canvas.getContext("2d");
|
|
10899
|
+
if (ctx) {
|
|
10900
|
+
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
|
|
10901
|
+
const dataUrl = canvas.toDataURL("image/jpeg", 0.8);
|
|
10902
|
+
setPosterUrl(dataUrl);
|
|
10903
|
+
}
|
|
10904
|
+
} catch {
|
|
10905
|
+
}
|
|
10906
|
+
video.remove();
|
|
10907
|
+
});
|
|
10908
|
+
video.addEventListener("error", () => {
|
|
10909
|
+
video.remove();
|
|
10910
|
+
});
|
|
10911
|
+
video.src = src;
|
|
10912
|
+
video.load();
|
|
10913
|
+
return () => {
|
|
10914
|
+
video.remove();
|
|
10915
|
+
};
|
|
10916
|
+
}, [src]);
|
|
10917
|
+
const handleLoadedMetadata = () => {
|
|
10918
|
+
const video = videoRef.current;
|
|
10919
|
+
if (video) {
|
|
10920
|
+
setDuration(video.duration);
|
|
10607
10921
|
}
|
|
10608
|
-
|
|
10922
|
+
};
|
|
10923
|
+
const handleTimeUpdate = () => {
|
|
10924
|
+
const video = videoRef.current;
|
|
10925
|
+
if (video) {
|
|
10926
|
+
setCurrentTime(video.currentTime);
|
|
10927
|
+
}
|
|
10928
|
+
};
|
|
10929
|
+
const handleMouseEnter = () => {
|
|
10930
|
+
setIsHovering(true);
|
|
10931
|
+
if (isFullPlaying) return;
|
|
10932
|
+
hoverTimerRef.current = setTimeout(() => {
|
|
10933
|
+
const video = videoRef.current;
|
|
10934
|
+
if (video) {
|
|
10935
|
+
video.muted = true;
|
|
10936
|
+
video.currentTime = 0;
|
|
10937
|
+
video.play().then(() => setIsPlaying(true)).catch(() => {
|
|
10938
|
+
});
|
|
10939
|
+
}
|
|
10940
|
+
}, 300);
|
|
10941
|
+
};
|
|
10942
|
+
const handleMouseLeave = () => {
|
|
10943
|
+
setIsHovering(false);
|
|
10944
|
+
if (hoverTimerRef.current) {
|
|
10945
|
+
clearTimeout(hoverTimerRef.current);
|
|
10946
|
+
hoverTimerRef.current = null;
|
|
10947
|
+
}
|
|
10948
|
+
if (!isFullPlaying) {
|
|
10949
|
+
const video = videoRef.current;
|
|
10950
|
+
if (video) {
|
|
10951
|
+
video.pause();
|
|
10952
|
+
video.currentTime = 0;
|
|
10953
|
+
setIsPlaying(false);
|
|
10954
|
+
}
|
|
10955
|
+
}
|
|
10956
|
+
};
|
|
10957
|
+
const handleClick = (e) => {
|
|
10958
|
+
e.stopPropagation();
|
|
10959
|
+
const video = videoRef.current;
|
|
10960
|
+
if (!video) return;
|
|
10961
|
+
if (isFullPlaying) {
|
|
10962
|
+
video.pause();
|
|
10963
|
+
setIsPlaying(false);
|
|
10964
|
+
setIsFullPlaying(false);
|
|
10965
|
+
} else {
|
|
10966
|
+
video.muted = isMuted;
|
|
10967
|
+
video.play().then(() => {
|
|
10968
|
+
setIsPlaying(true);
|
|
10969
|
+
setIsFullPlaying(true);
|
|
10970
|
+
}).catch(() => {
|
|
10971
|
+
});
|
|
10972
|
+
}
|
|
10973
|
+
};
|
|
10974
|
+
const handleToggleMute = (e) => {
|
|
10975
|
+
e.stopPropagation();
|
|
10976
|
+
const video = videoRef.current;
|
|
10977
|
+
if (video) {
|
|
10978
|
+
video.muted = !isMuted;
|
|
10979
|
+
setIsMuted(!isMuted);
|
|
10980
|
+
}
|
|
10981
|
+
};
|
|
10982
|
+
const handleProgressClick = (e) => {
|
|
10983
|
+
e.stopPropagation();
|
|
10984
|
+
const video = videoRef.current;
|
|
10985
|
+
if (!video || !duration) return;
|
|
10986
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
10987
|
+
const ratio = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width));
|
|
10988
|
+
video.currentTime = ratio * duration;
|
|
10989
|
+
setCurrentTime(ratio * duration);
|
|
10990
|
+
};
|
|
10991
|
+
const formatTime2 = (seconds) => {
|
|
10992
|
+
const mins = Math.floor(seconds / 60);
|
|
10993
|
+
const secs = Math.floor(seconds % 60);
|
|
10994
|
+
return `${mins}:${secs.toString().padStart(2, "0")}`;
|
|
10995
|
+
};
|
|
10996
|
+
const progressPercent = duration > 0 ? currentTime / duration * 100 : 0;
|
|
10997
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
10998
|
+
showPreview && /* @__PURE__ */ jsxRuntime.jsx(VideoPreviewComp, { src, onClose: () => setShowPreview(false) }),
|
|
10999
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
11000
|
+
"div",
|
|
11001
|
+
{
|
|
11002
|
+
className: cn(
|
|
11003
|
+
"my-2 relative inline-block rounded-xl overflow-hidden bg-black group/video cursor-pointer",
|
|
11004
|
+
"border border-zinc-800/60 agent-sdk-light:border-zinc-200",
|
|
11005
|
+
"transition-shadow duration-200 hover:shadow-xl hover:shadow-black/20",
|
|
11006
|
+
"max-w-full",
|
|
11007
|
+
className
|
|
11008
|
+
),
|
|
11009
|
+
style: { maxHeight: "400px" },
|
|
11010
|
+
onMouseEnter: handleMouseEnter,
|
|
11011
|
+
onMouseLeave: handleMouseLeave,
|
|
11012
|
+
onClick: handleClick,
|
|
11013
|
+
children: [
|
|
11014
|
+
posterUrl && !isPlaying && /* @__PURE__ */ jsxRuntime.jsx(
|
|
11015
|
+
"img",
|
|
11016
|
+
{
|
|
11017
|
+
src: posterUrl,
|
|
11018
|
+
alt: "Video cover",
|
|
11019
|
+
className: "absolute inset-0 w-full h-full object-contain z-[1]"
|
|
11020
|
+
}
|
|
11021
|
+
),
|
|
11022
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11023
|
+
"video",
|
|
11024
|
+
{
|
|
11025
|
+
ref: videoRef,
|
|
11026
|
+
src,
|
|
11027
|
+
muted: isMuted,
|
|
11028
|
+
playsInline: true,
|
|
11029
|
+
preload: "metadata",
|
|
11030
|
+
onLoadedMetadata: handleLoadedMetadata,
|
|
11031
|
+
onTimeUpdate: handleTimeUpdate,
|
|
11032
|
+
onEnded: () => {
|
|
11033
|
+
setIsPlaying(false);
|
|
11034
|
+
setIsFullPlaying(false);
|
|
11035
|
+
},
|
|
11036
|
+
className: cn(
|
|
11037
|
+
"w-full max-h-[400px] object-contain",
|
|
11038
|
+
!isPlaying && posterUrl && "opacity-0"
|
|
11039
|
+
)
|
|
11040
|
+
}
|
|
11041
|
+
),
|
|
11042
|
+
/* @__PURE__ */ jsxRuntime.jsx("canvas", { ref: canvasRef, className: "hidden" }),
|
|
11043
|
+
!isFullPlaying && /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(
|
|
11044
|
+
"absolute inset-0 z-[2] flex items-center justify-center",
|
|
11045
|
+
"bg-gradient-to-t from-black/50 via-transparent to-transparent",
|
|
11046
|
+
"transition-opacity duration-200",
|
|
11047
|
+
isHovering && isPlaying ? "opacity-0" : "opacity-100"
|
|
11048
|
+
), children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(
|
|
11049
|
+
"w-14 h-14 rounded-full bg-white/20 backdrop-blur-md",
|
|
11050
|
+
"flex items-center justify-center",
|
|
11051
|
+
"transition-all duration-200",
|
|
11052
|
+
"group-hover/video:scale-110 group-hover/video:bg-white/30",
|
|
11053
|
+
"shadow-lg shadow-black/20"
|
|
11054
|
+
), children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "white", className: "ml-1", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 5v14l11-7z" }) }) }) }),
|
|
11055
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(
|
|
11056
|
+
"absolute bottom-0 left-0 right-0 z-[3]",
|
|
11057
|
+
"bg-gradient-to-t from-black/80 via-black/40 to-transparent",
|
|
11058
|
+
"px-3 pb-2.5 pt-8",
|
|
11059
|
+
"transition-opacity duration-200",
|
|
11060
|
+
isHovering || isFullPlaying ? "opacity-100" : "opacity-0"
|
|
11061
|
+
), children: [
|
|
11062
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11063
|
+
"div",
|
|
11064
|
+
{
|
|
11065
|
+
className: "w-full h-1 bg-white/20 rounded-full mb-2 cursor-pointer group/progress",
|
|
11066
|
+
onClick: handleProgressClick,
|
|
11067
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
11068
|
+
"div",
|
|
11069
|
+
{
|
|
11070
|
+
className: "h-full bg-[#d8ff00] rounded-full relative transition-all duration-75",
|
|
11071
|
+
style: { width: `${progressPercent}%` },
|
|
11072
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute right-0 top-1/2 -translate-y-1/2 w-3 h-3 bg-[#d8ff00] rounded-full opacity-0 group-hover/progress:opacity-100 transition-opacity shadow-md" })
|
|
11073
|
+
}
|
|
11074
|
+
)
|
|
11075
|
+
}
|
|
11076
|
+
),
|
|
11077
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
11078
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
11079
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11080
|
+
"button",
|
|
11081
|
+
{
|
|
11082
|
+
onClick: handleClick,
|
|
11083
|
+
className: "p-1 text-white/80 hover:text-white transition-colors",
|
|
11084
|
+
children: isPlaying ? /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "currentColor", children: [
|
|
11085
|
+
/* @__PURE__ */ jsxRuntime.jsx("rect", { x: "6", y: "4", width: "4", height: "16", rx: "1" }),
|
|
11086
|
+
/* @__PURE__ */ jsxRuntime.jsx("rect", { x: "14", y: "4", width: "4", height: "16", rx: "1" })
|
|
11087
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 5v14l11-7z" }) })
|
|
11088
|
+
}
|
|
11089
|
+
),
|
|
11090
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11091
|
+
"button",
|
|
11092
|
+
{
|
|
11093
|
+
onClick: handleToggleMute,
|
|
11094
|
+
className: "p-1 text-white/80 hover:text-white transition-colors",
|
|
11095
|
+
children: isMuted ? /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
11096
|
+
/* @__PURE__ */ jsxRuntime.jsx("polygon", { points: "11 5 6 9 2 9 2 15 6 15 11 19 11 5" }),
|
|
11097
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "23", y1: "9", x2: "17", y2: "15" }),
|
|
11098
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "17", y1: "9", x2: "23", y2: "15" })
|
|
11099
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
11100
|
+
/* @__PURE__ */ jsxRuntime.jsx("polygon", { points: "11 5 6 9 2 9 2 15 6 15 11 19 11 5" }),
|
|
11101
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M19.07 4.93a10 10 0 0 1 0 14.14" }),
|
|
11102
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15.54 8.46a5 5 0 0 1 0 7.07" })
|
|
11103
|
+
] })
|
|
11104
|
+
}
|
|
11105
|
+
),
|
|
11106
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[11px] text-white/60 font-mono tabular-nums", children: [
|
|
11107
|
+
formatTime2(currentTime),
|
|
11108
|
+
" / ",
|
|
11109
|
+
formatTime2(duration)
|
|
11110
|
+
] })
|
|
11111
|
+
] }),
|
|
11112
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11113
|
+
"button",
|
|
11114
|
+
{
|
|
11115
|
+
onClick: (e) => {
|
|
11116
|
+
e.stopPropagation();
|
|
11117
|
+
const video = videoRef.current;
|
|
11118
|
+
if (video) {
|
|
11119
|
+
video.pause();
|
|
11120
|
+
setIsPlaying(false);
|
|
11121
|
+
setIsFullPlaying(false);
|
|
11122
|
+
}
|
|
11123
|
+
setShowPreview(true);
|
|
11124
|
+
},
|
|
11125
|
+
className: "p-1 text-white/60 hover:text-white transition-colors",
|
|
11126
|
+
title: "\u5168\u5C4F\u9884\u89C8",
|
|
11127
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
11128
|
+
/* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "15 3 21 3 21 9" }),
|
|
11129
|
+
/* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "9 21 3 21 3 15" }),
|
|
11130
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "21", y1: "3", x2: "14", y2: "10" }),
|
|
11131
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "3", y1: "21", x2: "10", y2: "14" })
|
|
11132
|
+
] })
|
|
11133
|
+
}
|
|
11134
|
+
)
|
|
11135
|
+
] })
|
|
11136
|
+
] })
|
|
11137
|
+
]
|
|
11138
|
+
}
|
|
11139
|
+
)
|
|
11140
|
+
] });
|
|
10609
11141
|
});
|
|
10610
11142
|
var ImagePreviewInternal = React20.memo(function ImagePreviewInternal2({
|
|
10611
11143
|
src,
|
|
@@ -12251,6 +12783,7 @@ var ToolResultRenderer = React20.memo(function ToolResultRenderer2({
|
|
|
12251
12783
|
result,
|
|
12252
12784
|
mediaUrls,
|
|
12253
12785
|
config,
|
|
12786
|
+
toolCallData,
|
|
12254
12787
|
onOpenArtifact
|
|
12255
12788
|
}) {
|
|
12256
12789
|
const [imgLoaded, setImgLoaded] = React20.useState({});
|
|
@@ -12317,32 +12850,134 @@ var ToolResultRenderer = React20.memo(function ToolResultRenderer2({
|
|
|
12317
12850
|
}
|
|
12318
12851
|
),
|
|
12319
12852
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
12320
|
-
hasMedia && /* @__PURE__ */ jsxRuntime.
|
|
12321
|
-
|
|
12322
|
-
|
|
12323
|
-
|
|
12324
|
-
|
|
12325
|
-
|
|
12326
|
-
|
|
12327
|
-
|
|
12328
|
-
|
|
12853
|
+
hasMedia && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2", children: (() => {
|
|
12854
|
+
const totalMedia = imageUrls.length + videoUrls.length;
|
|
12855
|
+
const isMultiple = totalMedia > 1;
|
|
12856
|
+
const buildMediaMetadata = (mediaIndex) => {
|
|
12857
|
+
if (!toolCallData) return void 0;
|
|
12858
|
+
const resultAny = toolCallData.result;
|
|
12859
|
+
const metadata = {};
|
|
12860
|
+
if (toolCallData.name) metadata.toolName = toolCallData.name;
|
|
12861
|
+
if (resultAny?.relation?.toolName) metadata.toolName = resultAny.relation.toolName;
|
|
12862
|
+
if (toolCallData.arguments) metadata.generationParams = toolCallData.arguments;
|
|
12863
|
+
if (resultAny?.relation) metadata.relation = resultAny.relation;
|
|
12864
|
+
if (resultAny?.taskId) metadata.taskId = resultAny.taskId;
|
|
12865
|
+
const work = resultAny?.works?.[mediaIndex];
|
|
12866
|
+
if (work) {
|
|
12867
|
+
if (work.publicId) metadata.workId = work.publicId;
|
|
12868
|
+
if (work.fileId) metadata.fileId = work.fileId;
|
|
12329
12869
|
}
|
|
12330
|
-
|
|
12331
|
-
|
|
12332
|
-
|
|
12333
|
-
/* @__PURE__ */ jsxRuntime.
|
|
12334
|
-
"
|
|
12870
|
+
return metadata;
|
|
12871
|
+
};
|
|
12872
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: isMultiple ? "grid grid-cols-2 gap-2" : "flex", children: [
|
|
12873
|
+
videoUrls.map((video, i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
12874
|
+
"div",
|
|
12335
12875
|
{
|
|
12336
|
-
|
|
12337
|
-
|
|
12338
|
-
|
|
12339
|
-
|
|
12340
|
-
|
|
12341
|
-
|
|
12342
|
-
|
|
12343
|
-
|
|
12344
|
-
|
|
12345
|
-
|
|
12876
|
+
className: `relative group/media overflow-hidden rounded-lg bg-black ${isMultiple ? "aspect-square" : "max-h-[375px]"}`,
|
|
12877
|
+
children: [
|
|
12878
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12879
|
+
MessageVideoInternal,
|
|
12880
|
+
{
|
|
12881
|
+
src: video.hdUrl || video.url,
|
|
12882
|
+
className: isMultiple ? "w-full h-full object-cover" : "max-h-[375px] max-w-full object-contain"
|
|
12883
|
+
}
|
|
12884
|
+
),
|
|
12885
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute bottom-0 left-0 right-0 p-2 bg-gradient-to-t from-black/70 to-transparent opacity-0 group-hover/media:opacity-100 transition-opacity duration-200 flex items-center justify-between z-[10]", children: [
|
|
12886
|
+
onOpenArtifact && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
12887
|
+
"button",
|
|
12888
|
+
{
|
|
12889
|
+
onClick: (e) => {
|
|
12890
|
+
e.stopPropagation();
|
|
12891
|
+
const resultAny = toolCallData?.result;
|
|
12892
|
+
const displayName = resultAny?.relation?.toolName || toolCallData?.name || "\u89C6\u9891\u751F\u6210";
|
|
12893
|
+
onOpenArtifact({
|
|
12894
|
+
type: "video",
|
|
12895
|
+
title: `${displayName} #${i + 1}`,
|
|
12896
|
+
content: video.hdUrl || video.url,
|
|
12897
|
+
metadata: buildMediaMetadata(imageUrls.length + i)
|
|
12898
|
+
});
|
|
12899
|
+
},
|
|
12900
|
+
className: "flex items-center gap-1.5 px-2.5 py-1.5 text-[11px] font-medium text-white bg-white/15 hover:bg-white/25 backdrop-blur-sm rounded-md transition-colors",
|
|
12901
|
+
children: [
|
|
12902
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { size: 12 }),
|
|
12903
|
+
"\u67E5\u770B\u8BE6\u60C5"
|
|
12904
|
+
]
|
|
12905
|
+
}
|
|
12906
|
+
),
|
|
12907
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12908
|
+
"button",
|
|
12909
|
+
{
|
|
12910
|
+
onClick: (e) => {
|
|
12911
|
+
e.stopPropagation();
|
|
12912
|
+
window.open(video.hdUrl || video.url, "_blank");
|
|
12913
|
+
},
|
|
12914
|
+
className: "p-1.5 text-white/80 hover:text-white bg-white/15 hover:bg-white/25 backdrop-blur-sm rounded-md transition-colors",
|
|
12915
|
+
title: "\u65B0\u7A97\u53E3\u6253\u5F00",
|
|
12916
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Video, { size: 14 })
|
|
12917
|
+
}
|
|
12918
|
+
)
|
|
12919
|
+
] })
|
|
12920
|
+
]
|
|
12921
|
+
},
|
|
12922
|
+
`video-${i}`
|
|
12923
|
+
)),
|
|
12924
|
+
imageUrls.map((img, i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
12925
|
+
"div",
|
|
12926
|
+
{
|
|
12927
|
+
className: `relative group/media overflow-hidden rounded-lg bg-black ${isMultiple ? "aspect-square" : "max-h-[375px]"}`,
|
|
12928
|
+
children: [
|
|
12929
|
+
!imgLoaded[i] && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-zinc-800 animate-pulse flex items-center justify-center w-full aspect-square", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "animate-spin rounded-full h-5 w-5 border-b-2 border-[#d8ff00]" }) }),
|
|
12930
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12931
|
+
"img",
|
|
12932
|
+
{
|
|
12933
|
+
src: img.url,
|
|
12934
|
+
alt: "Generated",
|
|
12935
|
+
onLoad: () => handleImgLoad(i),
|
|
12936
|
+
className: `cursor-zoom-in ${imgLoaded[i] ? "" : "hidden"} ${isMultiple ? "w-full h-full object-cover" : "max-h-[375px] max-w-full h-auto object-contain"}`,
|
|
12937
|
+
onClick: () => setPreviewUrl(img.hdUrl)
|
|
12938
|
+
}
|
|
12939
|
+
),
|
|
12940
|
+
imgLoaded[i] && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute bottom-0 left-0 right-0 p-2 bg-gradient-to-t from-black/70 to-transparent opacity-0 group-hover/media:opacity-100 transition-opacity duration-200 flex items-center justify-between", children: [
|
|
12941
|
+
onOpenArtifact && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
12942
|
+
"button",
|
|
12943
|
+
{
|
|
12944
|
+
onClick: (e) => {
|
|
12945
|
+
e.stopPropagation();
|
|
12946
|
+
const resultAny = toolCallData?.result;
|
|
12947
|
+
const displayName = resultAny?.relation?.toolName || toolCallData?.name || "\u56FE\u7247\u751F\u6210";
|
|
12948
|
+
onOpenArtifact({
|
|
12949
|
+
type: "image",
|
|
12950
|
+
title: `${displayName} #${i + 1}`,
|
|
12951
|
+
content: img.hdUrl || img.url,
|
|
12952
|
+
metadata: buildMediaMetadata(i)
|
|
12953
|
+
});
|
|
12954
|
+
},
|
|
12955
|
+
className: "flex items-center gap-1.5 px-2.5 py-1.5 text-[11px] font-medium text-white bg-white/15 hover:bg-white/25 backdrop-blur-sm rounded-md transition-colors",
|
|
12956
|
+
children: [
|
|
12957
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { size: 12 }),
|
|
12958
|
+
"\u67E5\u770B\u8BE6\u60C5"
|
|
12959
|
+
]
|
|
12960
|
+
}
|
|
12961
|
+
),
|
|
12962
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12963
|
+
"button",
|
|
12964
|
+
{
|
|
12965
|
+
onClick: (e) => {
|
|
12966
|
+
e.stopPropagation();
|
|
12967
|
+
setPreviewUrl(img.hdUrl);
|
|
12968
|
+
},
|
|
12969
|
+
className: "p-1.5 text-white/80 hover:text-white bg-white/15 hover:bg-white/25 backdrop-blur-sm rounded-md transition-colors",
|
|
12970
|
+
title: "\u653E\u5927\u9884\u89C8",
|
|
12971
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Image, { size: 14 })
|
|
12972
|
+
}
|
|
12973
|
+
)
|
|
12974
|
+
] })
|
|
12975
|
+
]
|
|
12976
|
+
},
|
|
12977
|
+
`img-${i}`
|
|
12978
|
+
))
|
|
12979
|
+
] });
|
|
12980
|
+
})() }),
|
|
12346
12981
|
hasCustomResponses && customResult
|
|
12347
12982
|
] })
|
|
12348
12983
|
] });
|
|
@@ -12468,6 +13103,7 @@ var ToolCallCard3 = React20.memo(function ToolCallCard4({
|
|
|
12468
13103
|
result: toolCall.result,
|
|
12469
13104
|
mediaUrls,
|
|
12470
13105
|
config,
|
|
13106
|
+
toolCallData: toolCall,
|
|
12471
13107
|
defaultExpanded: false,
|
|
12472
13108
|
onOpenArtifact
|
|
12473
13109
|
}
|
|
@@ -12738,7 +13374,7 @@ var ComponentPendingCard = React20.memo(function ComponentPendingCard2({
|
|
|
12738
13374
|
})() })
|
|
12739
13375
|
] });
|
|
12740
13376
|
});
|
|
12741
|
-
var ThoughtTimelineCard = React20.memo(function ThoughtTimelineCard2({ thought, config, isLoading = false }) {
|
|
13377
|
+
var ThoughtTimelineCard = React20.memo(function ThoughtTimelineCard2({ thought, config, isLoading = false, skipImages = false }) {
|
|
12742
13378
|
const [expanded, setExpanded] = React20.useState(true);
|
|
12743
13379
|
const { showItemTime } = useAgentStore();
|
|
12744
13380
|
const thoughtType = thought?.type || "";
|
|
@@ -12762,9 +13398,9 @@ var ThoughtTimelineCard = React20.memo(function ThoughtTimelineCard2({ thought,
|
|
|
12762
13398
|
return null;
|
|
12763
13399
|
}
|
|
12764
13400
|
if (thought?.raw && Array.isArray(thought.raw)) {
|
|
12765
|
-
const hasConfirmationEvent = thought.raw.some((
|
|
12766
|
-
const type =
|
|
12767
|
-
return excludedTypes.includes(type) ||
|
|
13401
|
+
const hasConfirmationEvent = thought.raw.some((r3) => {
|
|
13402
|
+
const type = r3?.type || "";
|
|
13403
|
+
return excludedTypes.includes(type) || r3?.content && (r3.content.includes('"type":"tool_confirmed"') || r3.content.includes('"type":"component_submitted"') || r3.content.includes("\u7528\u6237\u786E\u8BA4\u6267\u884C\u5DE5\u5177\u8C03\u7528"));
|
|
12768
13404
|
});
|
|
12769
13405
|
if (hasConfirmationEvent) {
|
|
12770
13406
|
return null;
|
|
@@ -12776,12 +13412,19 @@ var ThoughtTimelineCard = React20.memo(function ThoughtTimelineCard2({ thought,
|
|
|
12776
13412
|
if (!cleaned || !cleaned.trim()) return null;
|
|
12777
13413
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-3 py-2", children: [
|
|
12778
13414
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm leading-relaxed prose prose-invert prose-sm max-w-none [&_*]:break-words", children: [
|
|
12779
|
-
/* @__PURE__ */ jsxRuntime.jsx(MarkdownContent, { content: cleaned, skipImages
|
|
13415
|
+
/* @__PURE__ */ jsxRuntime.jsx(MarkdownContent, { content: cleaned, skipImages, config, variant: "thought" }),
|
|
12780
13416
|
isLoading && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-block w-2 h-4 ml-0.5 bg-[#d8ff00] animate-pulse rounded-sm" })
|
|
12781
13417
|
] }) }),
|
|
12782
13418
|
thought?.raw?.length > 0 && showItemTime && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-zinc-500 mt-2", children: new Date(
|
|
12783
13419
|
thought.raw[thought.raw.length - 1]?.gmt_create || thought.raw[thought.raw.length - 1]?.gmtCreate || thought.raw[thought.raw.length - 1]?.timestamp || ""
|
|
12784
|
-
).toLocaleTimeString("zh-CN", {
|
|
13420
|
+
).toLocaleTimeString("zh-CN", {
|
|
13421
|
+
year: "numeric",
|
|
13422
|
+
month: "2-digit",
|
|
13423
|
+
day: "2-digit",
|
|
13424
|
+
hour: "2-digit",
|
|
13425
|
+
minute: "2-digit",
|
|
13426
|
+
second: "2-digit"
|
|
13427
|
+
}) })
|
|
12785
13428
|
] }) });
|
|
12786
13429
|
});
|
|
12787
13430
|
var COMPONENT_TAGS_TO_STRIP = [
|
|
@@ -13781,7 +14424,8 @@ ${m.content}`;
|
|
|
13781
14424
|
}
|
|
13782
14425
|
var ThoughtBlockItem = React20.memo(function ThoughtBlockItem2({
|
|
13783
14426
|
content,
|
|
13784
|
-
config
|
|
14427
|
+
config,
|
|
14428
|
+
skipImages = false
|
|
13785
14429
|
}) {
|
|
13786
14430
|
const [expanded, setExpanded] = React20.useState(false);
|
|
13787
14431
|
const lineCount = React20.useMemo(() => content.split("\n").length, [content]);
|
|
@@ -13794,7 +14438,7 @@ var ThoughtBlockItem = React20.memo(function ThoughtBlockItem2({
|
|
|
13794
14438
|
"text-sm text-zinc-400 leading-relaxed prose prose-invert prose-sm max-w-none [&_*]:break-words",
|
|
13795
14439
|
shouldToggle && !expanded ? "max-h-[3.5em] overflow-hidden" : ""
|
|
13796
14440
|
),
|
|
13797
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(MarkdownContent, { content, skipImages
|
|
14441
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(MarkdownContent, { content, skipImages, config, variant: "thought" })
|
|
13798
14442
|
}
|
|
13799
14443
|
),
|
|
13800
14444
|
shouldToggle && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -13980,7 +14624,6 @@ var MessageBubble = React20.memo(function MessageBubble2({
|
|
|
13980
14624
|
const shouldShowAvatar = isUser ? showUserAvatar : showAssistantAvatar;
|
|
13981
14625
|
const shouldShowName = isUser ? showUserName : showAssistantName;
|
|
13982
14626
|
const shouldShowDescription = isUser ? showUserDescription : showAssistantDescription;
|
|
13983
|
-
console.log("[MessageBubble] \u6E32\u67D3\u6D88\u606F\u6C14\u6CE1, config?.identity:", config?.identity);
|
|
13984
14627
|
const resolveFileName = (url) => {
|
|
13985
14628
|
try {
|
|
13986
14629
|
const pathname = new URL(url, "http://dummy").pathname;
|
|
@@ -14041,7 +14684,8 @@ var MessageBubble = React20.memo(function MessageBubble2({
|
|
|
14041
14684
|
{
|
|
14042
14685
|
thought: item.data,
|
|
14043
14686
|
config,
|
|
14044
|
-
isLoading: showLoadingCursor
|
|
14687
|
+
isLoading: showLoadingCursor,
|
|
14688
|
+
skipImages: hasToolCallImages
|
|
14045
14689
|
},
|
|
14046
14690
|
item.id
|
|
14047
14691
|
);
|
|
@@ -14141,7 +14785,8 @@ var MessageBubble = React20.memo(function MessageBubble2({
|
|
|
14141
14785
|
ThoughtBlockItem,
|
|
14142
14786
|
{
|
|
14143
14787
|
content: block.content,
|
|
14144
|
-
config
|
|
14788
|
+
config,
|
|
14789
|
+
skipImages: hasToolCallImages
|
|
14145
14790
|
},
|
|
14146
14791
|
`${block.ts}-${index}`
|
|
14147
14792
|
)),
|
|
@@ -14186,15 +14831,23 @@ var MessageBubble = React20.memo(function MessageBubble2({
|
|
|
14186
14831
|
const isVideo = att.type === "video" || att.type?.startsWith("video/") || isVideoUrl2(att.url);
|
|
14187
14832
|
const isImage2 = att.type === "image" || att.type?.startsWith("image/") || !isVideo && /\.(jpg|jpeg|png|gif|webp|bmp|svg)(\?|#|$)/i.test(att.url);
|
|
14188
14833
|
const fileName = att.name || resolveFileName(att.url);
|
|
14834
|
+
if (att.url.includes("industryai")) {
|
|
14835
|
+
att.url = att.url.split("?")[0];
|
|
14836
|
+
}
|
|
14837
|
+
const assets = config?.asset?.transform?.({
|
|
14838
|
+
type: att.type,
|
|
14839
|
+
url: att.url,
|
|
14840
|
+
name: fileName
|
|
14841
|
+
}) || { url: att.url, type: att.type };
|
|
14189
14842
|
if (isImage2 || isVideo) {
|
|
14190
14843
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14191
14844
|
"button",
|
|
14192
14845
|
{
|
|
14193
14846
|
type: "button",
|
|
14194
|
-
onClick: () => setPreviewMedia({ url:
|
|
14847
|
+
onClick: () => setPreviewMedia({ url: assets.url, isVideo }),
|
|
14195
14848
|
className: "group/att relative w-[88px] h-[88px] rounded-lg overflow-hidden border border-zinc-700/40 bg-zinc-900/60 hover:border-zinc-500/60 transition-colors",
|
|
14196
14849
|
children: [
|
|
14197
|
-
isVideo ? /* @__PURE__ */ jsxRuntime.jsx(MessageVideoComp, { src:
|
|
14850
|
+
isVideo ? /* @__PURE__ */ jsxRuntime.jsx(MessageVideoComp, { src: assets.url, className: "w-full h-full object-cover" }) : /* @__PURE__ */ jsxRuntime.jsx(MessageImageComp, { src: att.url, alt: fileName, className: "w-full h-full object-cover" }),
|
|
14198
14851
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 bg-black/20 opacity-0 group-hover/att:opacity-100 transition-opacity" })
|
|
14199
14852
|
]
|
|
14200
14853
|
},
|
|
@@ -14299,7 +14952,14 @@ var MessageBubble = React20.memo(function MessageBubble2({
|
|
|
14299
14952
|
]
|
|
14300
14953
|
}
|
|
14301
14954
|
) }),
|
|
14302
|
-
message.gmtCreate && !isStreaming && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-zinc-600 text-[10px] mt-1", children: new Date(message.gmtCreate).toLocaleTimeString("zh-CN", {
|
|
14955
|
+
message.gmtCreate && !isStreaming && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-zinc-600 text-[10px] mt-1 opacity-0 group-hover:opacity-100 transition-opacity", children: new Date(message.gmtCreate).toLocaleTimeString("zh-CN", {
|
|
14956
|
+
year: "numeric",
|
|
14957
|
+
month: "2-digit",
|
|
14958
|
+
day: "2-digit",
|
|
14959
|
+
hour: "2-digit",
|
|
14960
|
+
minute: "2-digit",
|
|
14961
|
+
second: "2-digit"
|
|
14962
|
+
}) })
|
|
14303
14963
|
] })
|
|
14304
14964
|
] });
|
|
14305
14965
|
});
|
|
@@ -15174,9 +15834,24 @@ var DialogDescription = React20__namespace.forwardRef(({ className, ...props },
|
|
|
15174
15834
|
));
|
|
15175
15835
|
DialogDescription.displayName = DialogPrimitive__namespace.Description.displayName;
|
|
15176
15836
|
|
|
15837
|
+
// ../../node_modules/clsx/dist/clsx.mjs
|
|
15838
|
+
function r2(e) {
|
|
15839
|
+
var t, f, n = "";
|
|
15840
|
+
if ("string" == typeof e || "number" == typeof e) n += e;
|
|
15841
|
+
else if ("object" == typeof e) if (Array.isArray(e)) {
|
|
15842
|
+
var o = e.length;
|
|
15843
|
+
for (t = 0; t < o; t++) e[t] && (f = r2(e[t])) && (n && (n += " "), n += f);
|
|
15844
|
+
} else for (f in e) e[f] && (n && (n += " "), n += f);
|
|
15845
|
+
return n;
|
|
15846
|
+
}
|
|
15847
|
+
function clsx2() {
|
|
15848
|
+
for (var e, t, f = 0, n = "", o = arguments.length; f < o; f++) (e = arguments[f]) && (t = r2(e)) && (n && (n += " "), n += t);
|
|
15849
|
+
return n;
|
|
15850
|
+
}
|
|
15851
|
+
|
|
15177
15852
|
// ../../node_modules/class-variance-authority/dist/index.mjs
|
|
15178
15853
|
var falsyToString = (value) => typeof value === "boolean" ? `${value}` : value === 0 ? "0" : value;
|
|
15179
|
-
var cx =
|
|
15854
|
+
var cx = clsx2;
|
|
15180
15855
|
var cva = (base, config) => (props) => {
|
|
15181
15856
|
var _config_compoundVariants;
|
|
15182
15857
|
if ((config === null || config === void 0 ? void 0 : config.variants) == null) return cx(base, props === null || props === void 0 ? void 0 : props.class, props === null || props === void 0 ? void 0 : props.className);
|
|
@@ -15994,10 +16669,10 @@ var Observer = class {
|
|
|
15994
16669
|
});
|
|
15995
16670
|
}
|
|
15996
16671
|
};
|
|
15997
|
-
this.custom = (
|
|
16672
|
+
this.custom = (jsx59, data) => {
|
|
15998
16673
|
const id = (data == null ? void 0 : data.id) || toastsCounter++;
|
|
15999
16674
|
this.create({
|
|
16000
|
-
jsx:
|
|
16675
|
+
jsx: jsx59(id),
|
|
16001
16676
|
id,
|
|
16002
16677
|
...data
|
|
16003
16678
|
});
|
|
@@ -18498,7 +19173,57 @@ var ToolbarButton = React20.memo(function ToolbarButton2({
|
|
|
18498
19173
|
}
|
|
18499
19174
|
);
|
|
18500
19175
|
});
|
|
18501
|
-
var
|
|
19176
|
+
var artifactTypeConfig = {
|
|
19177
|
+
html: {
|
|
19178
|
+
icon: lucideReact.Globe,
|
|
19179
|
+
label: "HTML",
|
|
19180
|
+
color: "text-orange-400",
|
|
19181
|
+
bgColor: "bg-orange-500/10"
|
|
19182
|
+
},
|
|
19183
|
+
svg: {
|
|
19184
|
+
icon: lucideReact.Globe,
|
|
19185
|
+
label: "SVG",
|
|
19186
|
+
color: "text-orange-300",
|
|
19187
|
+
bgColor: "bg-orange-500/10"
|
|
19188
|
+
},
|
|
19189
|
+
markdown: {
|
|
19190
|
+
icon: lucideReact.FileText,
|
|
19191
|
+
label: "Markdown",
|
|
19192
|
+
color: "text-blue-400",
|
|
19193
|
+
bgColor: "bg-blue-500/10"
|
|
19194
|
+
},
|
|
19195
|
+
json: {
|
|
19196
|
+
icon: lucideReact.FileJson,
|
|
19197
|
+
label: "JSON",
|
|
19198
|
+
color: "text-yellow-400",
|
|
19199
|
+
bgColor: "bg-yellow-500/10"
|
|
19200
|
+
},
|
|
19201
|
+
code: {
|
|
19202
|
+
icon: lucideReact.FileCode,
|
|
19203
|
+
label: "Code",
|
|
19204
|
+
color: "text-purple-400",
|
|
19205
|
+
bgColor: "bg-purple-500/10"
|
|
19206
|
+
},
|
|
19207
|
+
text: {
|
|
19208
|
+
icon: lucideReact.FileText,
|
|
19209
|
+
label: "Text",
|
|
19210
|
+
color: "text-zinc-400",
|
|
19211
|
+
bgColor: "bg-zinc-500/10"
|
|
19212
|
+
},
|
|
19213
|
+
image: {
|
|
19214
|
+
icon: lucideReact.FileImage,
|
|
19215
|
+
label: "Image",
|
|
19216
|
+
color: "text-green-400",
|
|
19217
|
+
bgColor: "bg-green-500/10"
|
|
19218
|
+
},
|
|
19219
|
+
video: {
|
|
19220
|
+
icon: lucideReact.Video,
|
|
19221
|
+
label: "Video",
|
|
19222
|
+
color: "text-pink-400",
|
|
19223
|
+
bgColor: "bg-pink-500/10"
|
|
19224
|
+
}
|
|
19225
|
+
};
|
|
19226
|
+
var CodeBlock3 = React20.memo(function CodeBlock4({
|
|
18502
19227
|
code: code3,
|
|
18503
19228
|
language,
|
|
18504
19229
|
showLineNumbers = true
|
|
@@ -18786,38 +19511,1305 @@ React20.memo(function JsonPreview2({ content }) {
|
|
|
18786
19511
|
}
|
|
18787
19512
|
return /* @__PURE__ */ jsxRuntime.jsx(CodeBlock3, { code: formattedJson, language: "json" });
|
|
18788
19513
|
});
|
|
18789
|
-
var
|
|
18790
|
-
|
|
18791
|
-
|
|
18792
|
-
|
|
18793
|
-
|
|
18794
|
-
|
|
18795
|
-
|
|
18796
|
-
|
|
18797
|
-
|
|
18798
|
-
|
|
18799
|
-
|
|
18800
|
-
|
|
18801
|
-
|
|
18802
|
-
|
|
18803
|
-
|
|
18804
|
-
|
|
18805
|
-
|
|
18806
|
-
|
|
18807
|
-
},
|
|
18808
|
-
|
|
18809
|
-
|
|
18810
|
-
|
|
18811
|
-
|
|
18812
|
-
|
|
18813
|
-
|
|
18814
|
-
|
|
18815
|
-
|
|
18816
|
-
|
|
18817
|
-
|
|
18818
|
-
|
|
18819
|
-
|
|
18820
|
-
|
|
19514
|
+
var CodeEditor = React20.memo(function CodeEditor2({
|
|
19515
|
+
code: code3,
|
|
19516
|
+
language,
|
|
19517
|
+
onChange
|
|
19518
|
+
}) {
|
|
19519
|
+
const textareaRef = React20.useRef(null);
|
|
19520
|
+
const handleKeyDown = React20.useCallback((e) => {
|
|
19521
|
+
if (e.key === "Tab") {
|
|
19522
|
+
e.preventDefault();
|
|
19523
|
+
const textarea = e.currentTarget;
|
|
19524
|
+
const start = textarea.selectionStart;
|
|
19525
|
+
const end = textarea.selectionEnd;
|
|
19526
|
+
const newValue = code3.substring(0, start) + " " + code3.substring(end);
|
|
19527
|
+
onChange(newValue);
|
|
19528
|
+
requestAnimationFrame(() => {
|
|
19529
|
+
textarea.selectionStart = textarea.selectionEnd = start + 2;
|
|
19530
|
+
});
|
|
19531
|
+
}
|
|
19532
|
+
}, [code3, onChange]);
|
|
19533
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "h-full flex flex-col bg-zinc-950 agent-sdk-light:bg-white", children: [
|
|
19534
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-between px-4 py-2 border-b border-zinc-800/50 agent-sdk-light:border-zinc-200 bg-zinc-900/30 agent-sdk-light:bg-zinc-50 flex-shrink-0", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
19535
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, { size: 12, className: "text-[#d8ff00]" }),
|
|
19536
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-[#d8ff00] font-medium", children: "\u7F16\u8F91\u6A21\u5F0F" }),
|
|
19537
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-zinc-500 agent-sdk-light:text-zinc-600 font-mono uppercase ml-2", children: language || "text" })
|
|
19538
|
+
] }) }),
|
|
19539
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
19540
|
+
"textarea",
|
|
19541
|
+
{
|
|
19542
|
+
ref: textareaRef,
|
|
19543
|
+
value: code3,
|
|
19544
|
+
onChange: (e) => onChange(e.target.value),
|
|
19545
|
+
onKeyDown: handleKeyDown,
|
|
19546
|
+
className: "w-full h-full p-4 bg-zinc-950 agent-sdk-light:bg-white text-xs font-mono text-zinc-300 agent-sdk-light:text-zinc-800 leading-relaxed resize-none focus:outline-none",
|
|
19547
|
+
spellCheck: false,
|
|
19548
|
+
autoComplete: "off",
|
|
19549
|
+
autoCorrect: "off",
|
|
19550
|
+
autoCapitalize: "off"
|
|
19551
|
+
}
|
|
19552
|
+
) })
|
|
19553
|
+
] });
|
|
19554
|
+
});
|
|
19555
|
+
function useResolvedMediaUrl(content, options) {
|
|
19556
|
+
const { fileId, type = "image", config } = options || {};
|
|
19557
|
+
const [resolvedUrl, setResolvedUrl] = React20.useState(content);
|
|
19558
|
+
const [resolvedHdUrl, setResolvedHdUrl] = React20.useState(content);
|
|
19559
|
+
const [isLoading, setIsLoading] = React20.useState(true);
|
|
19560
|
+
React20.useEffect(() => {
|
|
19561
|
+
let active = true;
|
|
19562
|
+
setIsLoading(true);
|
|
19563
|
+
const resolve = async () => {
|
|
19564
|
+
const httpUrl = isHttpUrl(content) ? content : void 0;
|
|
19565
|
+
const asset = createAssetFromSource({
|
|
19566
|
+
fileId: fileId || (!httpUrl ? content : void 0),
|
|
19567
|
+
fileUrl: httpUrl,
|
|
19568
|
+
type
|
|
19569
|
+
});
|
|
19570
|
+
if (!asset) {
|
|
19571
|
+
if (active) {
|
|
19572
|
+
setResolvedUrl(content);
|
|
19573
|
+
setResolvedHdUrl(content);
|
|
19574
|
+
setIsLoading(false);
|
|
19575
|
+
}
|
|
19576
|
+
return;
|
|
19577
|
+
}
|
|
19578
|
+
const resolved = await resolveAssetForDisplay(asset, config);
|
|
19579
|
+
if (!active) return;
|
|
19580
|
+
if (resolved) {
|
|
19581
|
+
setResolvedUrl(resolved.url);
|
|
19582
|
+
setResolvedHdUrl(resolved.hdUrl || resolved.url);
|
|
19583
|
+
} else {
|
|
19584
|
+
setResolvedUrl(content);
|
|
19585
|
+
setResolvedHdUrl(content);
|
|
19586
|
+
}
|
|
19587
|
+
setIsLoading(false);
|
|
19588
|
+
};
|
|
19589
|
+
resolve();
|
|
19590
|
+
return () => {
|
|
19591
|
+
active = false;
|
|
19592
|
+
};
|
|
19593
|
+
}, [content, fileId, type, config]);
|
|
19594
|
+
return { url: resolvedUrl, hdUrl: resolvedHdUrl, isLoading };
|
|
19595
|
+
}
|
|
19596
|
+
function useResolvedThumbnailUrl(content, options) {
|
|
19597
|
+
const { fileId, type = "image", config, enabled = true } = options || {};
|
|
19598
|
+
const [url, setUrl] = React20.useState(null);
|
|
19599
|
+
React20.useEffect(() => {
|
|
19600
|
+
if (!enabled || !content) {
|
|
19601
|
+
setUrl(null);
|
|
19602
|
+
return;
|
|
19603
|
+
}
|
|
19604
|
+
if (type === "video") {
|
|
19605
|
+
setUrl(null);
|
|
19606
|
+
return;
|
|
19607
|
+
}
|
|
19608
|
+
let active = true;
|
|
19609
|
+
const resolve = async () => {
|
|
19610
|
+
const httpUrl = isHttpUrl(content) ? content : void 0;
|
|
19611
|
+
const asset = createAssetFromSource({
|
|
19612
|
+
fileId: fileId || (!httpUrl ? content : void 0),
|
|
19613
|
+
fileUrl: httpUrl,
|
|
19614
|
+
type
|
|
19615
|
+
});
|
|
19616
|
+
if (!asset) {
|
|
19617
|
+
if (active) setUrl(isHttpUrl(content) ? content : null);
|
|
19618
|
+
return;
|
|
19619
|
+
}
|
|
19620
|
+
const resolved = await resolveAssetForDisplay(asset, config);
|
|
19621
|
+
if (!active) return;
|
|
19622
|
+
setUrl(resolved?.url || (isHttpUrl(content) ? content : null));
|
|
19623
|
+
};
|
|
19624
|
+
resolve();
|
|
19625
|
+
return () => {
|
|
19626
|
+
active = false;
|
|
19627
|
+
};
|
|
19628
|
+
}, [content, fileId, type, config, enabled]);
|
|
19629
|
+
return url;
|
|
19630
|
+
}
|
|
19631
|
+
var ImageArtifactPreview = React20.memo(function ImageArtifactPreview2({
|
|
19632
|
+
content,
|
|
19633
|
+
metadata,
|
|
19634
|
+
config
|
|
19635
|
+
}) {
|
|
19636
|
+
const [isZoomed, setIsZoomed] = React20.useState(false);
|
|
19637
|
+
const [showInfo, setShowInfo] = React20.useState(true);
|
|
19638
|
+
const [imgNaturalSize, setImgNaturalSize] = React20.useState(null);
|
|
19639
|
+
const [copied, setCopied] = React20.useState(null);
|
|
19640
|
+
const { hdUrl: resolvedHdUrl } = useResolvedMediaUrl(content, {
|
|
19641
|
+
fileId: metadata?.fileId,
|
|
19642
|
+
type: "image",
|
|
19643
|
+
config
|
|
19644
|
+
});
|
|
19645
|
+
const generationParams = metadata?.generationParams;
|
|
19646
|
+
const toolName = metadata?.toolName;
|
|
19647
|
+
const relation = metadata?.relation;
|
|
19648
|
+
const handleCopy = React20.useCallback(async (text3, label) => {
|
|
19649
|
+
try {
|
|
19650
|
+
await navigator.clipboard.writeText(text3);
|
|
19651
|
+
setCopied(label);
|
|
19652
|
+
setTimeout(() => setCopied(null), 2e3);
|
|
19653
|
+
} catch {
|
|
19654
|
+
}
|
|
19655
|
+
}, []);
|
|
19656
|
+
const handleDownload = React20.useCallback(() => {
|
|
19657
|
+
const link2 = document.createElement("a");
|
|
19658
|
+
link2.href = resolvedHdUrl;
|
|
19659
|
+
link2.download = `generated-${Date.now()}.png`;
|
|
19660
|
+
link2.target = "_blank";
|
|
19661
|
+
document.body.appendChild(link2);
|
|
19662
|
+
link2.click();
|
|
19663
|
+
document.body.removeChild(link2);
|
|
19664
|
+
}, [resolvedHdUrl]);
|
|
19665
|
+
const formatParamKey = (key) => {
|
|
19666
|
+
const keyMap = {
|
|
19667
|
+
content: "Prompt",
|
|
19668
|
+
width: "\u5BBD\u5EA6",
|
|
19669
|
+
height: "\u9AD8\u5EA6",
|
|
19670
|
+
batchSize: "\u751F\u6210\u6570\u91CF",
|
|
19671
|
+
steps: "\u6B65\u6570",
|
|
19672
|
+
cfg_scale: "CFG Scale",
|
|
19673
|
+
seed: "\u79CD\u5B50",
|
|
19674
|
+
sampler: "\u91C7\u6837\u5668",
|
|
19675
|
+
model: "\u6A21\u578B",
|
|
19676
|
+
negative_prompt: "\u53CD\u5411\u63D0\u793A\u8BCD",
|
|
19677
|
+
style: "\u98CE\u683C",
|
|
19678
|
+
quality: "\u8D28\u91CF"
|
|
19679
|
+
};
|
|
19680
|
+
return keyMap[key] || key.replace(/([A-Z])/g, " $1").replace(/_/g, " ").replace(/^./, (s) => s.toUpperCase());
|
|
19681
|
+
};
|
|
19682
|
+
const promptText = generationParams?.content ? String(generationParams.content) : null;
|
|
19683
|
+
const otherParams = generationParams ? Object.entries(generationParams).filter(([key]) => key !== "content") : [];
|
|
19684
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "h-full flex flex-col bg-zinc-950 agent-sdk-light:bg-white", children: [
|
|
19685
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 overflow-auto flex items-center justify-center p-6 bg-zinc-950 agent-sdk-light:bg-zinc-50 relative", children: [
|
|
19686
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 opacity-[0.03]", style: {
|
|
19687
|
+
backgroundImage: "linear-gradient(45deg, #808080 25%, transparent 25%), linear-gradient(-45deg, #808080 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #808080 75%), linear-gradient(-45deg, transparent 75%, #808080 75%)",
|
|
19688
|
+
backgroundSize: "20px 20px",
|
|
19689
|
+
backgroundPosition: "0 0, 0 10px, 10px -10px, -10px 0px"
|
|
19690
|
+
} }),
|
|
19691
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
19692
|
+
"div",
|
|
19693
|
+
{
|
|
19694
|
+
className: cn2(
|
|
19695
|
+
"relative transition-transform duration-300 cursor-zoom-in z-10",
|
|
19696
|
+
isZoomed && "cursor-zoom-out scale-[2] z-50"
|
|
19697
|
+
),
|
|
19698
|
+
onClick: () => setIsZoomed((prev) => !prev),
|
|
19699
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
19700
|
+
"img",
|
|
19701
|
+
{
|
|
19702
|
+
src: resolvedHdUrl,
|
|
19703
|
+
alt: "Generated image",
|
|
19704
|
+
className: "max-w-full max-h-[60vh] object-contain rounded-lg shadow-2xl",
|
|
19705
|
+
loading: "lazy",
|
|
19706
|
+
onLoad: (e) => {
|
|
19707
|
+
const img = e.target;
|
|
19708
|
+
setImgNaturalSize({ width: img.naturalWidth, height: img.naturalHeight });
|
|
19709
|
+
}
|
|
19710
|
+
}
|
|
19711
|
+
)
|
|
19712
|
+
}
|
|
19713
|
+
),
|
|
19714
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute top-4 right-4 flex items-center gap-1.5 z-20", children: [
|
|
19715
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
19716
|
+
"button",
|
|
19717
|
+
{
|
|
19718
|
+
onClick: () => setShowInfo((prev) => !prev),
|
|
19719
|
+
className: cn2(
|
|
19720
|
+
"p-2 rounded-lg backdrop-blur-sm transition-colors",
|
|
19721
|
+
showInfo ? "bg-[#d8ff00]/20 text-[#d8ff00]" : "bg-black/30 text-white/70 hover:text-white hover:bg-black/50"
|
|
19722
|
+
),
|
|
19723
|
+
title: showInfo ? "\u9690\u85CF\u8BE6\u60C5" : "\u663E\u793A\u8BE6\u60C5",
|
|
19724
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileText, { size: 16 })
|
|
19725
|
+
}
|
|
19726
|
+
),
|
|
19727
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
19728
|
+
"button",
|
|
19729
|
+
{
|
|
19730
|
+
onClick: handleDownload,
|
|
19731
|
+
className: "p-2 bg-black/30 text-white/70 hover:text-white hover:bg-black/50 rounded-lg backdrop-blur-sm transition-colors",
|
|
19732
|
+
title: "\u4E0B\u8F7D\u56FE\u7247",
|
|
19733
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Download, { size: 16 })
|
|
19734
|
+
}
|
|
19735
|
+
)
|
|
19736
|
+
] }),
|
|
19737
|
+
imgNaturalSize && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute bottom-4 left-4 z-20 flex items-center gap-2 px-2.5 py-1.5 bg-black/40 backdrop-blur-sm rounded-lg", children: [
|
|
19738
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileImage, { size: 12, className: "text-white/60" }),
|
|
19739
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[11px] text-white/80 font-mono", children: [
|
|
19740
|
+
imgNaturalSize.width,
|
|
19741
|
+
" \xD7 ",
|
|
19742
|
+
imgNaturalSize.height
|
|
19743
|
+
] })
|
|
19744
|
+
] })
|
|
19745
|
+
] }),
|
|
19746
|
+
showInfo && (generationParams || toolName) && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0 border-t border-zinc-800/50 agent-sdk-light:border-zinc-200 bg-zinc-900/80 agent-sdk-light:bg-zinc-50 max-h-[40%] overflow-y-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-5 py-4 space-y-4", children: [
|
|
19747
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
19748
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2.5", children: [
|
|
19749
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-7 h-7 rounded-lg bg-[#d8ff00]/10 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { size: 14, className: "text-[#d8ff00]" }) }),
|
|
19750
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
19751
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-zinc-200 agent-sdk-light:text-zinc-800", children: toolName || "\u56FE\u7247\u751F\u6210" }),
|
|
19752
|
+
relation?.workflowCode && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2 text-[10px] text-zinc-500 font-mono bg-zinc-800/50 agent-sdk-light:bg-zinc-200 px-1.5 py-0.5 rounded", children: relation.workflowCode })
|
|
19753
|
+
] })
|
|
19754
|
+
] }),
|
|
19755
|
+
metadata?.taskId && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[10px] text-zinc-600 font-mono", children: [
|
|
19756
|
+
"Task: ",
|
|
19757
|
+
metadata.taskId
|
|
19758
|
+
] })
|
|
19759
|
+
] }),
|
|
19760
|
+
promptText && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
|
|
19761
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
19762
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-zinc-500 uppercase tracking-wider font-medium", children: "Prompt" }),
|
|
19763
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
19764
|
+
"button",
|
|
19765
|
+
{
|
|
19766
|
+
onClick: () => handleCopy(promptText, "prompt"),
|
|
19767
|
+
className: "text-[10px] text-zinc-500 hover:text-zinc-300 transition-colors flex items-center gap-1",
|
|
19768
|
+
children: copied === "prompt" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
19769
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCheck, { size: 10, className: "text-green-400" }),
|
|
19770
|
+
" \u5DF2\u590D\u5236"
|
|
19771
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
19772
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { size: 10 }),
|
|
19773
|
+
" \u590D\u5236"
|
|
19774
|
+
] })
|
|
19775
|
+
}
|
|
19776
|
+
)
|
|
19777
|
+
] }),
|
|
19778
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-3 bg-zinc-800/50 agent-sdk-light:bg-zinc-100 rounded-lg border border-zinc-700/30 agent-sdk-light:border-zinc-200", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-zinc-300 agent-sdk-light:text-zinc-700 leading-relaxed whitespace-pre-wrap", children: promptText }) })
|
|
19779
|
+
] }),
|
|
19780
|
+
otherParams.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
|
|
19781
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-zinc-500 uppercase tracking-wider font-medium", children: "\u53C2\u6570" }),
|
|
19782
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 sm:grid-cols-3 gap-2", children: otherParams.map(([key, value]) => {
|
|
19783
|
+
const displayValue = String(value);
|
|
19784
|
+
if (displayValue.length > 100) return null;
|
|
19785
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
19786
|
+
"div",
|
|
19787
|
+
{
|
|
19788
|
+
className: "flex flex-col gap-0.5 p-2 bg-zinc-800/30 agent-sdk-light:bg-zinc-100 rounded-lg border border-zinc-700/20 agent-sdk-light:border-zinc-200",
|
|
19789
|
+
children: [
|
|
19790
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-zinc-500 agent-sdk-light:text-zinc-500", children: formatParamKey(key) }),
|
|
19791
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-zinc-200 agent-sdk-light:text-zinc-800 font-mono font-medium truncate", title: displayValue, children: displayValue })
|
|
19792
|
+
]
|
|
19793
|
+
},
|
|
19794
|
+
key
|
|
19795
|
+
);
|
|
19796
|
+
}) })
|
|
19797
|
+
] }),
|
|
19798
|
+
(metadata?.fileId || metadata?.workId) && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pt-2 border-t border-zinc-800/30 agent-sdk-light:border-zinc-200", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-4 text-[10px] text-zinc-600", children: [
|
|
19799
|
+
metadata.workId && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
19800
|
+
"ID: ",
|
|
19801
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-zinc-500", children: metadata.workId })
|
|
19802
|
+
] }),
|
|
19803
|
+
metadata.fileId && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "truncate max-w-[200px]", title: metadata.fileId, children: [
|
|
19804
|
+
"File: ",
|
|
19805
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-zinc-500", children: metadata.fileId })
|
|
19806
|
+
] })
|
|
19807
|
+
] }) })
|
|
19808
|
+
] }) })
|
|
19809
|
+
] });
|
|
19810
|
+
});
|
|
19811
|
+
var VideoArtifactPreview = React20.memo(function VideoArtifactPreview2({
|
|
19812
|
+
content,
|
|
19813
|
+
metadata,
|
|
19814
|
+
config
|
|
19815
|
+
}) {
|
|
19816
|
+
const { hdUrl: resolvedUrl } = useResolvedMediaUrl(content, {
|
|
19817
|
+
fileId: metadata?.fileId,
|
|
19818
|
+
type: "video",
|
|
19819
|
+
config
|
|
19820
|
+
});
|
|
19821
|
+
const videoRef = React20.useRef(null);
|
|
19822
|
+
const progressRef = React20.useRef(null);
|
|
19823
|
+
const [isPlaying, setIsPlaying] = React20.useState(false);
|
|
19824
|
+
const [isMuted, setIsMuted] = React20.useState(false);
|
|
19825
|
+
const [duration, setDuration] = React20.useState(0);
|
|
19826
|
+
const [currentTime, setCurrentTime] = React20.useState(0);
|
|
19827
|
+
const [volume, setVolume] = React20.useState(1);
|
|
19828
|
+
const [isLoaded, setIsLoaded] = React20.useState(false);
|
|
19829
|
+
const [showVolumeSlider, setShowVolumeSlider] = React20.useState(false);
|
|
19830
|
+
const [posterUrl, setPosterUrl] = React20.useState(null);
|
|
19831
|
+
const [isDraggingProgress, setIsDraggingProgress] = React20.useState(false);
|
|
19832
|
+
const generationParams = metadata?.generationParams;
|
|
19833
|
+
const toolName = metadata?.toolName;
|
|
19834
|
+
React20.useEffect(() => {
|
|
19835
|
+
const video = document.createElement("video");
|
|
19836
|
+
video.crossOrigin = "anonymous";
|
|
19837
|
+
video.preload = "metadata";
|
|
19838
|
+
video.muted = true;
|
|
19839
|
+
video.addEventListener("loadeddata", () => {
|
|
19840
|
+
video.currentTime = Math.min(0.5, video.duration * 0.1);
|
|
19841
|
+
});
|
|
19842
|
+
video.addEventListener("seeked", () => {
|
|
19843
|
+
try {
|
|
19844
|
+
const canvas = document.createElement("canvas");
|
|
19845
|
+
canvas.width = video.videoWidth;
|
|
19846
|
+
canvas.height = video.videoHeight;
|
|
19847
|
+
const ctx = canvas.getContext("2d");
|
|
19848
|
+
if (ctx) {
|
|
19849
|
+
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
|
|
19850
|
+
setPosterUrl(canvas.toDataURL("image/jpeg", 0.8));
|
|
19851
|
+
}
|
|
19852
|
+
} catch {
|
|
19853
|
+
}
|
|
19854
|
+
video.remove();
|
|
19855
|
+
});
|
|
19856
|
+
video.addEventListener("error", () => video.remove());
|
|
19857
|
+
video.src = resolvedUrl;
|
|
19858
|
+
video.load();
|
|
19859
|
+
return () => {
|
|
19860
|
+
video.remove();
|
|
19861
|
+
};
|
|
19862
|
+
}, [resolvedUrl]);
|
|
19863
|
+
const handleLoadedMetadata = () => {
|
|
19864
|
+
const video = videoRef.current;
|
|
19865
|
+
if (video) {
|
|
19866
|
+
setDuration(video.duration);
|
|
19867
|
+
setIsLoaded(true);
|
|
19868
|
+
}
|
|
19869
|
+
};
|
|
19870
|
+
const handleTimeUpdate = () => {
|
|
19871
|
+
if (!isDraggingProgress && videoRef.current) {
|
|
19872
|
+
setCurrentTime(videoRef.current.currentTime);
|
|
19873
|
+
}
|
|
19874
|
+
};
|
|
19875
|
+
const togglePlay = React20.useCallback(() => {
|
|
19876
|
+
const video = videoRef.current;
|
|
19877
|
+
if (!video) return;
|
|
19878
|
+
if (isPlaying) {
|
|
19879
|
+
video.pause();
|
|
19880
|
+
setIsPlaying(false);
|
|
19881
|
+
} else {
|
|
19882
|
+
video.play().then(() => setIsPlaying(true)).catch(() => {
|
|
19883
|
+
});
|
|
19884
|
+
}
|
|
19885
|
+
}, [isPlaying]);
|
|
19886
|
+
const toggleMute = React20.useCallback(() => {
|
|
19887
|
+
const video = videoRef.current;
|
|
19888
|
+
if (video) {
|
|
19889
|
+
video.muted = !isMuted;
|
|
19890
|
+
setIsMuted(!isMuted);
|
|
19891
|
+
}
|
|
19892
|
+
}, [isMuted]);
|
|
19893
|
+
const handleVolumeChange = React20.useCallback((e) => {
|
|
19894
|
+
const newVolume = parseFloat(e.target.value);
|
|
19895
|
+
setVolume(newVolume);
|
|
19896
|
+
if (videoRef.current) {
|
|
19897
|
+
videoRef.current.volume = newVolume;
|
|
19898
|
+
if (newVolume === 0) {
|
|
19899
|
+
setIsMuted(true);
|
|
19900
|
+
videoRef.current.muted = true;
|
|
19901
|
+
} else if (isMuted) {
|
|
19902
|
+
setIsMuted(false);
|
|
19903
|
+
videoRef.current.muted = false;
|
|
19904
|
+
}
|
|
19905
|
+
}
|
|
19906
|
+
}, [isMuted]);
|
|
19907
|
+
const handleProgressClick = React20.useCallback((e) => {
|
|
19908
|
+
const video = videoRef.current;
|
|
19909
|
+
const bar = progressRef.current;
|
|
19910
|
+
if (!video || !bar || !duration) return;
|
|
19911
|
+
const rect = bar.getBoundingClientRect();
|
|
19912
|
+
const ratio = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width));
|
|
19913
|
+
video.currentTime = ratio * duration;
|
|
19914
|
+
setCurrentTime(ratio * duration);
|
|
19915
|
+
}, [duration]);
|
|
19916
|
+
const handleProgressDrag = React20.useCallback((e) => {
|
|
19917
|
+
if (!isDraggingProgress) return;
|
|
19918
|
+
const bar = progressRef.current;
|
|
19919
|
+
if (!bar || !duration) return;
|
|
19920
|
+
const rect = bar.getBoundingClientRect();
|
|
19921
|
+
const ratio = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width));
|
|
19922
|
+
setCurrentTime(ratio * duration);
|
|
19923
|
+
}, [isDraggingProgress, duration]);
|
|
19924
|
+
const handleProgressDragEnd = React20.useCallback(() => {
|
|
19925
|
+
if (isDraggingProgress && videoRef.current) {
|
|
19926
|
+
videoRef.current.currentTime = currentTime;
|
|
19927
|
+
}
|
|
19928
|
+
setIsDraggingProgress(false);
|
|
19929
|
+
}, [isDraggingProgress, currentTime]);
|
|
19930
|
+
React20.useEffect(() => {
|
|
19931
|
+
if (!isDraggingProgress) return;
|
|
19932
|
+
const handleMouseUp = () => handleProgressDragEnd();
|
|
19933
|
+
const handleMouseMove = (e) => {
|
|
19934
|
+
const bar = progressRef.current;
|
|
19935
|
+
if (!bar || !duration) return;
|
|
19936
|
+
const rect = bar.getBoundingClientRect();
|
|
19937
|
+
const ratio = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width));
|
|
19938
|
+
setCurrentTime(ratio * duration);
|
|
19939
|
+
};
|
|
19940
|
+
window.addEventListener("mouseup", handleMouseUp);
|
|
19941
|
+
window.addEventListener("mousemove", handleMouseMove);
|
|
19942
|
+
return () => {
|
|
19943
|
+
window.removeEventListener("mouseup", handleMouseUp);
|
|
19944
|
+
window.removeEventListener("mousemove", handleMouseMove);
|
|
19945
|
+
};
|
|
19946
|
+
}, [isDraggingProgress, duration, handleProgressDragEnd]);
|
|
19947
|
+
const handleDownload = React20.useCallback(() => {
|
|
19948
|
+
const link2 = document.createElement("a");
|
|
19949
|
+
link2.href = resolvedUrl;
|
|
19950
|
+
link2.download = `video-${Date.now()}.mp4`;
|
|
19951
|
+
document.body.appendChild(link2);
|
|
19952
|
+
link2.click();
|
|
19953
|
+
document.body.removeChild(link2);
|
|
19954
|
+
}, [resolvedUrl]);
|
|
19955
|
+
const formatTime2 = (seconds) => {
|
|
19956
|
+
const mins = Math.floor(seconds / 60);
|
|
19957
|
+
const secs = Math.floor(seconds % 60);
|
|
19958
|
+
return `${mins}:${secs.toString().padStart(2, "0")}`;
|
|
19959
|
+
};
|
|
19960
|
+
const progressPercent = duration > 0 ? currentTime / duration * 100 : 0;
|
|
19961
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "h-full flex flex-col bg-zinc-950 agent-sdk-light:bg-white", children: [
|
|
19962
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 overflow-hidden flex items-center justify-center bg-black relative group/player", children: [
|
|
19963
|
+
posterUrl && !isPlaying && !currentTime && /* @__PURE__ */ jsxRuntime.jsx(
|
|
19964
|
+
"img",
|
|
19965
|
+
{
|
|
19966
|
+
src: posterUrl,
|
|
19967
|
+
alt: "Video cover",
|
|
19968
|
+
className: "absolute inset-0 w-full h-full object-contain z-[1]"
|
|
19969
|
+
}
|
|
19970
|
+
),
|
|
19971
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
19972
|
+
"video",
|
|
19973
|
+
{
|
|
19974
|
+
ref: videoRef,
|
|
19975
|
+
src: resolvedUrl,
|
|
19976
|
+
muted: isMuted,
|
|
19977
|
+
playsInline: true,
|
|
19978
|
+
preload: "metadata",
|
|
19979
|
+
onLoadedMetadata: handleLoadedMetadata,
|
|
19980
|
+
onTimeUpdate: handleTimeUpdate,
|
|
19981
|
+
onEnded: () => setIsPlaying(false),
|
|
19982
|
+
onClick: togglePlay,
|
|
19983
|
+
className: cn2(
|
|
19984
|
+
"max-w-full max-h-full object-contain cursor-pointer",
|
|
19985
|
+
!isPlaying && posterUrl && !currentTime && "opacity-0"
|
|
19986
|
+
)
|
|
19987
|
+
}
|
|
19988
|
+
),
|
|
19989
|
+
!isPlaying && /* @__PURE__ */ jsxRuntime.jsx(
|
|
19990
|
+
"div",
|
|
19991
|
+
{
|
|
19992
|
+
className: "absolute inset-0 z-[2] flex items-center justify-center cursor-pointer",
|
|
19993
|
+
onClick: togglePlay,
|
|
19994
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn2(
|
|
19995
|
+
"w-16 h-16 rounded-full bg-white/15 backdrop-blur-md",
|
|
19996
|
+
"flex items-center justify-center",
|
|
19997
|
+
"transition-all duration-200",
|
|
19998
|
+
"group-hover/player:scale-110 group-hover/player:bg-white/25",
|
|
19999
|
+
"shadow-2xl shadow-black/30"
|
|
20000
|
+
), children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "26", height: "26", viewBox: "0 0 24 24", fill: "white", className: "ml-1", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 5v14l11-7z" }) }) })
|
|
20001
|
+
}
|
|
20002
|
+
),
|
|
20003
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn2(
|
|
20004
|
+
"absolute bottom-0 left-0 right-0 z-[3]",
|
|
20005
|
+
"bg-gradient-to-t from-black/90 via-black/50 to-transparent",
|
|
20006
|
+
"px-4 pb-3 pt-10",
|
|
20007
|
+
"transition-opacity duration-300",
|
|
20008
|
+
"opacity-0 group-hover/player:opacity-100",
|
|
20009
|
+
isPlaying ? "" : "opacity-100"
|
|
20010
|
+
), children: [
|
|
20011
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20012
|
+
"div",
|
|
20013
|
+
{
|
|
20014
|
+
ref: progressRef,
|
|
20015
|
+
className: "w-full h-1.5 bg-white/20 rounded-full mb-3 cursor-pointer group/progress hover:h-2 transition-all",
|
|
20016
|
+
onClick: handleProgressClick,
|
|
20017
|
+
onMouseDown: () => setIsDraggingProgress(true),
|
|
20018
|
+
onMouseMove: handleProgressDrag,
|
|
20019
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
20020
|
+
"div",
|
|
20021
|
+
{
|
|
20022
|
+
className: "h-full bg-[#d8ff00] rounded-full relative",
|
|
20023
|
+
style: { width: `${progressPercent}%` },
|
|
20024
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute right-0 top-1/2 -translate-y-1/2 w-3.5 h-3.5 bg-[#d8ff00] rounded-full opacity-0 group-hover/progress:opacity-100 transition-opacity shadow-lg -mr-1.5" })
|
|
20025
|
+
}
|
|
20026
|
+
)
|
|
20027
|
+
}
|
|
20028
|
+
),
|
|
20029
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
20030
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
20031
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: togglePlay, className: "p-1 text-white/90 hover:text-white transition-colors", children: isPlaying ? /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "currentColor", children: [
|
|
20032
|
+
/* @__PURE__ */ jsxRuntime.jsx("rect", { x: "6", y: "4", width: "4", height: "16", rx: "1" }),
|
|
20033
|
+
/* @__PURE__ */ jsxRuntime.jsx("rect", { x: "14", y: "4", width: "4", height: "16", rx: "1" })
|
|
20034
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 5v14l11-7z" }) }) }),
|
|
20035
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
20036
|
+
"div",
|
|
20037
|
+
{
|
|
20038
|
+
className: "flex items-center gap-1.5 relative",
|
|
20039
|
+
onMouseEnter: () => setShowVolumeSlider(true),
|
|
20040
|
+
onMouseLeave: () => setShowVolumeSlider(false),
|
|
20041
|
+
children: [
|
|
20042
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: toggleMute, className: "p-1 text-white/80 hover:text-white transition-colors", children: isMuted || volume === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
20043
|
+
/* @__PURE__ */ jsxRuntime.jsx("polygon", { points: "11 5 6 9 2 9 2 15 6 15 11 19 11 5" }),
|
|
20044
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "23", y1: "9", x2: "17", y2: "15" }),
|
|
20045
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "17", y1: "9", x2: "23", y2: "15" })
|
|
20046
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
20047
|
+
/* @__PURE__ */ jsxRuntime.jsx("polygon", { points: "11 5 6 9 2 9 2 15 6 15 11 19 11 5" }),
|
|
20048
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M19.07 4.93a10 10 0 0 1 0 14.14" }),
|
|
20049
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15.54 8.46a5 5 0 0 1 0 7.07" })
|
|
20050
|
+
] }) }),
|
|
20051
|
+
showVolumeSlider && /* @__PURE__ */ jsxRuntime.jsx(
|
|
20052
|
+
"input",
|
|
20053
|
+
{
|
|
20054
|
+
type: "range",
|
|
20055
|
+
min: "0",
|
|
20056
|
+
max: "1",
|
|
20057
|
+
step: "0.05",
|
|
20058
|
+
value: isMuted ? 0 : volume,
|
|
20059
|
+
onChange: handleVolumeChange,
|
|
20060
|
+
className: "w-20 h-1 appearance-none bg-white/20 rounded-full cursor-pointer accent-[#d8ff00]"
|
|
20061
|
+
}
|
|
20062
|
+
)
|
|
20063
|
+
]
|
|
20064
|
+
}
|
|
20065
|
+
),
|
|
20066
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-white/60 font-mono tabular-nums", children: [
|
|
20067
|
+
formatTime2(currentTime),
|
|
20068
|
+
" / ",
|
|
20069
|
+
formatTime2(duration)
|
|
20070
|
+
] })
|
|
20071
|
+
] }),
|
|
20072
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
20073
|
+
"button",
|
|
20074
|
+
{
|
|
20075
|
+
onClick: handleDownload,
|
|
20076
|
+
className: "p-1.5 text-white/60 hover:text-white transition-colors",
|
|
20077
|
+
title: "\u4E0B\u8F7D\u89C6\u9891",
|
|
20078
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Download, { size: 16 })
|
|
20079
|
+
}
|
|
20080
|
+
) })
|
|
20081
|
+
] })
|
|
20082
|
+
] })
|
|
20083
|
+
] }),
|
|
20084
|
+
generationParams && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0 border-t border-zinc-800/50 agent-sdk-light:border-zinc-200 bg-zinc-900/50 agent-sdk-light:bg-zinc-50", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-4 py-3", children: [
|
|
20085
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mb-2", children: [
|
|
20086
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { size: 12, className: "text-[#d8ff00]" }),
|
|
20087
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-zinc-300 agent-sdk-light:text-zinc-700", children: toolName || "\u751F\u6210\u53C2\u6570" })
|
|
20088
|
+
] }),
|
|
20089
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-x-4 gap-y-1.5", children: Object.entries(generationParams).map(([key, value]) => {
|
|
20090
|
+
const displayValue = String(value);
|
|
20091
|
+
if (displayValue.length > 80) return null;
|
|
20092
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-xs", children: [
|
|
20093
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-zinc-500 agent-sdk-light:text-zinc-500 capitalize", children: key.replace(/([A-Z])/g, " $1").replace(/^./, (s) => s.toUpperCase()) }),
|
|
20094
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-zinc-300 agent-sdk-light:text-zinc-700 font-mono", children: displayValue })
|
|
20095
|
+
] }, key);
|
|
20096
|
+
}) }),
|
|
20097
|
+
generationParams.content && String(generationParams.content).length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 pt-2 border-t border-zinc-800/30 agent-sdk-light:border-zinc-200", children: [
|
|
20098
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-zinc-500 agent-sdk-light:text-zinc-500 uppercase tracking-wider", children: "Prompt" }),
|
|
20099
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-zinc-300 agent-sdk-light:text-zinc-700 mt-1 leading-relaxed line-clamp-3", children: String(generationParams.content) })
|
|
20100
|
+
] })
|
|
20101
|
+
] }) })
|
|
20102
|
+
] });
|
|
20103
|
+
});
|
|
20104
|
+
function htmlToMarkdown(element) {
|
|
20105
|
+
const lines = [];
|
|
20106
|
+
function processNode(node2, listDepth = 0) {
|
|
20107
|
+
if (node2.nodeType === Node.TEXT_NODE) {
|
|
20108
|
+
return node2.textContent || "";
|
|
20109
|
+
}
|
|
20110
|
+
if (node2.nodeType !== Node.ELEMENT_NODE) return "";
|
|
20111
|
+
const el = node2;
|
|
20112
|
+
const tag = el.tagName.toLowerCase();
|
|
20113
|
+
const childContent = () => {
|
|
20114
|
+
let result = "";
|
|
20115
|
+
el.childNodes.forEach((child) => {
|
|
20116
|
+
result += processNode(child, listDepth);
|
|
20117
|
+
});
|
|
20118
|
+
return result;
|
|
20119
|
+
};
|
|
20120
|
+
switch (tag) {
|
|
20121
|
+
case "h1":
|
|
20122
|
+
return `# ${childContent().trim()}
|
|
20123
|
+
|
|
20124
|
+
`;
|
|
20125
|
+
case "h2":
|
|
20126
|
+
return `## ${childContent().trim()}
|
|
20127
|
+
|
|
20128
|
+
`;
|
|
20129
|
+
case "h3":
|
|
20130
|
+
return `### ${childContent().trim()}
|
|
20131
|
+
|
|
20132
|
+
`;
|
|
20133
|
+
case "h4":
|
|
20134
|
+
return `#### ${childContent().trim()}
|
|
20135
|
+
|
|
20136
|
+
`;
|
|
20137
|
+
case "h5":
|
|
20138
|
+
return `##### ${childContent().trim()}
|
|
20139
|
+
|
|
20140
|
+
`;
|
|
20141
|
+
case "h6":
|
|
20142
|
+
return `###### ${childContent().trim()}
|
|
20143
|
+
|
|
20144
|
+
`;
|
|
20145
|
+
case "p": {
|
|
20146
|
+
const inner = childContent().trim();
|
|
20147
|
+
return inner ? `${inner}
|
|
20148
|
+
|
|
20149
|
+
` : "\n";
|
|
20150
|
+
}
|
|
20151
|
+
case "br":
|
|
20152
|
+
return "\n";
|
|
20153
|
+
case "strong":
|
|
20154
|
+
case "b":
|
|
20155
|
+
return `**${childContent()}**`;
|
|
20156
|
+
case "em":
|
|
20157
|
+
case "i":
|
|
20158
|
+
return `*${childContent()}*`;
|
|
20159
|
+
case "del":
|
|
20160
|
+
case "s":
|
|
20161
|
+
return `~~${childContent()}~~`;
|
|
20162
|
+
case "code": {
|
|
20163
|
+
if (el.parentElement?.tagName.toLowerCase() === "pre") {
|
|
20164
|
+
return childContent();
|
|
20165
|
+
}
|
|
20166
|
+
return `\`${childContent()}\``;
|
|
20167
|
+
}
|
|
20168
|
+
case "pre": {
|
|
20169
|
+
const codeEl = el.querySelector("code");
|
|
20170
|
+
const codeContent = codeEl ? codeEl.textContent || "" : el.textContent || "";
|
|
20171
|
+
const langClass = codeEl?.className?.match(/language-(\w+)/);
|
|
20172
|
+
const lang = langClass ? langClass[1] : "";
|
|
20173
|
+
return `\`\`\`${lang}
|
|
20174
|
+
${codeContent.trim()}
|
|
20175
|
+
\`\`\`
|
|
20176
|
+
|
|
20177
|
+
`;
|
|
20178
|
+
}
|
|
20179
|
+
case "blockquote": {
|
|
20180
|
+
const inner = childContent().trim();
|
|
20181
|
+
return inner.split("\n").map((line) => `> ${line}`).join("\n") + "\n\n";
|
|
20182
|
+
}
|
|
20183
|
+
case "ul": {
|
|
20184
|
+
let result = "";
|
|
20185
|
+
el.childNodes.forEach((child) => {
|
|
20186
|
+
if (child.tagName?.toLowerCase() === "li") {
|
|
20187
|
+
const indent2 = " ".repeat(listDepth);
|
|
20188
|
+
const liContent = processListItem(child, listDepth);
|
|
20189
|
+
result += `${indent2}- ${liContent}
|
|
20190
|
+
`;
|
|
20191
|
+
}
|
|
20192
|
+
});
|
|
20193
|
+
return listDepth === 0 ? result + "\n" : result;
|
|
20194
|
+
}
|
|
20195
|
+
case "ol": {
|
|
20196
|
+
let result = "";
|
|
20197
|
+
let index = 1;
|
|
20198
|
+
el.childNodes.forEach((child) => {
|
|
20199
|
+
if (child.tagName?.toLowerCase() === "li") {
|
|
20200
|
+
const indent2 = " ".repeat(listDepth);
|
|
20201
|
+
const liContent = processListItem(child, listDepth);
|
|
20202
|
+
result += `${indent2}${index}. ${liContent}
|
|
20203
|
+
`;
|
|
20204
|
+
index++;
|
|
20205
|
+
}
|
|
20206
|
+
});
|
|
20207
|
+
return listDepth === 0 ? result + "\n" : result;
|
|
20208
|
+
}
|
|
20209
|
+
case "li": {
|
|
20210
|
+
return childContent();
|
|
20211
|
+
}
|
|
20212
|
+
case "a": {
|
|
20213
|
+
const href = el.getAttribute("href") || "";
|
|
20214
|
+
const text3 = childContent();
|
|
20215
|
+
return `[${text3}](${href})`;
|
|
20216
|
+
}
|
|
20217
|
+
case "img": {
|
|
20218
|
+
const src = el.getAttribute("src") || "";
|
|
20219
|
+
const alt = el.getAttribute("alt") || "";
|
|
20220
|
+
return ``;
|
|
20221
|
+
}
|
|
20222
|
+
case "hr":
|
|
20223
|
+
return "---\n\n";
|
|
20224
|
+
case "table": {
|
|
20225
|
+
return processTable(el) + "\n";
|
|
20226
|
+
}
|
|
20227
|
+
case "input": {
|
|
20228
|
+
if (el.getAttribute("type") === "checkbox") {
|
|
20229
|
+
return el.hasAttribute("checked") ? "[x] " : "[ ] ";
|
|
20230
|
+
}
|
|
20231
|
+
return "";
|
|
20232
|
+
}
|
|
20233
|
+
case "div":
|
|
20234
|
+
case "span":
|
|
20235
|
+
case "section":
|
|
20236
|
+
case "article":
|
|
20237
|
+
case "main":
|
|
20238
|
+
case "header":
|
|
20239
|
+
case "footer":
|
|
20240
|
+
return childContent();
|
|
20241
|
+
default:
|
|
20242
|
+
return childContent();
|
|
20243
|
+
}
|
|
20244
|
+
}
|
|
20245
|
+
function processListItem(li, depth, _ordered) {
|
|
20246
|
+
let textParts = [];
|
|
20247
|
+
let subLists = "";
|
|
20248
|
+
li.childNodes.forEach((child) => {
|
|
20249
|
+
const childTag = child.tagName?.toLowerCase();
|
|
20250
|
+
if (childTag === "ul" || childTag === "ol") {
|
|
20251
|
+
subLists += processNode(child, depth + 1);
|
|
20252
|
+
} else {
|
|
20253
|
+
textParts.push(processNode(child, depth));
|
|
20254
|
+
}
|
|
20255
|
+
});
|
|
20256
|
+
let result = textParts.join("").trim();
|
|
20257
|
+
if (subLists) {
|
|
20258
|
+
result += "\n" + subLists;
|
|
20259
|
+
}
|
|
20260
|
+
return result;
|
|
20261
|
+
}
|
|
20262
|
+
function processTable(table) {
|
|
20263
|
+
const rows = [];
|
|
20264
|
+
table.querySelectorAll("tr").forEach((tr) => {
|
|
20265
|
+
const cells = [];
|
|
20266
|
+
tr.querySelectorAll("th, td").forEach((cell) => {
|
|
20267
|
+
cells.push((cell.textContent || "").trim());
|
|
20268
|
+
});
|
|
20269
|
+
rows.push(cells);
|
|
20270
|
+
});
|
|
20271
|
+
if (rows.length === 0) return "";
|
|
20272
|
+
const colCount = Math.max(...rows.map((r3) => r3.length));
|
|
20273
|
+
const colWidths = Array(colCount).fill(3);
|
|
20274
|
+
rows.forEach((row) => {
|
|
20275
|
+
row.forEach((cell, i) => {
|
|
20276
|
+
colWidths[i] = Math.max(colWidths[i], cell.length);
|
|
20277
|
+
});
|
|
20278
|
+
});
|
|
20279
|
+
let result = "";
|
|
20280
|
+
rows.forEach((row, rowIndex) => {
|
|
20281
|
+
const paddedCells = Array(colCount).fill("").map((_, i) => {
|
|
20282
|
+
const cell = row[i] || "";
|
|
20283
|
+
return cell.padEnd(colWidths[i]);
|
|
20284
|
+
});
|
|
20285
|
+
result += `| ${paddedCells.join(" | ")} |
|
|
20286
|
+
`;
|
|
20287
|
+
if (rowIndex === 0) {
|
|
20288
|
+
const separators = colWidths.map((w) => "-".repeat(w));
|
|
20289
|
+
result += `| ${separators.join(" | ")} |
|
|
20290
|
+
`;
|
|
20291
|
+
}
|
|
20292
|
+
});
|
|
20293
|
+
return result;
|
|
20294
|
+
}
|
|
20295
|
+
element.childNodes.forEach((child) => {
|
|
20296
|
+
lines.push(processNode(child));
|
|
20297
|
+
});
|
|
20298
|
+
return lines.join("").replace(/\n{3,}/g, "\n\n").trim() + "\n";
|
|
20299
|
+
}
|
|
20300
|
+
var MarkdownEditor = React20.memo(function MarkdownEditor2({
|
|
20301
|
+
content,
|
|
20302
|
+
onChange,
|
|
20303
|
+
config
|
|
20304
|
+
}) {
|
|
20305
|
+
const editorRef = React20.useRef(null);
|
|
20306
|
+
const textareaRef = React20.useRef(null);
|
|
20307
|
+
const [isSourceMode, setIsSourceMode] = React20.useState(false);
|
|
20308
|
+
const isInternalUpdate = React20.useRef(false);
|
|
20309
|
+
const lastMarkdownRef = React20.useRef(content);
|
|
20310
|
+
const contentToHtml = React20.useCallback((markdown) => {
|
|
20311
|
+
return marked.marked.parse(markdown, { breaks: true, gfm: true });
|
|
20312
|
+
}, []);
|
|
20313
|
+
React20.useEffect(() => {
|
|
20314
|
+
if (isSourceMode) return;
|
|
20315
|
+
if (isInternalUpdate.current) {
|
|
20316
|
+
isInternalUpdate.current = false;
|
|
20317
|
+
return;
|
|
20318
|
+
}
|
|
20319
|
+
if (editorRef.current && content !== lastMarkdownRef.current) {
|
|
20320
|
+
const html2 = contentToHtml(content);
|
|
20321
|
+
editorRef.current.innerHTML = html2;
|
|
20322
|
+
lastMarkdownRef.current = content;
|
|
20323
|
+
}
|
|
20324
|
+
}, [content, isSourceMode, contentToHtml]);
|
|
20325
|
+
React20.useEffect(() => {
|
|
20326
|
+
if (editorRef.current && !isSourceMode) {
|
|
20327
|
+
const html2 = contentToHtml(content);
|
|
20328
|
+
editorRef.current.innerHTML = html2;
|
|
20329
|
+
}
|
|
20330
|
+
}, []);
|
|
20331
|
+
const handleInput = React20.useCallback(() => {
|
|
20332
|
+
if (!editorRef.current) return;
|
|
20333
|
+
const markdown = htmlToMarkdown(editorRef.current);
|
|
20334
|
+
lastMarkdownRef.current = markdown;
|
|
20335
|
+
isInternalUpdate.current = true;
|
|
20336
|
+
onChange(markdown);
|
|
20337
|
+
}, [onChange]);
|
|
20338
|
+
const execCommand = React20.useCallback((command, value) => {
|
|
20339
|
+
editorRef.current?.focus();
|
|
20340
|
+
document.execCommand(command, false, value);
|
|
20341
|
+
requestAnimationFrame(() => handleInput());
|
|
20342
|
+
}, [handleInput]);
|
|
20343
|
+
const formatBlock = React20.useCallback((tag) => {
|
|
20344
|
+
execCommand("formatBlock", tag);
|
|
20345
|
+
}, [execCommand]);
|
|
20346
|
+
const insertHorizontalRule = React20.useCallback(() => {
|
|
20347
|
+
execCommand("insertHorizontalRule");
|
|
20348
|
+
}, [execCommand]);
|
|
20349
|
+
const insertLink = React20.useCallback(() => {
|
|
20350
|
+
const selection = window.getSelection();
|
|
20351
|
+
const selectedText = selection?.toString() || "\u94FE\u63A5\u6587\u672C";
|
|
20352
|
+
const url = prompt("\u8BF7\u8F93\u5165\u94FE\u63A5\u5730\u5740:", "https://");
|
|
20353
|
+
if (url) {
|
|
20354
|
+
if (selection && selection.rangeCount > 0) {
|
|
20355
|
+
const range = selection.getRangeAt(0);
|
|
20356
|
+
range.deleteContents();
|
|
20357
|
+
const anchor = document.createElement("a");
|
|
20358
|
+
anchor.href = url;
|
|
20359
|
+
anchor.textContent = selectedText;
|
|
20360
|
+
range.insertNode(anchor);
|
|
20361
|
+
range.setStartAfter(anchor);
|
|
20362
|
+
range.collapse(true);
|
|
20363
|
+
selection.removeAllRanges();
|
|
20364
|
+
selection.addRange(range);
|
|
20365
|
+
}
|
|
20366
|
+
requestAnimationFrame(() => handleInput());
|
|
20367
|
+
}
|
|
20368
|
+
}, [handleInput]);
|
|
20369
|
+
const insertImage = React20.useCallback(() => {
|
|
20370
|
+
const url = prompt("\u8BF7\u8F93\u5165\u56FE\u7247\u5730\u5740:", "https://");
|
|
20371
|
+
if (url) {
|
|
20372
|
+
execCommand("insertImage", url);
|
|
20373
|
+
}
|
|
20374
|
+
}, [execCommand]);
|
|
20375
|
+
const insertCodeBlock = React20.useCallback(() => {
|
|
20376
|
+
const editor = editorRef.current;
|
|
20377
|
+
if (!editor) return;
|
|
20378
|
+
const selection = window.getSelection();
|
|
20379
|
+
if (selection && selection.rangeCount > 0) {
|
|
20380
|
+
const range = selection.getRangeAt(0);
|
|
20381
|
+
const pre = document.createElement("pre");
|
|
20382
|
+
const code3 = document.createElement("code");
|
|
20383
|
+
code3.textContent = selection.toString() || "\u4EE3\u7801\u5185\u5BB9";
|
|
20384
|
+
pre.appendChild(code3);
|
|
20385
|
+
range.deleteContents();
|
|
20386
|
+
range.insertNode(pre);
|
|
20387
|
+
const paragraph2 = document.createElement("p");
|
|
20388
|
+
paragraph2.innerHTML = "<br>";
|
|
20389
|
+
pre.parentNode?.insertBefore(paragraph2, pre.nextSibling);
|
|
20390
|
+
range.setStart(paragraph2, 0);
|
|
20391
|
+
range.collapse(true);
|
|
20392
|
+
selection.removeAllRanges();
|
|
20393
|
+
selection.addRange(range);
|
|
20394
|
+
}
|
|
20395
|
+
requestAnimationFrame(() => handleInput());
|
|
20396
|
+
}, [handleInput]);
|
|
20397
|
+
const handleKeyDown = React20.useCallback((e) => {
|
|
20398
|
+
const isMod = e.metaKey || e.ctrlKey;
|
|
20399
|
+
if (isMod && e.key === "b") {
|
|
20400
|
+
e.preventDefault();
|
|
20401
|
+
execCommand("bold");
|
|
20402
|
+
} else if (isMod && e.key === "i") {
|
|
20403
|
+
e.preventDefault();
|
|
20404
|
+
execCommand("italic");
|
|
20405
|
+
} else if (isMod && e.key === "u") {
|
|
20406
|
+
e.preventDefault();
|
|
20407
|
+
execCommand("underline");
|
|
20408
|
+
} else if (isMod && e.key === "e") {
|
|
20409
|
+
e.preventDefault();
|
|
20410
|
+
const selection = window.getSelection();
|
|
20411
|
+
if (selection && selection.rangeCount > 0) {
|
|
20412
|
+
const selectedText = selection.toString() || "code";
|
|
20413
|
+
execCommand("insertHTML", `<code>${selectedText}</code>`);
|
|
20414
|
+
}
|
|
20415
|
+
} else if (e.key === "Tab") {
|
|
20416
|
+
e.preventDefault();
|
|
20417
|
+
execCommand("insertHTML", " ");
|
|
20418
|
+
}
|
|
20419
|
+
}, [execCommand]);
|
|
20420
|
+
const handleSourceKeyDown = React20.useCallback((e) => {
|
|
20421
|
+
if (e.key === "Tab") {
|
|
20422
|
+
e.preventDefault();
|
|
20423
|
+
const textarea = e.currentTarget;
|
|
20424
|
+
const start = textarea.selectionStart;
|
|
20425
|
+
const end = textarea.selectionEnd;
|
|
20426
|
+
const newValue = content.substring(0, start) + " " + content.substring(end);
|
|
20427
|
+
onChange(newValue);
|
|
20428
|
+
requestAnimationFrame(() => {
|
|
20429
|
+
textarea.selectionStart = textarea.selectionEnd = start + 2;
|
|
20430
|
+
});
|
|
20431
|
+
}
|
|
20432
|
+
}, [content, onChange]);
|
|
20433
|
+
const toggleSourceMode = React20.useCallback(() => {
|
|
20434
|
+
if (isSourceMode) {
|
|
20435
|
+
setIsSourceMode(false);
|
|
20436
|
+
requestAnimationFrame(() => {
|
|
20437
|
+
if (editorRef.current) {
|
|
20438
|
+
const html2 = contentToHtml(content);
|
|
20439
|
+
editorRef.current.innerHTML = html2;
|
|
20440
|
+
lastMarkdownRef.current = content;
|
|
20441
|
+
}
|
|
20442
|
+
});
|
|
20443
|
+
} else {
|
|
20444
|
+
if (editorRef.current) {
|
|
20445
|
+
const markdown = htmlToMarkdown(editorRef.current);
|
|
20446
|
+
lastMarkdownRef.current = markdown;
|
|
20447
|
+
isInternalUpdate.current = true;
|
|
20448
|
+
onChange(markdown);
|
|
20449
|
+
}
|
|
20450
|
+
setIsSourceMode(true);
|
|
20451
|
+
}
|
|
20452
|
+
}, [isSourceMode, content, contentToHtml, onChange]);
|
|
20453
|
+
const toolbarGroups = React20.useMemo(() => [
|
|
20454
|
+
{
|
|
20455
|
+
items: [
|
|
20456
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-bold text-[11px]", children: "B" }), label: "\u52A0\u7C97 (\u2318B)", onClick: () => execCommand("bold") },
|
|
20457
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "italic text-[11px]", children: "I" }), label: "\u659C\u4F53 (\u2318I)", onClick: () => execCommand("italic") },
|
|
20458
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "line-through text-[11px]", children: "S" }), label: "\u5220\u9664\u7EBF", onClick: () => execCommand("strikeThrough") },
|
|
20459
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Code2, { size: 13 }), label: "\u884C\u5185\u4EE3\u7801 (\u2318E)", onClick: () => {
|
|
20460
|
+
const selection = window.getSelection();
|
|
20461
|
+
const text3 = selection?.toString() || "code";
|
|
20462
|
+
execCommand("insertHTML", `<code>${text3}</code>`);
|
|
20463
|
+
} }
|
|
20464
|
+
]
|
|
20465
|
+
},
|
|
20466
|
+
{
|
|
20467
|
+
items: [
|
|
20468
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] font-bold", children: "H1" }), label: "\u4E00\u7EA7\u6807\u9898", onClick: () => formatBlock("h1") },
|
|
20469
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] font-bold", children: "H2" }), label: "\u4E8C\u7EA7\u6807\u9898", onClick: () => formatBlock("h2") },
|
|
20470
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] font-bold", children: "H3" }), label: "\u4E09\u7EA7\u6807\u9898", onClick: () => formatBlock("h3") }
|
|
20471
|
+
]
|
|
20472
|
+
},
|
|
20473
|
+
{
|
|
20474
|
+
items: [
|
|
20475
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px]", children: "\u2022" }), label: "\u65E0\u5E8F\u5217\u8868", onClick: () => execCommand("insertUnorderedList") },
|
|
20476
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px]", children: "1." }), label: "\u6709\u5E8F\u5217\u8868", onClick: () => execCommand("insertOrderedList") },
|
|
20477
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px]", children: "\u275D" }), label: "\u5F15\u7528", onClick: () => formatBlock("blockquote") }
|
|
20478
|
+
]
|
|
20479
|
+
},
|
|
20480
|
+
{
|
|
20481
|
+
items: [
|
|
20482
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px]", children: "\u2014" }), label: "\u5206\u5272\u7EBF", onClick: insertHorizontalRule },
|
|
20483
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Globe, { size: 13 }), label: "\u94FE\u63A5", onClick: insertLink },
|
|
20484
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileImage, { size: 13 }), label: "\u56FE\u7247", onClick: insertImage },
|
|
20485
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Code2, { size: 13, className: "opacity-60" }), label: "\u4EE3\u7801\u5757", onClick: insertCodeBlock }
|
|
20486
|
+
]
|
|
20487
|
+
}
|
|
20488
|
+
], [execCommand, formatBlock, insertHorizontalRule, insertLink, insertImage, insertCodeBlock]);
|
|
20489
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "h-full flex flex-col bg-zinc-950 agent-sdk-light:bg-white", children: [
|
|
20490
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-0.5 px-3 py-1.5 border-b border-zinc-800/50 agent-sdk-light:border-zinc-200 bg-zinc-900/50 agent-sdk-light:bg-zinc-50 flex-shrink-0 overflow-x-auto", style: { scrollbarWidth: "none" }, children: [
|
|
20491
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 mr-2", children: [
|
|
20492
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, { size: 12, className: "text-[#d8ff00]" }),
|
|
20493
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] text-[#d8ff00] font-medium whitespace-nowrap", children: isSourceMode ? "Markdown \u6E90\u7801" : "\u5BCC\u6587\u672C\u7F16\u8F91" })
|
|
20494
|
+
] }),
|
|
20495
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-4 w-px bg-zinc-700/50 agent-sdk-light:bg-zinc-300 mx-1" }),
|
|
20496
|
+
!isSourceMode && toolbarGroups.map((group, groupIndex) => /* @__PURE__ */ jsxRuntime.jsxs(React20__namespace.default.Fragment, { children: [
|
|
20497
|
+
group.items.map((action, actionIndex) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
20498
|
+
"button",
|
|
20499
|
+
{
|
|
20500
|
+
onClick: action.onClick,
|
|
20501
|
+
className: "p-1.5 min-w-[28px] h-7 flex items-center justify-center text-zinc-400 agent-sdk-light:text-zinc-600 hover:text-zinc-100 agent-sdk-light:hover:text-zinc-900 hover:bg-zinc-700/50 agent-sdk-light:hover:bg-zinc-200 rounded transition-colors",
|
|
20502
|
+
title: action.label,
|
|
20503
|
+
children: action.icon
|
|
20504
|
+
},
|
|
20505
|
+
actionIndex
|
|
20506
|
+
)),
|
|
20507
|
+
groupIndex < toolbarGroups.length - 1 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-4 w-px bg-zinc-700/50 agent-sdk-light:bg-zinc-300 mx-0.5" })
|
|
20508
|
+
] }, groupIndex)),
|
|
20509
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-4 w-px bg-zinc-700/50 agent-sdk-light:bg-zinc-300 mx-1 ml-auto" }),
|
|
20510
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
20511
|
+
"button",
|
|
20512
|
+
{
|
|
20513
|
+
onClick: toggleSourceMode,
|
|
20514
|
+
className: cn2(
|
|
20515
|
+
"p-1.5 flex items-center gap-1 text-[11px] rounded transition-colors whitespace-nowrap",
|
|
20516
|
+
isSourceMode ? "bg-[#d8ff00]/10 text-[#d8ff00]" : "text-zinc-400 agent-sdk-light:text-zinc-600 hover:text-zinc-100 agent-sdk-light:hover:text-zinc-900 hover:bg-zinc-700/50 agent-sdk-light:hover:bg-zinc-200"
|
|
20517
|
+
),
|
|
20518
|
+
title: isSourceMode ? "\u5207\u6362\u5230\u5BCC\u6587\u672C\u6A21\u5F0F" : "\u5207\u6362\u5230\u6E90\u7801\u6A21\u5F0F",
|
|
20519
|
+
children: [
|
|
20520
|
+
isSourceMode ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Eye, { size: 13 }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Code2, { size: 13 }),
|
|
20521
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:inline", children: isSourceMode ? "\u5BCC\u6587\u672C" : "\u6E90\u7801" })
|
|
20522
|
+
]
|
|
20523
|
+
}
|
|
20524
|
+
)
|
|
20525
|
+
] }),
|
|
20526
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-h-0 overflow-hidden", children: isSourceMode ? (
|
|
20527
|
+
/* 源码编辑模式 */
|
|
20528
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20529
|
+
"textarea",
|
|
20530
|
+
{
|
|
20531
|
+
ref: textareaRef,
|
|
20532
|
+
value: content,
|
|
20533
|
+
onChange: (e) => onChange(e.target.value),
|
|
20534
|
+
onKeyDown: handleSourceKeyDown,
|
|
20535
|
+
className: "w-full h-full p-5 bg-zinc-950 agent-sdk-light:bg-white text-sm text-zinc-300 agent-sdk-light:text-zinc-800 leading-[1.8] resize-none focus:outline-none",
|
|
20536
|
+
style: { fontFamily: '"SF Mono", "Fira Code", "JetBrains Mono", Menlo, Monaco, monospace' },
|
|
20537
|
+
spellCheck: false,
|
|
20538
|
+
autoComplete: "off",
|
|
20539
|
+
autoCorrect: "off",
|
|
20540
|
+
autoCapitalize: "off",
|
|
20541
|
+
placeholder: "\u7F16\u5199 Markdown \u6E90\u7801..."
|
|
20542
|
+
}
|
|
20543
|
+
)
|
|
20544
|
+
) : (
|
|
20545
|
+
/* WYSIWYG 富文本编辑模式 */
|
|
20546
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20547
|
+
"div",
|
|
20548
|
+
{
|
|
20549
|
+
ref: editorRef,
|
|
20550
|
+
contentEditable: true,
|
|
20551
|
+
suppressContentEditableWarning: true,
|
|
20552
|
+
onInput: handleInput,
|
|
20553
|
+
onKeyDown: handleKeyDown,
|
|
20554
|
+
className: "w-full h-full p-5 overflow-auto bg-zinc-950 agent-sdk-light:bg-white text-sm text-zinc-300 agent-sdk-light:text-zinc-800 leading-[1.8] focus:outline-none prose prose-invert prose-zinc agent-sdk-light:prose prose-sm max-w-none\n [&_h1]:text-2xl [&_h1]:font-bold [&_h1]:text-zinc-100 [&_h1]:agent-sdk-light:text-zinc-900 [&_h1]:mb-4 [&_h1]:mt-6 [&_h1]:border-b [&_h1]:border-zinc-800/30 [&_h1]:agent-sdk-light:border-zinc-200 [&_h1]:pb-2\n [&_h2]:text-xl [&_h2]:font-bold [&_h2]:text-zinc-200 [&_h2]:agent-sdk-light:text-zinc-800 [&_h2]:mb-3 [&_h2]:mt-5\n [&_h3]:text-lg [&_h3]:font-semibold [&_h3]:text-zinc-200 [&_h3]:agent-sdk-light:text-zinc-800 [&_h3]:mb-2 [&_h3]:mt-4\n [&_p]:mb-3 [&_p]:leading-relaxed\n [&_strong]:text-zinc-100 [&_strong]:agent-sdk-light:text-zinc-900 [&_strong]:font-semibold\n [&_em]:text-zinc-300 [&_em]:agent-sdk-light:text-zinc-700\n [&_code]:bg-zinc-800/60 [&_code]:agent-sdk-light:bg-zinc-100 [&_code]:text-[#d8ff00] [&_code]:agent-sdk-light:text-pink-600 [&_code]:px-1.5 [&_code]:py-0.5 [&_code]:rounded [&_code]:text-[13px] [&_code]:font-mono\n [&_pre]:bg-zinc-900/80 [&_pre]:agent-sdk-light:bg-zinc-50 [&_pre]:border [&_pre]:border-zinc-800/50 [&_pre]:agent-sdk-light:border-zinc-200 [&_pre]:rounded-lg [&_pre]:p-4 [&_pre]:my-3 [&_pre]:overflow-x-auto\n [&_pre_code]:bg-transparent [&_pre_code]:p-0 [&_pre_code]:text-zinc-300 [&_pre_code]:agent-sdk-light:text-zinc-800\n [&_blockquote]:border-l-3 [&_blockquote]:border-[#d8ff00]/40 [&_blockquote]:pl-4 [&_blockquote]:my-3 [&_blockquote]:text-zinc-400 [&_blockquote]:agent-sdk-light:text-zinc-600 [&_blockquote]:italic\n [&_ul]:list-disc [&_ul]:pl-6 [&_ul]:my-2\n [&_ol]:list-decimal [&_ol]:pl-6 [&_ol]:my-2\n [&_li]:mb-1\n [&_a]:text-[#d8ff00] [&_a]:agent-sdk-light:text-blue-600 [&_a]:underline [&_a]:underline-offset-2\n [&_hr]:border-zinc-700/50 [&_hr]:agent-sdk-light:border-zinc-300 [&_hr]:my-6\n [&_img]:max-w-full [&_img]:rounded-lg [&_img]:my-3\n [&_table]:w-full [&_table]:border-collapse [&_table]:my-3\n [&_th]:border [&_th]:border-zinc-700/50 [&_th]:agent-sdk-light:border-zinc-300 [&_th]:px-3 [&_th]:py-2 [&_th]:bg-zinc-800/30 [&_th]:agent-sdk-light:bg-zinc-100 [&_th]:text-left [&_th]:font-medium\n [&_td]:border [&_td]:border-zinc-700/50 [&_td]:agent-sdk-light:border-zinc-300 [&_td]:px-3 [&_td]:py-2",
|
|
20555
|
+
"data-placeholder": "\u5F00\u59CB\u7F16\u5199\u5185\u5BB9..."
|
|
20556
|
+
}
|
|
20557
|
+
)
|
|
20558
|
+
) })
|
|
20559
|
+
] });
|
|
20560
|
+
});
|
|
20561
|
+
var ArtifactThumbnail = React20.memo(function ArtifactThumbnail2({
|
|
20562
|
+
artifact,
|
|
20563
|
+
config
|
|
20564
|
+
}) {
|
|
20565
|
+
const typeConf = artifactTypeConfig[artifact.type] || artifactTypeConfig.text;
|
|
20566
|
+
const TypeIcon = typeConf.icon;
|
|
20567
|
+
const isMedia = artifact.type === "image" || artifact.type === "video";
|
|
20568
|
+
const thumbnailUrl = useResolvedThumbnailUrl(
|
|
20569
|
+
artifact.currentContent,
|
|
20570
|
+
{
|
|
20571
|
+
fileId: artifact.metadata?.fileId,
|
|
20572
|
+
type: artifact.type,
|
|
20573
|
+
config,
|
|
20574
|
+
enabled: isMedia
|
|
20575
|
+
}
|
|
20576
|
+
);
|
|
20577
|
+
if (isMedia && thumbnailUrl) {
|
|
20578
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
20579
|
+
"img",
|
|
20580
|
+
{
|
|
20581
|
+
src: thumbnailUrl,
|
|
20582
|
+
alt: "",
|
|
20583
|
+
className: "w-6 h-6 rounded object-cover flex-shrink-0",
|
|
20584
|
+
loading: "lazy"
|
|
20585
|
+
}
|
|
20586
|
+
);
|
|
20587
|
+
}
|
|
20588
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn2("w-6 h-6 rounded flex items-center justify-center flex-shrink-0", typeConf.bgColor), children: /* @__PURE__ */ jsxRuntime.jsx(TypeIcon, { size: 12, className: typeConf.color }) });
|
|
20589
|
+
});
|
|
20590
|
+
var ArtifactTabs = React20.memo(function ArtifactTabs2({
|
|
20591
|
+
artifacts,
|
|
20592
|
+
activeId,
|
|
20593
|
+
onSwitch,
|
|
20594
|
+
onClose,
|
|
20595
|
+
onReorder,
|
|
20596
|
+
config
|
|
20597
|
+
}) {
|
|
20598
|
+
const scrollContainerRef = React20.useRef(null);
|
|
20599
|
+
const [canScrollLeft, setCanScrollLeft] = React20.useState(false);
|
|
20600
|
+
const [canScrollRight, setCanScrollRight] = React20.useState(false);
|
|
20601
|
+
const [showAllPanel, setShowAllPanel] = React20.useState(false);
|
|
20602
|
+
const allPanelRef = React20.useRef(null);
|
|
20603
|
+
const [dragState, setDragState] = React20.useState({ draggingId: null, dragOverId: null, dragStartX: 0, isDragging: false });
|
|
20604
|
+
const checkScrollState = React20.useCallback(() => {
|
|
20605
|
+
const container = scrollContainerRef.current;
|
|
20606
|
+
if (!container) return;
|
|
20607
|
+
setCanScrollLeft(container.scrollLeft > 2);
|
|
20608
|
+
setCanScrollRight(container.scrollLeft < container.scrollWidth - container.clientWidth - 2);
|
|
20609
|
+
}, []);
|
|
20610
|
+
React20.useEffect(() => {
|
|
20611
|
+
checkScrollState();
|
|
20612
|
+
const container = scrollContainerRef.current;
|
|
20613
|
+
if (!container) return;
|
|
20614
|
+
container.addEventListener("scroll", checkScrollState, { passive: true });
|
|
20615
|
+
const resizeObserver = new ResizeObserver(checkScrollState);
|
|
20616
|
+
resizeObserver.observe(container);
|
|
20617
|
+
return () => {
|
|
20618
|
+
container.removeEventListener("scroll", checkScrollState);
|
|
20619
|
+
resizeObserver.disconnect();
|
|
20620
|
+
};
|
|
20621
|
+
}, [checkScrollState, artifacts.length]);
|
|
20622
|
+
React20.useEffect(() => {
|
|
20623
|
+
if (!showAllPanel) return;
|
|
20624
|
+
const handleClickOutside = (e) => {
|
|
20625
|
+
if (allPanelRef.current && !allPanelRef.current.contains(e.target)) {
|
|
20626
|
+
setShowAllPanel(false);
|
|
20627
|
+
}
|
|
20628
|
+
};
|
|
20629
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
20630
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
20631
|
+
}, [showAllPanel]);
|
|
20632
|
+
const scrollBy = React20.useCallback((direction) => {
|
|
20633
|
+
const container = scrollContainerRef.current;
|
|
20634
|
+
if (!container) return;
|
|
20635
|
+
const scrollAmount = 200;
|
|
20636
|
+
container.scrollBy({
|
|
20637
|
+
left: direction === "left" ? -scrollAmount : scrollAmount,
|
|
20638
|
+
behavior: "smooth"
|
|
20639
|
+
});
|
|
20640
|
+
}, []);
|
|
20641
|
+
const handleDragStart = React20.useCallback((e, artifactId) => {
|
|
20642
|
+
e.dataTransfer.effectAllowed = "move";
|
|
20643
|
+
e.dataTransfer.setData("text/plain", artifactId);
|
|
20644
|
+
setDragState((prev) => ({ ...prev, draggingId: artifactId, dragStartX: e.clientX, isDragging: true }));
|
|
20645
|
+
}, []);
|
|
20646
|
+
const handleDragOver = React20.useCallback((e, artifactId) => {
|
|
20647
|
+
e.preventDefault();
|
|
20648
|
+
e.dataTransfer.dropEffect = "move";
|
|
20649
|
+
setDragState((prev) => ({ ...prev, dragOverId: artifactId }));
|
|
20650
|
+
}, []);
|
|
20651
|
+
const handleDragEnd = React20.useCallback(() => {
|
|
20652
|
+
setDragState({ draggingId: null, dragOverId: null, dragStartX: 0, isDragging: false });
|
|
20653
|
+
}, []);
|
|
20654
|
+
const handleDrop = React20.useCallback((e, targetId) => {
|
|
20655
|
+
e.preventDefault();
|
|
20656
|
+
const sourceId = e.dataTransfer.getData("text/plain");
|
|
20657
|
+
if (!sourceId || sourceId === targetId || !onReorder) {
|
|
20658
|
+
handleDragEnd();
|
|
20659
|
+
return;
|
|
20660
|
+
}
|
|
20661
|
+
const fromIndex = artifacts.findIndex((a) => a.id === sourceId);
|
|
20662
|
+
const toIndex = artifacts.findIndex((a) => a.id === targetId);
|
|
20663
|
+
if (fromIndex !== -1 && toIndex !== -1 && fromIndex !== toIndex) {
|
|
20664
|
+
onReorder(fromIndex, toIndex);
|
|
20665
|
+
}
|
|
20666
|
+
handleDragEnd();
|
|
20667
|
+
}, [artifacts, onReorder, handleDragEnd]);
|
|
20668
|
+
const handleCloseTab = React20.useCallback((e, artifactId) => {
|
|
20669
|
+
e.stopPropagation();
|
|
20670
|
+
if (!onClose) return;
|
|
20671
|
+
if (artifactId === activeId && artifacts.length > 1) {
|
|
20672
|
+
const currentIndex = artifacts.findIndex((a) => a.id === artifactId);
|
|
20673
|
+
const nextIndex = currentIndex < artifacts.length - 1 ? currentIndex + 1 : currentIndex - 1;
|
|
20674
|
+
if (nextIndex >= 0 && nextIndex < artifacts.length) {
|
|
20675
|
+
onSwitch(artifacts[nextIndex].id);
|
|
20676
|
+
}
|
|
20677
|
+
}
|
|
20678
|
+
onClose(artifactId);
|
|
20679
|
+
}, [onClose, activeId, artifacts, onSwitch]);
|
|
20680
|
+
if (artifacts.length <= 1) return null;
|
|
20681
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center border-b border-zinc-800/50 agent-sdk-light:border-zinc-200 bg-zinc-950/50 agent-sdk-light:bg-zinc-100 flex-shrink-0 relative", children: [
|
|
20682
|
+
canScrollLeft && /* @__PURE__ */ jsxRuntime.jsx(
|
|
20683
|
+
"button",
|
|
20684
|
+
{
|
|
20685
|
+
onClick: () => scrollBy("left"),
|
|
20686
|
+
className: "flex-shrink-0 p-1 text-zinc-500 hover:text-zinc-300 hover:bg-zinc-800/50 transition-colors z-10",
|
|
20687
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeft, { size: 14 })
|
|
20688
|
+
}
|
|
20689
|
+
),
|
|
20690
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20691
|
+
"div",
|
|
20692
|
+
{
|
|
20693
|
+
ref: scrollContainerRef,
|
|
20694
|
+
className: "flex items-center gap-0.5 px-1 py-1 overflow-x-auto flex-1 min-w-0",
|
|
20695
|
+
style: { scrollbarWidth: "none", msOverflowStyle: "none" },
|
|
20696
|
+
children: artifacts.map((artifact) => {
|
|
20697
|
+
const typeConf = artifactTypeConfig[artifact.type] || artifactTypeConfig.text;
|
|
20698
|
+
const isActive = artifact.id === activeId;
|
|
20699
|
+
const isDragging = dragState.draggingId === artifact.id;
|
|
20700
|
+
const isDragOver = dragState.dragOverId === artifact.id && dragState.draggingId !== artifact.id;
|
|
20701
|
+
const TypeIcon = typeConf.icon;
|
|
20702
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
20703
|
+
"div",
|
|
20704
|
+
{
|
|
20705
|
+
draggable: !!onReorder,
|
|
20706
|
+
onDragStart: (e) => handleDragStart(e, artifact.id),
|
|
20707
|
+
onDragOver: (e) => handleDragOver(e, artifact.id),
|
|
20708
|
+
onDragEnd: handleDragEnd,
|
|
20709
|
+
onDrop: (e) => handleDrop(e, artifact.id),
|
|
20710
|
+
onClick: () => onSwitch(artifact.id),
|
|
20711
|
+
className: cn2(
|
|
20712
|
+
"group/tab flex items-center gap-1 pl-2.5 pr-1 py-1 text-xs rounded-md transition-all whitespace-nowrap flex-shrink-0 cursor-pointer select-none",
|
|
20713
|
+
isActive ? "bg-zinc-800 text-zinc-100 agent-sdk-light:bg-zinc-200 agent-sdk-light:text-zinc-900" : "text-zinc-500 agent-sdk-light:text-zinc-600 hover:text-zinc-300 agent-sdk-light:hover:text-zinc-900 hover:bg-zinc-800/50 agent-sdk-light:hover:bg-zinc-200/50",
|
|
20714
|
+
isDragging && "opacity-40",
|
|
20715
|
+
isDragOver && "ring-1 ring-[#d8ff00]/50",
|
|
20716
|
+
onReorder && "cursor-grab active:cursor-grabbing"
|
|
20717
|
+
),
|
|
20718
|
+
title: artifact.title,
|
|
20719
|
+
children: [
|
|
20720
|
+
/* @__PURE__ */ jsxRuntime.jsx(TypeIcon, { size: 12, className: cn2("flex-shrink-0", isActive ? typeConf.color : "") }),
|
|
20721
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "max-w-[120px] truncate", children: artifact.title }),
|
|
20722
|
+
onClose && /* @__PURE__ */ jsxRuntime.jsx(
|
|
20723
|
+
"button",
|
|
20724
|
+
{
|
|
20725
|
+
onClick: (e) => handleCloseTab(e, artifact.id),
|
|
20726
|
+
className: cn2(
|
|
20727
|
+
"ml-0.5 p-0.5 rounded transition-colors flex-shrink-0",
|
|
20728
|
+
isActive ? "text-zinc-400 hover:text-zinc-100 hover:bg-zinc-700" : "text-transparent group-hover/tab:text-zinc-500 hover:!text-zinc-300 hover:!bg-zinc-700"
|
|
20729
|
+
),
|
|
20730
|
+
title: "\u5173\u95ED",
|
|
20731
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 10 })
|
|
20732
|
+
}
|
|
20733
|
+
)
|
|
20734
|
+
]
|
|
20735
|
+
},
|
|
20736
|
+
artifact.id
|
|
20737
|
+
);
|
|
20738
|
+
})
|
|
20739
|
+
}
|
|
20740
|
+
),
|
|
20741
|
+
canScrollRight && /* @__PURE__ */ jsxRuntime.jsx(
|
|
20742
|
+
"button",
|
|
20743
|
+
{
|
|
20744
|
+
onClick: () => scrollBy("right"),
|
|
20745
|
+
className: "flex-shrink-0 p-1 text-zinc-500 hover:text-zinc-300 hover:bg-zinc-800/50 transition-colors z-10",
|
|
20746
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { size: 14 })
|
|
20747
|
+
}
|
|
20748
|
+
),
|
|
20749
|
+
artifacts.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex-shrink-0", ref: allPanelRef, children: [
|
|
20750
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20751
|
+
"button",
|
|
20752
|
+
{
|
|
20753
|
+
onClick: () => setShowAllPanel((prev) => !prev),
|
|
20754
|
+
className: cn2(
|
|
20755
|
+
"p-1.5 mr-1 text-zinc-500 hover:text-zinc-300 hover:bg-zinc-800/50 rounded transition-colors",
|
|
20756
|
+
showAllPanel && "bg-zinc-800 text-zinc-300"
|
|
20757
|
+
),
|
|
20758
|
+
title: "\u5168\u90E8\u4EA7\u7269",
|
|
20759
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.LayoutGrid, { size: 14 })
|
|
20760
|
+
}
|
|
20761
|
+
),
|
|
20762
|
+
showAllPanel && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute right-0 top-full mt-1 z-50 w-72 max-h-80 overflow-y-auto bg-zinc-900 agent-sdk-light:bg-white border border-zinc-700 agent-sdk-light:border-zinc-300 rounded-lg shadow-xl", children: [
|
|
20763
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-2 border-b border-zinc-800 agent-sdk-light:border-zinc-200", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs font-medium text-zinc-400 agent-sdk-light:text-zinc-600", children: [
|
|
20764
|
+
"\u5168\u90E8\u4EA7\u7269 (",
|
|
20765
|
+
artifacts.length,
|
|
20766
|
+
")"
|
|
20767
|
+
] }) }),
|
|
20768
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-1.5 grid grid-cols-1 gap-0.5", children: artifacts.map((artifact) => {
|
|
20769
|
+
const typeConf = artifactTypeConfig[artifact.type] || artifactTypeConfig.text;
|
|
20770
|
+
const isActive = artifact.id === activeId;
|
|
20771
|
+
typeConf.icon;
|
|
20772
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
20773
|
+
"button",
|
|
20774
|
+
{
|
|
20775
|
+
onClick: () => {
|
|
20776
|
+
onSwitch(artifact.id);
|
|
20777
|
+
setShowAllPanel(false);
|
|
20778
|
+
},
|
|
20779
|
+
className: cn2(
|
|
20780
|
+
"flex items-center gap-2.5 px-2.5 py-2 text-xs rounded-md transition-all w-full text-left",
|
|
20781
|
+
isActive ? "bg-zinc-800 text-zinc-100 agent-sdk-light:bg-zinc-100 agent-sdk-light:text-zinc-900" : "text-zinc-400 agent-sdk-light:text-zinc-600 hover:text-zinc-200 agent-sdk-light:hover:text-zinc-900 hover:bg-zinc-800/50 agent-sdk-light:hover:bg-zinc-100"
|
|
20782
|
+
),
|
|
20783
|
+
children: [
|
|
20784
|
+
/* @__PURE__ */ jsxRuntime.jsx(ArtifactThumbnail, { artifact, config }),
|
|
20785
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
20786
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "truncate font-medium", children: artifact.title }),
|
|
20787
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-[10px] text-zinc-600 agent-sdk-light:text-zinc-500 mt-0.5", children: [
|
|
20788
|
+
typeConf.label,
|
|
20789
|
+
artifact.language && artifact.language !== artifact.type && ` \u2022 ${artifact.language}`
|
|
20790
|
+
] })
|
|
20791
|
+
] }),
|
|
20792
|
+
onClose && /* @__PURE__ */ jsxRuntime.jsx(
|
|
20793
|
+
"button",
|
|
20794
|
+
{
|
|
20795
|
+
onClick: (e) => {
|
|
20796
|
+
e.stopPropagation();
|
|
20797
|
+
handleCloseTab(e, artifact.id);
|
|
20798
|
+
},
|
|
20799
|
+
className: "p-1 text-zinc-600 hover:text-zinc-300 hover:bg-zinc-700 rounded transition-colors flex-shrink-0",
|
|
20800
|
+
title: "\u5173\u95ED",
|
|
20801
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 12 })
|
|
20802
|
+
}
|
|
20803
|
+
)
|
|
20804
|
+
]
|
|
20805
|
+
},
|
|
20806
|
+
artifact.id
|
|
20807
|
+
);
|
|
20808
|
+
}) })
|
|
20809
|
+
] })
|
|
20810
|
+
] })
|
|
20811
|
+
] });
|
|
20812
|
+
});
|
|
18821
20813
|
var ArtifactViewer = React20.memo(function ArtifactViewer2({
|
|
18822
20814
|
artifact,
|
|
18823
20815
|
isOpen,
|
|
@@ -18826,41 +20818,127 @@ var ArtifactViewer = React20.memo(function ArtifactViewer2({
|
|
|
18826
20818
|
defaultView = "preview",
|
|
18827
20819
|
isFullscreen,
|
|
18828
20820
|
onFullscreenToggle,
|
|
18829
|
-
embedded = false
|
|
20821
|
+
embedded = false,
|
|
20822
|
+
artifacts = [],
|
|
20823
|
+
activeArtifactId,
|
|
20824
|
+
onSwitchArtifact,
|
|
20825
|
+
onCloseArtifact,
|
|
20826
|
+
onReorderArtifacts,
|
|
20827
|
+
onContentChange,
|
|
20828
|
+
onSave
|
|
18830
20829
|
}) {
|
|
18831
20830
|
const [viewMode, setViewMode] = React20.useState(defaultView);
|
|
20831
|
+
const [isEditing, setIsEditing] = React20.useState(false);
|
|
20832
|
+
const [editContent, setEditContent] = React20.useState("");
|
|
20833
|
+
const [undoStack, setUndoStack] = React20.useState([]);
|
|
20834
|
+
const [redoStack, setRedoStack] = React20.useState([]);
|
|
18832
20835
|
React20.useEffect(() => {
|
|
18833
20836
|
if (artifact) {
|
|
18834
|
-
if (artifact.type === "html" || artifact.type === "markdown") {
|
|
20837
|
+
if (artifact.type === "html" || artifact.type === "markdown" || artifact.type === "svg") {
|
|
18835
20838
|
setViewMode("preview");
|
|
18836
20839
|
} else {
|
|
18837
20840
|
setViewMode("code");
|
|
18838
20841
|
}
|
|
20842
|
+
setIsEditing(false);
|
|
20843
|
+
setEditContent(artifact.content);
|
|
20844
|
+
setUndoStack([]);
|
|
20845
|
+
setRedoStack([]);
|
|
18839
20846
|
}
|
|
18840
20847
|
}, [artifact?.id]);
|
|
20848
|
+
React20.useEffect(() => {
|
|
20849
|
+
if (artifact && !isEditing) {
|
|
20850
|
+
setEditContent(artifact.content);
|
|
20851
|
+
}
|
|
20852
|
+
}, [artifact?.content, isEditing]);
|
|
18841
20853
|
if (!artifact) return null;
|
|
18842
|
-
const typeConfig = artifactTypeConfig[artifact.type];
|
|
18843
|
-
const canPreview = artifact.type === "html" || artifact.type === "markdown";
|
|
20854
|
+
const typeConfig = artifactTypeConfig[artifact.type] || artifactTypeConfig.text;
|
|
20855
|
+
const canPreview = artifact.type === "html" || artifact.type === "markdown" || artifact.type === "svg";
|
|
20856
|
+
const canEdit = artifact.type !== "image" && artifact.type !== "video";
|
|
20857
|
+
const handleStartEdit = () => {
|
|
20858
|
+
setEditContent(artifact.content);
|
|
20859
|
+
setUndoStack([artifact.content]);
|
|
20860
|
+
setRedoStack([]);
|
|
20861
|
+
setIsEditing(true);
|
|
20862
|
+
setViewMode("code");
|
|
20863
|
+
};
|
|
20864
|
+
const handleEditChange = (newContent) => {
|
|
20865
|
+
setUndoStack((prev) => [...prev, editContent]);
|
|
20866
|
+
setRedoStack([]);
|
|
20867
|
+
setEditContent(newContent);
|
|
20868
|
+
onContentChange?.(newContent);
|
|
20869
|
+
};
|
|
20870
|
+
const handleUndo = () => {
|
|
20871
|
+
if (undoStack.length === 0) return;
|
|
20872
|
+
const previous2 = undoStack[undoStack.length - 1];
|
|
20873
|
+
setUndoStack((prev) => prev.slice(0, -1));
|
|
20874
|
+
setRedoStack((prev) => [...prev, editContent]);
|
|
20875
|
+
setEditContent(previous2);
|
|
20876
|
+
onContentChange?.(previous2);
|
|
20877
|
+
};
|
|
20878
|
+
const handleRedo = () => {
|
|
20879
|
+
if (redoStack.length === 0) return;
|
|
20880
|
+
const next = redoStack[redoStack.length - 1];
|
|
20881
|
+
setRedoStack((prev) => prev.slice(0, -1));
|
|
20882
|
+
setUndoStack((prev) => [...prev, editContent]);
|
|
20883
|
+
setEditContent(next);
|
|
20884
|
+
onContentChange?.(next);
|
|
20885
|
+
};
|
|
20886
|
+
const handleSave = () => {
|
|
20887
|
+
onSave?.(artifact.id, editContent);
|
|
20888
|
+
setIsEditing(false);
|
|
20889
|
+
};
|
|
20890
|
+
const handleCancelEdit = () => {
|
|
20891
|
+
setEditContent(artifact.content);
|
|
20892
|
+
setIsEditing(false);
|
|
20893
|
+
};
|
|
20894
|
+
const displayContent = isEditing ? editContent : artifact.content;
|
|
18844
20895
|
const renderContent = () => {
|
|
20896
|
+
if (isEditing) {
|
|
20897
|
+
if (artifact.type === "markdown") {
|
|
20898
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
20899
|
+
MarkdownEditor,
|
|
20900
|
+
{
|
|
20901
|
+
content: editContent,
|
|
20902
|
+
onChange: handleEditChange,
|
|
20903
|
+
config
|
|
20904
|
+
}
|
|
20905
|
+
);
|
|
20906
|
+
}
|
|
20907
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
20908
|
+
CodeEditor,
|
|
20909
|
+
{
|
|
20910
|
+
code: editContent,
|
|
20911
|
+
language: artifact.language || artifact.type,
|
|
20912
|
+
onChange: handleEditChange
|
|
20913
|
+
}
|
|
20914
|
+
);
|
|
20915
|
+
}
|
|
20916
|
+
if (artifact.type === "image") {
|
|
20917
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ImageArtifactPreview, { content: displayContent, metadata: artifact.metadata, config });
|
|
20918
|
+
}
|
|
20919
|
+
if (artifact.type === "video") {
|
|
20920
|
+
return /* @__PURE__ */ jsxRuntime.jsx(VideoArtifactPreview, { content: displayContent, metadata: artifact.metadata, config });
|
|
20921
|
+
}
|
|
18845
20922
|
if (viewMode === "code" || !canPreview) {
|
|
18846
20923
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
18847
20924
|
CodeBlock3,
|
|
18848
20925
|
{
|
|
18849
|
-
code:
|
|
20926
|
+
code: displayContent,
|
|
18850
20927
|
language: artifact.language || artifact.type
|
|
18851
20928
|
}
|
|
18852
20929
|
);
|
|
18853
20930
|
}
|
|
18854
20931
|
switch (artifact.type) {
|
|
18855
20932
|
case "html":
|
|
18856
|
-
|
|
20933
|
+
case "svg":
|
|
20934
|
+
return /* @__PURE__ */ jsxRuntime.jsx(HtmlPreview3, { content: displayContent });
|
|
18857
20935
|
case "markdown":
|
|
18858
|
-
return /* @__PURE__ */ jsxRuntime.jsx(MarkdownPreview, { content:
|
|
20936
|
+
return /* @__PURE__ */ jsxRuntime.jsx(MarkdownPreview, { content: displayContent, config });
|
|
18859
20937
|
default:
|
|
18860
20938
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
18861
20939
|
CodeBlock3,
|
|
18862
20940
|
{
|
|
18863
|
-
code:
|
|
20941
|
+
code: displayContent,
|
|
18864
20942
|
language: artifact.language || artifact.type
|
|
18865
20943
|
}
|
|
18866
20944
|
);
|
|
@@ -18883,26 +20961,79 @@ var ArtifactViewer = React20.memo(function ArtifactViewer2({
|
|
|
18883
20961
|
] })
|
|
18884
20962
|
] }),
|
|
18885
20963
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
18886
|
-
|
|
18887
|
-
|
|
18888
|
-
|
|
18889
|
-
|
|
18890
|
-
|
|
18891
|
-
|
|
18892
|
-
|
|
18893
|
-
|
|
18894
|
-
|
|
18895
|
-
|
|
18896
|
-
|
|
18897
|
-
|
|
18898
|
-
|
|
18899
|
-
|
|
18900
|
-
|
|
18901
|
-
|
|
18902
|
-
|
|
18903
|
-
|
|
18904
|
-
|
|
18905
|
-
|
|
20964
|
+
isEditing ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
20965
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20966
|
+
"button",
|
|
20967
|
+
{
|
|
20968
|
+
onClick: handleUndo,
|
|
20969
|
+
disabled: undoStack.length === 0,
|
|
20970
|
+
className: "p-1.5 text-zinc-500 hover:text-zinc-300 hover:bg-zinc-800 rounded-lg transition-colors disabled:opacity-30 disabled:cursor-not-allowed",
|
|
20971
|
+
title: "\u64A4\u9500",
|
|
20972
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Undo2, { size: 14 })
|
|
20973
|
+
}
|
|
20974
|
+
),
|
|
20975
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20976
|
+
"button",
|
|
20977
|
+
{
|
|
20978
|
+
onClick: handleRedo,
|
|
20979
|
+
disabled: redoStack.length === 0,
|
|
20980
|
+
className: "p-1.5 text-zinc-500 hover:text-zinc-300 hover:bg-zinc-800 rounded-lg transition-colors disabled:opacity-30 disabled:cursor-not-allowed",
|
|
20981
|
+
title: "\u91CD\u505A",
|
|
20982
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Redo2, { size: 14 })
|
|
20983
|
+
}
|
|
20984
|
+
),
|
|
20985
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
20986
|
+
"button",
|
|
20987
|
+
{
|
|
20988
|
+
onClick: handleSave,
|
|
20989
|
+
className: "flex items-center gap-1 px-2.5 py-1 text-xs bg-[#d8ff00] hover:bg-[#e5ff4d] text-black rounded-lg transition-colors font-medium",
|
|
20990
|
+
title: "\u4FDD\u5B58",
|
|
20991
|
+
children: [
|
|
20992
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Save, { size: 12 }),
|
|
20993
|
+
"\u4FDD\u5B58"
|
|
20994
|
+
]
|
|
20995
|
+
}
|
|
20996
|
+
),
|
|
20997
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20998
|
+
"button",
|
|
20999
|
+
{
|
|
21000
|
+
onClick: handleCancelEdit,
|
|
21001
|
+
className: "px-2.5 py-1 text-xs text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800 rounded-lg transition-colors",
|
|
21002
|
+
title: "\u53D6\u6D88\u7F16\u8F91",
|
|
21003
|
+
children: "\u53D6\u6D88"
|
|
21004
|
+
}
|
|
21005
|
+
)
|
|
21006
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
21007
|
+
canEdit && onContentChange && /* @__PURE__ */ jsxRuntime.jsx(
|
|
21008
|
+
"button",
|
|
21009
|
+
{
|
|
21010
|
+
onClick: handleStartEdit,
|
|
21011
|
+
className: "p-1.5 text-zinc-500 agent-sdk-light:text-zinc-600 hover:text-zinc-300 agent-sdk-light:hover:text-zinc-900 hover:bg-zinc-800 agent-sdk-light:hover:bg-zinc-200 rounded-lg transition-colors",
|
|
21012
|
+
title: "\u7F16\u8F91",
|
|
21013
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, { size: 14 })
|
|
21014
|
+
}
|
|
21015
|
+
),
|
|
21016
|
+
onFullscreenToggle && /* @__PURE__ */ jsxRuntime.jsx(
|
|
21017
|
+
"button",
|
|
21018
|
+
{
|
|
21019
|
+
onClick: onFullscreenToggle,
|
|
21020
|
+
className: "p-1.5 text-zinc-500 agent-sdk-light:text-zinc-600 hover:text-zinc-300 agent-sdk-light:hover:text-zinc-900 hover:bg-zinc-800 agent-sdk-light:hover:bg-zinc-200 rounded-lg transition-colors",
|
|
21021
|
+
title: isFullscreen ? "\u9000\u51FA\u5168\u5C4F" : "\u5168\u5C4F",
|
|
21022
|
+
children: isFullscreen ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Minimize2, { size: 14 }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Maximize2, { size: 14 })
|
|
21023
|
+
}
|
|
21024
|
+
),
|
|
21025
|
+
canPreview && /* @__PURE__ */ jsxRuntime.jsx(
|
|
21026
|
+
ViewTabs,
|
|
21027
|
+
{
|
|
21028
|
+
activeView: viewMode,
|
|
21029
|
+
onViewChange: (v) => setViewMode(v),
|
|
21030
|
+
views: [
|
|
21031
|
+
{ id: "preview", label: "Preview", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Eye, { size: 12 }) },
|
|
21032
|
+
{ id: "code", label: "Code", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Code2, { size: 12 }) }
|
|
21033
|
+
]
|
|
21034
|
+
}
|
|
21035
|
+
)
|
|
21036
|
+
] }),
|
|
18906
21037
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
18907
21038
|
"button",
|
|
18908
21039
|
{
|
|
@@ -18917,6 +21048,16 @@ var ArtifactViewer = React20.memo(function ArtifactViewer2({
|
|
|
18917
21048
|
)
|
|
18918
21049
|
] })
|
|
18919
21050
|
] }),
|
|
21051
|
+
onSwitchArtifact && /* @__PURE__ */ jsxRuntime.jsx(
|
|
21052
|
+
ArtifactTabs,
|
|
21053
|
+
{
|
|
21054
|
+
artifacts,
|
|
21055
|
+
activeId: activeArtifactId ?? artifact.id,
|
|
21056
|
+
onSwitch: onSwitchArtifact,
|
|
21057
|
+
onClose: onCloseArtifact,
|
|
21058
|
+
onReorder: onReorderArtifacts
|
|
21059
|
+
}
|
|
21060
|
+
),
|
|
18920
21061
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-hidden", children: renderContent() })
|
|
18921
21062
|
] });
|
|
18922
21063
|
}
|
|
@@ -18962,6 +21103,145 @@ var ArtifactViewer = React20.memo(function ArtifactViewer2({
|
|
|
18962
21103
|
}
|
|
18963
21104
|
);
|
|
18964
21105
|
});
|
|
21106
|
+
|
|
21107
|
+
// src/utils/artifactExtractor.ts
|
|
21108
|
+
function getMediaTypeFromParamType(paramType) {
|
|
21109
|
+
const upper = paramType?.toUpperCase();
|
|
21110
|
+
if (upper === "IMAGE") return "image";
|
|
21111
|
+
if (upper === "VIDEO") return "video";
|
|
21112
|
+
return null;
|
|
21113
|
+
}
|
|
21114
|
+
function inferMediaTypeFromUrl(url) {
|
|
21115
|
+
if (!url) return null;
|
|
21116
|
+
const lower = url.toLowerCase();
|
|
21117
|
+
if (/\.(jpg|jpeg|png|gif|webp|svg|bmp)(\?|#|$)/.test(lower)) return "image";
|
|
21118
|
+
if (/\.(mp4|mov|webm|avi|mkv|m4v)(\?|#|$)/.test(lower)) return "video";
|
|
21119
|
+
if (/\.(jpg|jpeg|png|gif|webp)/.test(lower)) return "image";
|
|
21120
|
+
if (/\.(mp4|mov|webm)/.test(lower)) return "video";
|
|
21121
|
+
return null;
|
|
21122
|
+
}
|
|
21123
|
+
function extractArtifactsFromToolCall(toolCall, sessionId, messageId) {
|
|
21124
|
+
const artifacts = [];
|
|
21125
|
+
if (!toolCall || toolCall.status?.toLowerCase() !== "completed") return artifacts;
|
|
21126
|
+
const result = toolCall.result;
|
|
21127
|
+
if (!result) return artifacts;
|
|
21128
|
+
const toolName = result?.relation?.toolName || toolCall.name || "AI Tool";
|
|
21129
|
+
const args = toolCall.arguments || {};
|
|
21130
|
+
if (result.works && Array.isArray(result.works)) {
|
|
21131
|
+
result.works.forEach((work, index) => {
|
|
21132
|
+
const paramType = work.customResponse?.paramType;
|
|
21133
|
+
const fileId = work.fileId;
|
|
21134
|
+
const fileUrl = work.fileUrl || work.customResponse?.url;
|
|
21135
|
+
if (!fileId && !fileUrl) return;
|
|
21136
|
+
const mediaType = getMediaTypeFromParamType(paramType) || (fileUrl ? inferMediaTypeFromUrl(fileUrl) : null) || (fileId ? inferMediaTypeFromUrl(fileId) : null);
|
|
21137
|
+
if (!mediaType) return;
|
|
21138
|
+
const artifactId = work.publicId || `media-${toolCall.id}-${index}`;
|
|
21139
|
+
artifacts.push({
|
|
21140
|
+
id: artifactId,
|
|
21141
|
+
sessionId,
|
|
21142
|
+
type: mediaType,
|
|
21143
|
+
title: `${toolName} #${index + 1}`,
|
|
21144
|
+
// 优先存 fileId,resolveAssetForDisplay 会将其转换为可用 URL
|
|
21145
|
+
currentContent: fileId || fileUrl,
|
|
21146
|
+
version: 1,
|
|
21147
|
+
source: "tool",
|
|
21148
|
+
sourceId: toolCall.id,
|
|
21149
|
+
metadata: {
|
|
21150
|
+
toolName,
|
|
21151
|
+
generationParams: args,
|
|
21152
|
+
messageId,
|
|
21153
|
+
workflowCode: result.workflowCode,
|
|
21154
|
+
taskId: result.taskId,
|
|
21155
|
+
fileId: work.fileId,
|
|
21156
|
+
fileUrl: work.fileUrl
|
|
21157
|
+
},
|
|
21158
|
+
gmtCreate: (/* @__PURE__ */ new Date()).toISOString(),
|
|
21159
|
+
gmtModified: (/* @__PURE__ */ new Date()).toISOString()
|
|
21160
|
+
});
|
|
21161
|
+
});
|
|
21162
|
+
}
|
|
21163
|
+
if (artifacts.length === 0 && result.outputs?.images) {
|
|
21164
|
+
const imgUrl = typeof result.outputs.images === "string" ? result.outputs.images : null;
|
|
21165
|
+
if (imgUrl) {
|
|
21166
|
+
artifacts.push({
|
|
21167
|
+
id: `media-${toolCall.id}-output`,
|
|
21168
|
+
sessionId,
|
|
21169
|
+
type: "image",
|
|
21170
|
+
title: `${toolName}`,
|
|
21171
|
+
currentContent: imgUrl,
|
|
21172
|
+
version: 1,
|
|
21173
|
+
source: "tool",
|
|
21174
|
+
sourceId: toolCall.id,
|
|
21175
|
+
metadata: {
|
|
21176
|
+
toolName,
|
|
21177
|
+
generationParams: args,
|
|
21178
|
+
messageId
|
|
21179
|
+
},
|
|
21180
|
+
gmtCreate: (/* @__PURE__ */ new Date()).toISOString(),
|
|
21181
|
+
gmtModified: (/* @__PURE__ */ new Date()).toISOString()
|
|
21182
|
+
});
|
|
21183
|
+
}
|
|
21184
|
+
}
|
|
21185
|
+
if (result.works && Array.isArray(result.works)) {
|
|
21186
|
+
result.works.forEach((work, index) => {
|
|
21187
|
+
if (work.customResponse?.value) {
|
|
21188
|
+
const parsed = detectContentType(work.customResponse.value);
|
|
21189
|
+
if (parsed.content && parsed.type !== "text") {
|
|
21190
|
+
artifacts.push({
|
|
21191
|
+
id: `content-${toolCall.id}-${index}`,
|
|
21192
|
+
sessionId,
|
|
21193
|
+
type: parsed.type,
|
|
21194
|
+
title: parsed.title || `${toolName} - ${parsed.type.toUpperCase()}`,
|
|
21195
|
+
currentContent: parsed.content,
|
|
21196
|
+
language: parsed.language,
|
|
21197
|
+
version: 1,
|
|
21198
|
+
source: "tool",
|
|
21199
|
+
sourceId: toolCall.id,
|
|
21200
|
+
metadata: {
|
|
21201
|
+
toolName,
|
|
21202
|
+
messageId
|
|
21203
|
+
},
|
|
21204
|
+
gmtCreate: (/* @__PURE__ */ new Date()).toISOString(),
|
|
21205
|
+
gmtModified: (/* @__PURE__ */ new Date()).toISOString()
|
|
21206
|
+
});
|
|
21207
|
+
}
|
|
21208
|
+
}
|
|
21209
|
+
});
|
|
21210
|
+
}
|
|
21211
|
+
return artifacts;
|
|
21212
|
+
}
|
|
21213
|
+
function extractArtifactsFromMessages(messages, sessionId) {
|
|
21214
|
+
const allArtifacts = [];
|
|
21215
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
21216
|
+
for (const message of messages) {
|
|
21217
|
+
if (message.role !== "assistant") continue;
|
|
21218
|
+
const toolCalls = message.extraData?.tool_calls || [];
|
|
21219
|
+
for (const tc of toolCalls) {
|
|
21220
|
+
const extracted = extractArtifactsFromToolCall(tc, sessionId, message.messageId);
|
|
21221
|
+
for (const artifact of extracted) {
|
|
21222
|
+
if (!seenIds.has(artifact.id)) {
|
|
21223
|
+
seenIds.add(artifact.id);
|
|
21224
|
+
allArtifacts.push(artifact);
|
|
21225
|
+
}
|
|
21226
|
+
}
|
|
21227
|
+
}
|
|
21228
|
+
const thoughts = message.extraData?.thoughts || message.thoughts || [];
|
|
21229
|
+
for (const thought of thoughts) {
|
|
21230
|
+
if (thought.toolCalls) {
|
|
21231
|
+
for (const tc of thought.toolCalls) {
|
|
21232
|
+
const extracted = extractArtifactsFromToolCall(tc, sessionId, message.messageId);
|
|
21233
|
+
for (const artifact of extracted) {
|
|
21234
|
+
if (!seenIds.has(artifact.id)) {
|
|
21235
|
+
seenIds.add(artifact.id);
|
|
21236
|
+
allArtifacts.push(artifact);
|
|
21237
|
+
}
|
|
21238
|
+
}
|
|
21239
|
+
}
|
|
21240
|
+
}
|
|
21241
|
+
}
|
|
21242
|
+
}
|
|
21243
|
+
return allArtifacts;
|
|
21244
|
+
}
|
|
18965
21245
|
var Field = ({ label, value }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-3 text-xs text-zinc-400", children: [
|
|
18966
21246
|
/* @__PURE__ */ jsxRuntime.jsx("span", { children: label }),
|
|
18967
21247
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-zinc-200 truncate max-w-[60%]", children: value ?? "-" })
|
|
@@ -19293,7 +21573,9 @@ function ChatInputArea({
|
|
|
19293
21573
|
onSend,
|
|
19294
21574
|
onStop,
|
|
19295
21575
|
isStreaming,
|
|
19296
|
-
config
|
|
21576
|
+
config,
|
|
21577
|
+
activeArtifact,
|
|
21578
|
+
onDetachArtifact
|
|
19297
21579
|
}) {
|
|
19298
21580
|
const textareaRef = React20.useRef(null);
|
|
19299
21581
|
const fileInputRef = React20.useRef(null);
|
|
@@ -19374,6 +21656,20 @@ function ChatInputArea({
|
|
|
19374
21656
|
};
|
|
19375
21657
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-zinc-950 px-4 py-4 flex-shrink-0", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-3xl mx-auto", children: [
|
|
19376
21658
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative bg-zinc-900 border border-zinc-800 rounded-2xl shadow-lg shadow-black/20 focus-within:border-zinc-700 focus-within:shadow-xl focus-within:shadow-black/30 transition-all duration-200", children: [
|
|
21659
|
+
activeArtifact && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2 px-4 pt-3 pb-1", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 px-2.5 py-1 bg-zinc-800/80 rounded-lg text-xs", children: [
|
|
21660
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileCode, { size: 12, className: "text-[#d8ff00] flex-shrink-0" }),
|
|
21661
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-zinc-400", children: "\u5173\u8054\u4EA7\u7269\uFF1A" }),
|
|
21662
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-zinc-200 font-medium max-w-[200px] truncate", children: activeArtifact.title }),
|
|
21663
|
+
onDetachArtifact && /* @__PURE__ */ jsxRuntime.jsx(
|
|
21664
|
+
"button",
|
|
21665
|
+
{
|
|
21666
|
+
onClick: onDetachArtifact,
|
|
21667
|
+
className: "p-0.5 text-zinc-500 hover:text-zinc-300 rounded transition-colors",
|
|
21668
|
+
title: "\u53D6\u6D88\u5173\u8054",
|
|
21669
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Unlink, { size: 10 })
|
|
21670
|
+
}
|
|
21671
|
+
)
|
|
21672
|
+
] }) }),
|
|
19377
21673
|
images.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-3 p-4 pb-2", children: images.map((img, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative group", children: [
|
|
19378
21674
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
19379
21675
|
"img",
|
|
@@ -19538,6 +21834,188 @@ var DragHandle = React20__namespace.default.memo(function DragHandle2({
|
|
|
19538
21834
|
}
|
|
19539
21835
|
);
|
|
19540
21836
|
});
|
|
21837
|
+
var artifactTypeIconMap = {
|
|
21838
|
+
html: lucideReact.Globe,
|
|
21839
|
+
svg: lucideReact.Globe,
|
|
21840
|
+
markdown: lucideReact.FileText,
|
|
21841
|
+
json: lucideReact.FileJson,
|
|
21842
|
+
code: lucideReact.FileCode,
|
|
21843
|
+
text: lucideReact.FileText,
|
|
21844
|
+
image: lucideReact.FileImage,
|
|
21845
|
+
video: lucideReact.Video
|
|
21846
|
+
};
|
|
21847
|
+
var ArtifactBarItemThumbnail = React20.memo(function ArtifactBarItemThumbnail2({
|
|
21848
|
+
artifact,
|
|
21849
|
+
config
|
|
21850
|
+
}) {
|
|
21851
|
+
const TypeIcon = artifactTypeIconMap[artifact.type] || lucideReact.FileText;
|
|
21852
|
+
const isMedia = artifact.type === "image" || artifact.type === "video";
|
|
21853
|
+
const thumbnailUrl = useResolvedThumbnailUrl(
|
|
21854
|
+
artifact.currentContent,
|
|
21855
|
+
{
|
|
21856
|
+
fileId: artifact.metadata?.fileId,
|
|
21857
|
+
type: artifact.type,
|
|
21858
|
+
config,
|
|
21859
|
+
enabled: isMedia
|
|
21860
|
+
}
|
|
21861
|
+
);
|
|
21862
|
+
if (isMedia && thumbnailUrl) {
|
|
21863
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
21864
|
+
"img",
|
|
21865
|
+
{
|
|
21866
|
+
src: thumbnailUrl,
|
|
21867
|
+
alt: "",
|
|
21868
|
+
className: "w-10 h-10 rounded-lg object-cover flex-shrink-0 border border-zinc-700/50 agent-sdk-light:border-zinc-300",
|
|
21869
|
+
loading: "lazy"
|
|
21870
|
+
}
|
|
21871
|
+
);
|
|
21872
|
+
}
|
|
21873
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-10 h-10 rounded-lg bg-zinc-800/50 agent-sdk-light:bg-zinc-100 flex items-center justify-center flex-shrink-0 border border-zinc-700/30 agent-sdk-light:border-zinc-300", children: /* @__PURE__ */ jsxRuntime.jsx(TypeIcon, { size: 18, className: "text-zinc-400 agent-sdk-light:text-zinc-500" }) });
|
|
21874
|
+
});
|
|
21875
|
+
var ArtifactBarMiniThumbnail = React20.memo(function ArtifactBarMiniThumbnail2({
|
|
21876
|
+
artifact,
|
|
21877
|
+
config
|
|
21878
|
+
}) {
|
|
21879
|
+
const TypeIcon = artifactTypeIconMap[artifact.type] || lucideReact.FileText;
|
|
21880
|
+
const isMedia = artifact.type === "image" || artifact.type === "video";
|
|
21881
|
+
const thumbnailUrl = useResolvedThumbnailUrl(
|
|
21882
|
+
artifact.currentContent,
|
|
21883
|
+
{
|
|
21884
|
+
fileId: artifact.metadata?.fileId,
|
|
21885
|
+
type: artifact.type,
|
|
21886
|
+
config,
|
|
21887
|
+
enabled: isMedia
|
|
21888
|
+
}
|
|
21889
|
+
);
|
|
21890
|
+
if (isMedia && thumbnailUrl) {
|
|
21891
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
21892
|
+
"img",
|
|
21893
|
+
{
|
|
21894
|
+
src: thumbnailUrl,
|
|
21895
|
+
alt: "",
|
|
21896
|
+
className: "w-6 h-6 rounded border border-zinc-700 agent-sdk-light:border-zinc-300 object-cover",
|
|
21897
|
+
loading: "lazy"
|
|
21898
|
+
}
|
|
21899
|
+
);
|
|
21900
|
+
}
|
|
21901
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-6 h-6 rounded border border-zinc-700 agent-sdk-light:border-zinc-300 bg-zinc-800 agent-sdk-light:bg-zinc-200 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(TypeIcon, { size: 10, className: "text-zinc-400" }) });
|
|
21902
|
+
});
|
|
21903
|
+
var ArtifactBar = React20__namespace.default.memo(function ArtifactBar2({
|
|
21904
|
+
artifacts,
|
|
21905
|
+
onOpenArtifact,
|
|
21906
|
+
config
|
|
21907
|
+
}) {
|
|
21908
|
+
const [expanded, setExpanded] = React20.useState(false);
|
|
21909
|
+
const barRef = React20.useRef(null);
|
|
21910
|
+
React20.useEffect(() => {
|
|
21911
|
+
if (!expanded) return;
|
|
21912
|
+
const handleClickOutside = (e) => {
|
|
21913
|
+
if (barRef.current && !barRef.current.contains(e.target)) {
|
|
21914
|
+
setExpanded(false);
|
|
21915
|
+
}
|
|
21916
|
+
};
|
|
21917
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
21918
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
21919
|
+
}, [expanded]);
|
|
21920
|
+
if (artifacts.length === 0) return null;
|
|
21921
|
+
const imageCount = artifacts.filter((a) => a.type === "image").length;
|
|
21922
|
+
const codeCount = artifacts.filter((a) => ["code", "html", "svg", "json"].includes(a.type)).length;
|
|
21923
|
+
const docCount = artifacts.filter((a) => ["markdown", "text"].includes(a.type)).length;
|
|
21924
|
+
const videoCount = artifacts.filter((a) => a.type === "video").length;
|
|
21925
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: barRef, className: "relative flex-shrink-0 mx-auto max-w-md", children: [
|
|
21926
|
+
expanded && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute bottom-full left-0 right-0 mb-1 z-30 max-h-[50vh] overflow-y-auto bg-zinc-900/95 agent-sdk-light:bg-white/95 backdrop-blur-md border border-zinc-700/50 agent-sdk-light:border-zinc-300 rounded-xl shadow-2xl", children: [
|
|
21927
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-4 py-3 border-b border-zinc-800/50 agent-sdk-light:border-zinc-200 flex items-center justify-between", children: [
|
|
21928
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
21929
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.LayoutGrid, { size: 14, className: "text-[#d8ff00]" }),
|
|
21930
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-zinc-200 agent-sdk-light:text-zinc-800", children: "\u5168\u90E8\u4EA7\u7269" }),
|
|
21931
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-zinc-500 bg-zinc-800/50 agent-sdk-light:bg-zinc-200 px-1.5 py-0.5 rounded-full", children: artifacts.length })
|
|
21932
|
+
] }),
|
|
21933
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21934
|
+
"button",
|
|
21935
|
+
{
|
|
21936
|
+
onClick: () => setExpanded(false),
|
|
21937
|
+
className: "p-1 text-zinc-500 hover:text-zinc-300 agent-sdk-light:hover:text-zinc-700 rounded transition-colors",
|
|
21938
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { size: 16 })
|
|
21939
|
+
}
|
|
21940
|
+
)
|
|
21941
|
+
] }),
|
|
21942
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2 grid grid-cols-1 gap-1", children: artifacts.map((artifact) => {
|
|
21943
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
21944
|
+
"button",
|
|
21945
|
+
{
|
|
21946
|
+
onClick: () => {
|
|
21947
|
+
onOpenArtifact(artifact.id);
|
|
21948
|
+
setExpanded(false);
|
|
21949
|
+
},
|
|
21950
|
+
className: "flex items-center gap-3 px-3 py-2.5 rounded-lg text-left w-full hover:bg-zinc-800/60 agent-sdk-light:hover:bg-zinc-100 transition-colors group",
|
|
21951
|
+
children: [
|
|
21952
|
+
/* @__PURE__ */ jsxRuntime.jsx(ArtifactBarItemThumbnail, { artifact, config }),
|
|
21953
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
21954
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-zinc-200 agent-sdk-light:text-zinc-800 truncate font-medium group-hover:text-white agent-sdk-light:group-hover:text-zinc-900", children: artifact.title }),
|
|
21955
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-[11px] text-zinc-500 agent-sdk-light:text-zinc-500 mt-0.5", children: [
|
|
21956
|
+
artifact.type.toUpperCase(),
|
|
21957
|
+
artifact.language && artifact.language !== artifact.type && ` \u2022 ${artifact.language}`
|
|
21958
|
+
] })
|
|
21959
|
+
] })
|
|
21960
|
+
]
|
|
21961
|
+
},
|
|
21962
|
+
artifact.id
|
|
21963
|
+
);
|
|
21964
|
+
}) })
|
|
21965
|
+
] }),
|
|
21966
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-2 border-t border-zinc-800/30 agent-sdk-light:border-zinc-200/50 bg-zinc-900/30 agent-sdk-light:bg-zinc-50/50", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
21967
|
+
"button",
|
|
21968
|
+
{
|
|
21969
|
+
onClick: () => setExpanded((prev) => !prev),
|
|
21970
|
+
className: "w-full flex items-center gap-2.5 px-3 py-2 rounded-lg bg-zinc-800/40 agent-sdk-light:bg-zinc-100 hover:bg-zinc-800/60 agent-sdk-light:hover:bg-zinc-200/80 border border-zinc-700/30 agent-sdk-light:border-zinc-300/50 transition-colors group",
|
|
21971
|
+
children: [
|
|
21972
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
21973
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { size: 14, className: "text-[#d8ff00]" }),
|
|
21974
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs font-medium text-zinc-300 agent-sdk-light:text-zinc-700", children: [
|
|
21975
|
+
artifacts.length,
|
|
21976
|
+
" \u4E2A\u4EA7\u7269"
|
|
21977
|
+
] })
|
|
21978
|
+
] }),
|
|
21979
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 flex-1 min-w-0", children: [
|
|
21980
|
+
imageCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1 text-[10px] text-zinc-500 bg-zinc-700/30 agent-sdk-light:bg-zinc-200 px-1.5 py-0.5 rounded", children: [
|
|
21981
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileImage, { size: 10 }),
|
|
21982
|
+
" ",
|
|
21983
|
+
imageCount
|
|
21984
|
+
] }),
|
|
21985
|
+
codeCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1 text-[10px] text-zinc-500 bg-zinc-700/30 agent-sdk-light:bg-zinc-200 px-1.5 py-0.5 rounded", children: [
|
|
21986
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileCode, { size: 10 }),
|
|
21987
|
+
" ",
|
|
21988
|
+
codeCount
|
|
21989
|
+
] }),
|
|
21990
|
+
docCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1 text-[10px] text-zinc-500 bg-zinc-700/30 agent-sdk-light:bg-zinc-200 px-1.5 py-0.5 rounded", children: [
|
|
21991
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileText, { size: 10 }),
|
|
21992
|
+
" ",
|
|
21993
|
+
docCount
|
|
21994
|
+
] }),
|
|
21995
|
+
videoCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1 text-[10px] text-zinc-500 bg-zinc-700/30 agent-sdk-light:bg-zinc-200 px-1.5 py-0.5 rounded", children: [
|
|
21996
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Video, { size: 10 }),
|
|
21997
|
+
" ",
|
|
21998
|
+
videoCount
|
|
21999
|
+
] })
|
|
22000
|
+
] }),
|
|
22001
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center -space-x-1.5", children: [
|
|
22002
|
+
artifacts.slice(0, 4).map((artifact) => {
|
|
22003
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ArtifactBarMiniThumbnail, { artifact, config }, artifact.id);
|
|
22004
|
+
}),
|
|
22005
|
+
artifacts.length > 4 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-6 h-6 rounded border border-zinc-700 agent-sdk-light:border-zinc-300 bg-zinc-800 agent-sdk-light:bg-zinc-200 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[9px] text-zinc-400", children: [
|
|
22006
|
+
"+",
|
|
22007
|
+
artifacts.length - 4
|
|
22008
|
+
] }) })
|
|
22009
|
+
] }),
|
|
22010
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronUp, { size: 14, className: cn2(
|
|
22011
|
+
"text-zinc-500 transition-transform flex-shrink-0",
|
|
22012
|
+
expanded && "rotate-180"
|
|
22013
|
+
) })
|
|
22014
|
+
]
|
|
22015
|
+
}
|
|
22016
|
+
) })
|
|
22017
|
+
] });
|
|
22018
|
+
});
|
|
19541
22019
|
var AgentChat = React20__namespace.default.forwardRef(({
|
|
19542
22020
|
agentId,
|
|
19543
22021
|
projectId,
|
|
@@ -19580,7 +22058,7 @@ var AgentChat = React20__namespace.default.forwardRef(({
|
|
|
19580
22058
|
ComponentRegistry: mergedRegistry
|
|
19581
22059
|
};
|
|
19582
22060
|
}, [config?.components, outerComponents]);
|
|
19583
|
-
const { sessions, setSessions, currentSession, setCurrentSession, addSession, removeSession, tools: _tools, setTools, setSkills, setShowItemTime } = useAgentStore();
|
|
22061
|
+
const { sessions, setSessions, currentSession, setCurrentSession, addSession, removeSession, tools: _tools, setTools, setSkills, setShowItemTime, artifacts, artifactOrder, activeArtifactId, upsertArtifact, updateArtifactContent, setActiveArtifact, removeArtifact, clearArtifacts, setArtifacts, reorderArtifacts } = useAgentStore();
|
|
19584
22062
|
const [loading, setLoading] = React20.useState(true);
|
|
19585
22063
|
const [messagesLoading, setMessagesLoading] = React20.useState(false);
|
|
19586
22064
|
const [collapsed, setCollapsed] = React20.useState(false);
|
|
@@ -19592,7 +22070,23 @@ var AgentChat = React20__namespace.default.forwardRef(({
|
|
|
19592
22070
|
const lastUserMessageRef = React20.useRef("");
|
|
19593
22071
|
const [shareModalOpen, setShareModalOpen] = React20.useState(false);
|
|
19594
22072
|
const [shareSession, setShareSession] = React20.useState(null);
|
|
19595
|
-
const
|
|
22073
|
+
const artifactList = React20.useMemo(() => {
|
|
22074
|
+
const ordered = artifactOrder.map((id) => artifacts[id]).filter(Boolean);
|
|
22075
|
+
const unordered = Object.values(artifacts).filter(
|
|
22076
|
+
(a) => !artifactOrder.includes(a.id)
|
|
22077
|
+
);
|
|
22078
|
+
return [...ordered, ...unordered];
|
|
22079
|
+
}, [artifacts, artifactOrder]);
|
|
22080
|
+
const activeArtifact = activeArtifactId ? artifacts[activeArtifactId] ?? null : null;
|
|
22081
|
+
const currentArtifact = activeArtifact ? {
|
|
22082
|
+
id: activeArtifact.id,
|
|
22083
|
+
type: activeArtifact.type,
|
|
22084
|
+
title: activeArtifact.title,
|
|
22085
|
+
content: activeArtifact.currentContent,
|
|
22086
|
+
language: activeArtifact.language,
|
|
22087
|
+
source: activeArtifact.sourceId,
|
|
22088
|
+
metadata: activeArtifact.metadata
|
|
22089
|
+
} : null;
|
|
19596
22090
|
const [isArtifactFullscreen, setIsArtifactFullscreen] = React20.useState(false);
|
|
19597
22091
|
const [artifactPanelWidth, setArtifactPanelWidth] = React20.useState(50);
|
|
19598
22092
|
const [isDragging, setIsDragging] = React20.useState(false);
|
|
@@ -19618,7 +22112,11 @@ var AgentChat = React20__namespace.default.forwardRef(({
|
|
|
19618
22112
|
const deltaX = dragStartRef.current.startX - e.clientX;
|
|
19619
22113
|
const deltaPercent = deltaX / containerWidth * 100;
|
|
19620
22114
|
const newWidth = dragStartRef.current.startWidth + deltaPercent;
|
|
19621
|
-
const
|
|
22115
|
+
const minChatPx = 350;
|
|
22116
|
+
const minArtifactPx = 400;
|
|
22117
|
+
const maxArtifactPercent = (containerWidth - minChatPx) / containerWidth * 100;
|
|
22118
|
+
const minArtifactPercent = minArtifactPx / containerWidth * 100;
|
|
22119
|
+
const clampedWidth = Math.max(minArtifactPercent, Math.min(maxArtifactPercent, newWidth));
|
|
19622
22120
|
setArtifactPanelWidth(clampedWidth);
|
|
19623
22121
|
};
|
|
19624
22122
|
const handleMouseUp = () => {
|
|
@@ -19640,38 +22138,52 @@ var AgentChat = React20__namespace.default.forwardRef(({
|
|
|
19640
22138
|
setShowItemTime(showItemTime);
|
|
19641
22139
|
}, [showItemTime]);
|
|
19642
22140
|
const handleOpenArtifact = React20.useCallback((data) => {
|
|
19643
|
-
if (
|
|
19644
|
-
|
|
22141
|
+
if (activeArtifact && activeArtifact.currentContent === data.content && activeArtifact.type === data.type) {
|
|
22142
|
+
setActiveArtifact(null);
|
|
19645
22143
|
setIsArtifactFullscreen(false);
|
|
19646
22144
|
return;
|
|
19647
22145
|
}
|
|
19648
|
-
const
|
|
19649
|
-
|
|
19650
|
-
|
|
19651
|
-
|
|
19652
|
-
|
|
19653
|
-
|
|
19654
|
-
|
|
19655
|
-
|
|
19656
|
-
|
|
19657
|
-
|
|
22146
|
+
const existingArtifact = Object.values(artifacts).find(
|
|
22147
|
+
(a) => a.currentContent === data.content && a.type === data.type
|
|
22148
|
+
);
|
|
22149
|
+
if (existingArtifact) {
|
|
22150
|
+
setActiveArtifact(existingArtifact.id);
|
|
22151
|
+
} else {
|
|
22152
|
+
const sessionId = currentSession?.sessionId || "";
|
|
22153
|
+
const newArtifactEntry = {
|
|
22154
|
+
id: `artifact-${Date.now()}`,
|
|
22155
|
+
sessionId,
|
|
22156
|
+
type: data.type,
|
|
22157
|
+
title: data.title,
|
|
22158
|
+
currentContent: data.content,
|
|
22159
|
+
language: data.language,
|
|
22160
|
+
metadata: data.metadata,
|
|
22161
|
+
version: 1,
|
|
22162
|
+
source: "llm",
|
|
22163
|
+
gmtCreate: (/* @__PURE__ */ new Date()).toISOString(),
|
|
22164
|
+
gmtModified: (/* @__PURE__ */ new Date()).toISOString()
|
|
22165
|
+
};
|
|
22166
|
+
upsertArtifact(newArtifactEntry);
|
|
22167
|
+
setActiveArtifact(newArtifactEntry.id);
|
|
22168
|
+
}
|
|
22169
|
+
}, [activeArtifact, artifacts, currentSession, upsertArtifact, setActiveArtifact]);
|
|
19658
22170
|
const handleCloseArtifact = React20.useCallback(() => {
|
|
19659
|
-
|
|
22171
|
+
setActiveArtifact(null);
|
|
19660
22172
|
setIsArtifactFullscreen(false);
|
|
19661
|
-
}, []);
|
|
22173
|
+
}, [setActiveArtifact]);
|
|
19662
22174
|
React20.useEffect(() => {
|
|
19663
22175
|
const handleKeyDown = (e) => {
|
|
19664
|
-
if (e.key === "Escape" &&
|
|
22176
|
+
if (e.key === "Escape" && activeArtifactId) {
|
|
19665
22177
|
if (isArtifactFullscreen) {
|
|
19666
22178
|
setIsArtifactFullscreen(false);
|
|
19667
22179
|
} else {
|
|
19668
|
-
|
|
22180
|
+
setActiveArtifact(null);
|
|
19669
22181
|
}
|
|
19670
22182
|
}
|
|
19671
22183
|
};
|
|
19672
22184
|
document.addEventListener("keydown", handleKeyDown);
|
|
19673
22185
|
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
19674
|
-
}, [
|
|
22186
|
+
}, [activeArtifactId, isArtifactFullscreen, setActiveArtifact]);
|
|
19675
22187
|
const handleToggleArtifactFullscreen = React20.useCallback(() => {
|
|
19676
22188
|
setIsArtifactFullscreen((prev) => !prev);
|
|
19677
22189
|
}, []);
|
|
@@ -19873,8 +22385,9 @@ var AgentChat = React20__namespace.default.forwardRef(({
|
|
|
19873
22385
|
addSession(s);
|
|
19874
22386
|
setCurrentSession(s);
|
|
19875
22387
|
useAgentStore.getState().setMessages([]);
|
|
22388
|
+
clearArtifacts();
|
|
19876
22389
|
}
|
|
19877
|
-
}, [projectId, agentId]);
|
|
22390
|
+
}, [projectId, agentId, clearArtifacts]);
|
|
19878
22391
|
const handlePrompt = React20.useCallback(async (p) => {
|
|
19879
22392
|
await handleNew();
|
|
19880
22393
|
setInput(p);
|
|
@@ -19885,10 +22398,29 @@ var AgentChat = React20__namespace.default.forwardRef(({
|
|
|
19885
22398
|
onSessionIdChange?.(s.sessionId);
|
|
19886
22399
|
setMobileOpen(false);
|
|
19887
22400
|
useAgentStore.getState().setMessages([]);
|
|
22401
|
+
clearArtifacts();
|
|
19888
22402
|
setMessagesLoading(true);
|
|
19889
|
-
await
|
|
22403
|
+
await Promise.all([
|
|
22404
|
+
loadMessages(s.sessionId),
|
|
22405
|
+
artifactService.list(s.sessionId).then((res) => {
|
|
22406
|
+
if (res.success && res.data && res.data.length > 0) {
|
|
22407
|
+
setArtifacts(res.data);
|
|
22408
|
+
}
|
|
22409
|
+
}).catch((err) => {
|
|
22410
|
+
console.error("[AgentChat] Load artifacts failed:", err);
|
|
22411
|
+
})
|
|
22412
|
+
]);
|
|
22413
|
+
const currentArtifacts = useAgentStore.getState().artifacts;
|
|
22414
|
+
if (Object.keys(currentArtifacts).length === 0) {
|
|
22415
|
+
const currentMessages = useAgentStore.getState().messages;
|
|
22416
|
+
const extracted = extractArtifactsFromMessages(currentMessages, s.sessionId);
|
|
22417
|
+
if (extracted.length > 0) {
|
|
22418
|
+
console.log("[AgentChat] Fallback: extracted", extracted.length, "artifacts from messages");
|
|
22419
|
+
extracted.forEach((artifact) => upsertArtifact(artifact));
|
|
22420
|
+
}
|
|
22421
|
+
}
|
|
19890
22422
|
setMessagesLoading(false);
|
|
19891
|
-
}, []);
|
|
22423
|
+
}, [clearArtifacts, setArtifacts, upsertArtifact]);
|
|
19892
22424
|
const handleDelete2 = React20.useCallback(async (id) => {
|
|
19893
22425
|
toast("\u5220\u9664\u6B64\u5BF9\u8BDD\uFF1F", {
|
|
19894
22426
|
action: {
|
|
@@ -19961,10 +22493,6 @@ var AgentChat = React20__namespace.default.forwardRef(({
|
|
|
19961
22493
|
working = { ...working, fileId: uploadRes.key, url };
|
|
19962
22494
|
}
|
|
19963
22495
|
}
|
|
19964
|
-
const rendered = await resolveAssetForDisplay(working, config);
|
|
19965
|
-
if (rendered?.url) {
|
|
19966
|
-
urls.push(rendered.url);
|
|
19967
|
-
}
|
|
19968
22496
|
}
|
|
19969
22497
|
if (urls.length > 0) {
|
|
19970
22498
|
const imageMarkdown = urls.map((url) => ``).join("\n");
|
|
@@ -19984,8 +22512,14 @@ var AgentChat = React20__namespace.default.forwardRef(({
|
|
|
19984
22512
|
}
|
|
19985
22513
|
});
|
|
19986
22514
|
setImages([]);
|
|
19987
|
-
|
|
19988
|
-
|
|
22515
|
+
const currentActiveArtifact = activeArtifactId ? artifacts[activeArtifactId] : null;
|
|
22516
|
+
const artifactContext = currentActiveArtifact ? {
|
|
22517
|
+
artifactId: currentActiveArtifact.id,
|
|
22518
|
+
title: currentActiveArtifact.title,
|
|
22519
|
+
currentContent: currentActiveArtifact.currentContent
|
|
22520
|
+
} : void 0;
|
|
22521
|
+
await sendMessage(currentSession.sessionId, messageContent, { artifactContext });
|
|
22522
|
+
}, [input, images, currentSession, sendMessage, config, activeArtifactId, artifacts]);
|
|
19989
22523
|
const sendTextMessage = React20.useCallback(async (content) => {
|
|
19990
22524
|
if (!content.trim()) return;
|
|
19991
22525
|
if (!currentSession) return;
|
|
@@ -20150,6 +22684,13 @@ var AgentChat = React20__namespace.default.forwardRef(({
|
|
|
20150
22684
|
onOpenArtifact: handleOpenArtifact
|
|
20151
22685
|
}
|
|
20152
22686
|
),
|
|
22687
|
+
artifactList.length > 0 && !currentArtifact && /* @__PURE__ */ jsxRuntime.jsx(
|
|
22688
|
+
ArtifactBar,
|
|
22689
|
+
{
|
|
22690
|
+
artifacts: artifactList,
|
|
22691
|
+
onOpenArtifact: (id) => setActiveArtifact(id)
|
|
22692
|
+
}
|
|
22693
|
+
),
|
|
20153
22694
|
!hideInput && /* @__PURE__ */ jsxRuntime.jsx(
|
|
20154
22695
|
ChatInputArea,
|
|
20155
22696
|
{
|
|
@@ -20160,7 +22701,9 @@ var AgentChat = React20__namespace.default.forwardRef(({
|
|
|
20160
22701
|
onSend: handleSend,
|
|
20161
22702
|
onStop: handleStop,
|
|
20162
22703
|
isStreaming: isCurrentSessionStreaming,
|
|
20163
|
-
config
|
|
22704
|
+
config,
|
|
22705
|
+
activeArtifact,
|
|
22706
|
+
onDetachArtifact: () => setActiveArtifact(null)
|
|
20164
22707
|
}
|
|
20165
22708
|
)
|
|
20166
22709
|
]
|
|
@@ -20199,7 +22742,36 @@ var AgentChat = React20__namespace.default.forwardRef(({
|
|
|
20199
22742
|
config,
|
|
20200
22743
|
isFullscreen: isArtifactFullscreen,
|
|
20201
22744
|
onFullscreenToggle: handleToggleArtifactFullscreen,
|
|
20202
|
-
embedded: true
|
|
22745
|
+
embedded: true,
|
|
22746
|
+
artifacts: artifactList,
|
|
22747
|
+
activeArtifactId,
|
|
22748
|
+
onSwitchArtifact: (id) => setActiveArtifact(id),
|
|
22749
|
+
onCloseArtifact: (id) => {
|
|
22750
|
+
removeArtifact(id);
|
|
22751
|
+
if (artifactList.length <= 1) {
|
|
22752
|
+
setIsArtifactFullscreen(false);
|
|
22753
|
+
}
|
|
22754
|
+
},
|
|
22755
|
+
onReorderArtifacts: reorderArtifacts,
|
|
22756
|
+
onContentChange: (content) => {
|
|
22757
|
+
if (activeArtifactId) {
|
|
22758
|
+
updateArtifactContent(activeArtifactId, content, "user");
|
|
22759
|
+
}
|
|
22760
|
+
},
|
|
22761
|
+
onSave: async (artifactId, content) => {
|
|
22762
|
+
try {
|
|
22763
|
+
const res = await artifactService.updateContent(artifactId, content);
|
|
22764
|
+
if (res.success) {
|
|
22765
|
+
updateArtifactContent(artifactId, content, "user");
|
|
22766
|
+
toast.success("\u4EA7\u7269\u5DF2\u4FDD\u5B58");
|
|
22767
|
+
} else {
|
|
22768
|
+
toast.error("\u4FDD\u5B58\u5931\u8D25");
|
|
22769
|
+
}
|
|
22770
|
+
} catch (err) {
|
|
22771
|
+
console.error("[AgentChat] Save artifact failed:", err);
|
|
22772
|
+
toast.error("\u4FDD\u5B58\u4EA7\u7269\u5931\u8D25");
|
|
22773
|
+
}
|
|
22774
|
+
}
|
|
20203
22775
|
}
|
|
20204
22776
|
)
|
|
20205
22777
|
]
|
|
@@ -20709,6 +23281,7 @@ exports.VoiceWaveform = VoiceWaveform;
|
|
|
20709
23281
|
exports.agentService = agentService;
|
|
20710
23282
|
exports.agentSkillService = agentSkillService;
|
|
20711
23283
|
exports.agentToolService = agentToolService;
|
|
23284
|
+
exports.artifactService = artifactService;
|
|
20712
23285
|
exports.calculateReconnectDelay = calculateReconnectDelay;
|
|
20713
23286
|
exports.componentService = componentService;
|
|
20714
23287
|
exports.confirmAllPendingToolCalls = confirmAllPendingToolCalls;
|
|
@@ -20764,8 +23337,14 @@ exports.shareService = shareService;
|
|
|
20764
23337
|
exports.templateService = templateService;
|
|
20765
23338
|
exports.toolCallService = toolCallService;
|
|
20766
23339
|
exports.uploadOSS = uploadOSS;
|
|
23340
|
+
exports.useActiveArtifact = useActiveArtifact;
|
|
23341
|
+
exports.useActiveArtifactId = useActiveArtifactId;
|
|
20767
23342
|
exports.useActiveSubAgent = useActiveSubAgent;
|
|
20768
23343
|
exports.useAgentStore = useAgentStore;
|
|
23344
|
+
exports.useArtifactList = useArtifactList;
|
|
23345
|
+
exports.useArtifactOrder = useArtifactOrder;
|
|
23346
|
+
exports.useArtifacts = useArtifacts;
|
|
23347
|
+
exports.useCanvasBridge = useCanvasBridge;
|
|
20769
23348
|
exports.useChatError = useChatError;
|
|
20770
23349
|
exports.useChatUI = useChatUI;
|
|
20771
23350
|
exports.useComponent = useComponent;
|