@malette/agent-sdk 0.1.1-alpha.0 → 0.1.2
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 +2740 -158
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2735 -160
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +1463 -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,284 @@ 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 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
|
+
className
|
|
11007
|
+
),
|
|
11008
|
+
style: { maxHeight: "400px", maxWidth: "100%" },
|
|
11009
|
+
onMouseEnter: handleMouseEnter,
|
|
11010
|
+
onMouseLeave: handleMouseLeave,
|
|
11011
|
+
onClick: handleClick,
|
|
11012
|
+
children: [
|
|
11013
|
+
posterUrl && !isPlaying && /* @__PURE__ */ jsxRuntime.jsx(
|
|
11014
|
+
"img",
|
|
11015
|
+
{
|
|
11016
|
+
src: posterUrl,
|
|
11017
|
+
alt: "Video cover",
|
|
11018
|
+
className: "absolute inset-0 w-full h-full object-contain z-[1]"
|
|
11019
|
+
}
|
|
11020
|
+
),
|
|
11021
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11022
|
+
"video",
|
|
11023
|
+
{
|
|
11024
|
+
ref: videoRef,
|
|
11025
|
+
src,
|
|
11026
|
+
muted: isMuted,
|
|
11027
|
+
playsInline: true,
|
|
11028
|
+
preload: "metadata",
|
|
11029
|
+
onLoadedMetadata: handleLoadedMetadata,
|
|
11030
|
+
onTimeUpdate: handleTimeUpdate,
|
|
11031
|
+
onEnded: () => {
|
|
11032
|
+
setIsPlaying(false);
|
|
11033
|
+
setIsFullPlaying(false);
|
|
11034
|
+
},
|
|
11035
|
+
className: cn(
|
|
11036
|
+
"w-full max-h-[400px] object-contain",
|
|
11037
|
+
!isPlaying && posterUrl && "opacity-0"
|
|
11038
|
+
)
|
|
11039
|
+
}
|
|
11040
|
+
),
|
|
11041
|
+
/* @__PURE__ */ jsxRuntime.jsx("canvas", { ref: canvasRef, className: "hidden" }),
|
|
11042
|
+
!isFullPlaying && /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(
|
|
11043
|
+
"absolute inset-0 z-[2] flex items-center justify-center",
|
|
11044
|
+
"bg-gradient-to-t from-black/50 via-transparent to-transparent",
|
|
11045
|
+
"transition-opacity duration-200",
|
|
11046
|
+
isHovering && isPlaying ? "opacity-0" : "opacity-100"
|
|
11047
|
+
), children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(
|
|
11048
|
+
"w-14 h-14 rounded-full bg-white/20 backdrop-blur-md",
|
|
11049
|
+
"flex items-center justify-center",
|
|
11050
|
+
"transition-all duration-200",
|
|
11051
|
+
"group-hover/video:scale-110 group-hover/video:bg-white/30",
|
|
11052
|
+
"shadow-lg shadow-black/20"
|
|
11053
|
+
), 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" }) }) }) }),
|
|
11054
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(
|
|
11055
|
+
"absolute bottom-0 left-0 right-0 z-[3]",
|
|
11056
|
+
"bg-gradient-to-t from-black/80 via-black/40 to-transparent",
|
|
11057
|
+
"px-3 pb-2.5 pt-8",
|
|
11058
|
+
"transition-opacity duration-200",
|
|
11059
|
+
isHovering || isFullPlaying ? "opacity-100" : "opacity-0"
|
|
11060
|
+
), children: [
|
|
11061
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11062
|
+
"div",
|
|
11063
|
+
{
|
|
11064
|
+
className: "w-full h-1 bg-white/20 rounded-full mb-2 cursor-pointer group/progress",
|
|
11065
|
+
onClick: handleProgressClick,
|
|
11066
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
11067
|
+
"div",
|
|
11068
|
+
{
|
|
11069
|
+
className: "h-full bg-[#d8ff00] rounded-full relative transition-all duration-75",
|
|
11070
|
+
style: { width: `${progressPercent}%` },
|
|
11071
|
+
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" })
|
|
11072
|
+
}
|
|
11073
|
+
)
|
|
11074
|
+
}
|
|
11075
|
+
),
|
|
11076
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
11077
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
11078
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11079
|
+
"button",
|
|
11080
|
+
{
|
|
11081
|
+
onClick: handleClick,
|
|
11082
|
+
className: "p-1 text-white/80 hover:text-white transition-colors",
|
|
11083
|
+
children: isPlaying ? /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "currentColor", children: [
|
|
11084
|
+
/* @__PURE__ */ jsxRuntime.jsx("rect", { x: "6", y: "4", width: "4", height: "16", rx: "1" }),
|
|
11085
|
+
/* @__PURE__ */ jsxRuntime.jsx("rect", { x: "14", y: "4", width: "4", height: "16", rx: "1" })
|
|
11086
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 5v14l11-7z" }) })
|
|
11087
|
+
}
|
|
11088
|
+
),
|
|
11089
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11090
|
+
"button",
|
|
11091
|
+
{
|
|
11092
|
+
onClick: handleToggleMute,
|
|
11093
|
+
className: "p-1 text-white/80 hover:text-white transition-colors",
|
|
11094
|
+
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: [
|
|
11095
|
+
/* @__PURE__ */ jsxRuntime.jsx("polygon", { points: "11 5 6 9 2 9 2 15 6 15 11 19 11 5" }),
|
|
11096
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "23", y1: "9", x2: "17", y2: "15" }),
|
|
11097
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "17", y1: "9", x2: "23", y2: "15" })
|
|
11098
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
11099
|
+
/* @__PURE__ */ jsxRuntime.jsx("polygon", { points: "11 5 6 9 2 9 2 15 6 15 11 19 11 5" }),
|
|
11100
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M19.07 4.93a10 10 0 0 1 0 14.14" }),
|
|
11101
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15.54 8.46a5 5 0 0 1 0 7.07" })
|
|
11102
|
+
] })
|
|
11103
|
+
}
|
|
11104
|
+
),
|
|
11105
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[11px] text-white/60 font-mono tabular-nums", children: [
|
|
11106
|
+
formatTime2(currentTime),
|
|
11107
|
+
" / ",
|
|
11108
|
+
formatTime2(duration)
|
|
11109
|
+
] })
|
|
11110
|
+
] }),
|
|
11111
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11112
|
+
"button",
|
|
11113
|
+
{
|
|
11114
|
+
onClick: (e) => {
|
|
11115
|
+
e.stopPropagation();
|
|
11116
|
+
const video = videoRef.current;
|
|
11117
|
+
if (video) {
|
|
11118
|
+
video.pause();
|
|
11119
|
+
setIsPlaying(false);
|
|
11120
|
+
setIsFullPlaying(false);
|
|
11121
|
+
}
|
|
11122
|
+
setShowPreview(true);
|
|
11123
|
+
},
|
|
11124
|
+
className: "p-1 text-white/60 hover:text-white transition-colors",
|
|
11125
|
+
title: "\u5168\u5C4F\u9884\u89C8",
|
|
11126
|
+
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: [
|
|
11127
|
+
/* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "15 3 21 3 21 9" }),
|
|
11128
|
+
/* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "9 21 3 21 3 15" }),
|
|
11129
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "21", y1: "3", x2: "14", y2: "10" }),
|
|
11130
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "3", y1: "21", x2: "10", y2: "14" })
|
|
11131
|
+
] })
|
|
11132
|
+
}
|
|
11133
|
+
)
|
|
11134
|
+
] })
|
|
11135
|
+
] })
|
|
11136
|
+
]
|
|
11137
|
+
}
|
|
11138
|
+
)
|
|
11139
|
+
] });
|
|
10609
11140
|
});
|
|
10610
11141
|
var ImagePreviewInternal = React20.memo(function ImagePreviewInternal2({
|
|
10611
11142
|
src,
|
|
@@ -12251,6 +12782,7 @@ var ToolResultRenderer = React20.memo(function ToolResultRenderer2({
|
|
|
12251
12782
|
result,
|
|
12252
12783
|
mediaUrls,
|
|
12253
12784
|
config,
|
|
12785
|
+
toolCallData,
|
|
12254
12786
|
onOpenArtifact
|
|
12255
12787
|
}) {
|
|
12256
12788
|
const [imgLoaded, setImgLoaded] = React20.useState({});
|
|
@@ -12317,32 +12849,134 @@ var ToolResultRenderer = React20.memo(function ToolResultRenderer2({
|
|
|
12317
12849
|
}
|
|
12318
12850
|
),
|
|
12319
12851
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
12320
|
-
hasMedia && /* @__PURE__ */ jsxRuntime.
|
|
12321
|
-
|
|
12322
|
-
|
|
12323
|
-
|
|
12324
|
-
|
|
12325
|
-
|
|
12326
|
-
|
|
12327
|
-
|
|
12328
|
-
|
|
12852
|
+
hasMedia && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2", children: (() => {
|
|
12853
|
+
const totalMedia = imageUrls.length + videoUrls.length;
|
|
12854
|
+
const isMultiple = totalMedia > 1;
|
|
12855
|
+
const buildMediaMetadata = (mediaIndex) => {
|
|
12856
|
+
if (!toolCallData) return void 0;
|
|
12857
|
+
const resultAny = toolCallData.result;
|
|
12858
|
+
const metadata = {};
|
|
12859
|
+
if (toolCallData.name) metadata.toolName = toolCallData.name;
|
|
12860
|
+
if (resultAny?.relation?.toolName) metadata.toolName = resultAny.relation.toolName;
|
|
12861
|
+
if (toolCallData.arguments) metadata.generationParams = toolCallData.arguments;
|
|
12862
|
+
if (resultAny?.relation) metadata.relation = resultAny.relation;
|
|
12863
|
+
if (resultAny?.taskId) metadata.taskId = resultAny.taskId;
|
|
12864
|
+
const work = resultAny?.works?.[mediaIndex];
|
|
12865
|
+
if (work) {
|
|
12866
|
+
if (work.publicId) metadata.workId = work.publicId;
|
|
12867
|
+
if (work.fileId) metadata.fileId = work.fileId;
|
|
12329
12868
|
}
|
|
12330
|
-
|
|
12331
|
-
|
|
12332
|
-
|
|
12333
|
-
/* @__PURE__ */ jsxRuntime.
|
|
12334
|
-
"
|
|
12869
|
+
return metadata;
|
|
12870
|
+
};
|
|
12871
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: isMultiple ? "grid grid-cols-2 gap-2" : "flex", children: [
|
|
12872
|
+
videoUrls.map((video, i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
12873
|
+
"div",
|
|
12335
12874
|
{
|
|
12336
|
-
|
|
12337
|
-
|
|
12338
|
-
|
|
12339
|
-
|
|
12340
|
-
|
|
12341
|
-
|
|
12342
|
-
|
|
12343
|
-
|
|
12344
|
-
|
|
12345
|
-
|
|
12875
|
+
className: `relative group/media overflow-hidden rounded-lg bg-black ${isMultiple ? "aspect-square" : "max-h-[375px]"}`,
|
|
12876
|
+
children: [
|
|
12877
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12878
|
+
MessageVideoInternal,
|
|
12879
|
+
{
|
|
12880
|
+
src: video.hdUrl || video.url,
|
|
12881
|
+
className: isMultiple ? "w-full h-full object-cover" : "max-h-[375px] max-w-full object-contain"
|
|
12882
|
+
}
|
|
12883
|
+
),
|
|
12884
|
+
/* @__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: [
|
|
12885
|
+
onOpenArtifact && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
12886
|
+
"button",
|
|
12887
|
+
{
|
|
12888
|
+
onClick: (e) => {
|
|
12889
|
+
e.stopPropagation();
|
|
12890
|
+
const resultAny = toolCallData?.result;
|
|
12891
|
+
const displayName = resultAny?.relation?.toolName || toolCallData?.name || "\u89C6\u9891\u751F\u6210";
|
|
12892
|
+
onOpenArtifact({
|
|
12893
|
+
type: "video",
|
|
12894
|
+
title: `${displayName} #${i + 1}`,
|
|
12895
|
+
content: video.hdUrl || video.url,
|
|
12896
|
+
metadata: buildMediaMetadata(imageUrls.length + i)
|
|
12897
|
+
});
|
|
12898
|
+
},
|
|
12899
|
+
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",
|
|
12900
|
+
children: [
|
|
12901
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { size: 12 }),
|
|
12902
|
+
"\u67E5\u770B\u8BE6\u60C5"
|
|
12903
|
+
]
|
|
12904
|
+
}
|
|
12905
|
+
),
|
|
12906
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12907
|
+
"button",
|
|
12908
|
+
{
|
|
12909
|
+
onClick: (e) => {
|
|
12910
|
+
e.stopPropagation();
|
|
12911
|
+
window.open(video.hdUrl || video.url, "_blank");
|
|
12912
|
+
},
|
|
12913
|
+
className: "p-1.5 text-white/80 hover:text-white bg-white/15 hover:bg-white/25 backdrop-blur-sm rounded-md transition-colors",
|
|
12914
|
+
title: "\u65B0\u7A97\u53E3\u6253\u5F00",
|
|
12915
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Video, { size: 14 })
|
|
12916
|
+
}
|
|
12917
|
+
)
|
|
12918
|
+
] })
|
|
12919
|
+
]
|
|
12920
|
+
},
|
|
12921
|
+
`video-${i}`
|
|
12922
|
+
)),
|
|
12923
|
+
imageUrls.map((img, i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
12924
|
+
"div",
|
|
12925
|
+
{
|
|
12926
|
+
className: `relative group/media overflow-hidden rounded-lg bg-black ${isMultiple ? "aspect-square" : "max-h-[375px]"}`,
|
|
12927
|
+
children: [
|
|
12928
|
+
!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]" }) }),
|
|
12929
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12930
|
+
"img",
|
|
12931
|
+
{
|
|
12932
|
+
src: img.url,
|
|
12933
|
+
alt: "Generated",
|
|
12934
|
+
onLoad: () => handleImgLoad(i),
|
|
12935
|
+
className: `cursor-zoom-in ${imgLoaded[i] ? "" : "hidden"} ${isMultiple ? "w-full h-full object-cover" : "max-h-[375px] max-w-full h-auto object-contain"}`,
|
|
12936
|
+
onClick: () => setPreviewUrl(img.hdUrl)
|
|
12937
|
+
}
|
|
12938
|
+
),
|
|
12939
|
+
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: [
|
|
12940
|
+
onOpenArtifact && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
12941
|
+
"button",
|
|
12942
|
+
{
|
|
12943
|
+
onClick: (e) => {
|
|
12944
|
+
e.stopPropagation();
|
|
12945
|
+
const resultAny = toolCallData?.result;
|
|
12946
|
+
const displayName = resultAny?.relation?.toolName || toolCallData?.name || "\u56FE\u7247\u751F\u6210";
|
|
12947
|
+
onOpenArtifact({
|
|
12948
|
+
type: "image",
|
|
12949
|
+
title: `${displayName} #${i + 1}`,
|
|
12950
|
+
content: img.hdUrl || img.url,
|
|
12951
|
+
metadata: buildMediaMetadata(i)
|
|
12952
|
+
});
|
|
12953
|
+
},
|
|
12954
|
+
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",
|
|
12955
|
+
children: [
|
|
12956
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { size: 12 }),
|
|
12957
|
+
"\u67E5\u770B\u8BE6\u60C5"
|
|
12958
|
+
]
|
|
12959
|
+
}
|
|
12960
|
+
),
|
|
12961
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12962
|
+
"button",
|
|
12963
|
+
{
|
|
12964
|
+
onClick: (e) => {
|
|
12965
|
+
e.stopPropagation();
|
|
12966
|
+
setPreviewUrl(img.hdUrl);
|
|
12967
|
+
},
|
|
12968
|
+
className: "p-1.5 text-white/80 hover:text-white bg-white/15 hover:bg-white/25 backdrop-blur-sm rounded-md transition-colors",
|
|
12969
|
+
title: "\u653E\u5927\u9884\u89C8",
|
|
12970
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Image, { size: 14 })
|
|
12971
|
+
}
|
|
12972
|
+
)
|
|
12973
|
+
] })
|
|
12974
|
+
]
|
|
12975
|
+
},
|
|
12976
|
+
`img-${i}`
|
|
12977
|
+
))
|
|
12978
|
+
] });
|
|
12979
|
+
})() }),
|
|
12346
12980
|
hasCustomResponses && customResult
|
|
12347
12981
|
] })
|
|
12348
12982
|
] });
|
|
@@ -12468,6 +13102,7 @@ var ToolCallCard3 = React20.memo(function ToolCallCard4({
|
|
|
12468
13102
|
result: toolCall.result,
|
|
12469
13103
|
mediaUrls,
|
|
12470
13104
|
config,
|
|
13105
|
+
toolCallData: toolCall,
|
|
12471
13106
|
defaultExpanded: false,
|
|
12472
13107
|
onOpenArtifact
|
|
12473
13108
|
}
|
|
@@ -12738,7 +13373,7 @@ var ComponentPendingCard = React20.memo(function ComponentPendingCard2({
|
|
|
12738
13373
|
})() })
|
|
12739
13374
|
] });
|
|
12740
13375
|
});
|
|
12741
|
-
var ThoughtTimelineCard = React20.memo(function ThoughtTimelineCard2({ thought, config, isLoading = false }) {
|
|
13376
|
+
var ThoughtTimelineCard = React20.memo(function ThoughtTimelineCard2({ thought, config, isLoading = false, skipImages = false }) {
|
|
12742
13377
|
const [expanded, setExpanded] = React20.useState(true);
|
|
12743
13378
|
const { showItemTime } = useAgentStore();
|
|
12744
13379
|
const thoughtType = thought?.type || "";
|
|
@@ -12762,9 +13397,9 @@ var ThoughtTimelineCard = React20.memo(function ThoughtTimelineCard2({ thought,
|
|
|
12762
13397
|
return null;
|
|
12763
13398
|
}
|
|
12764
13399
|
if (thought?.raw && Array.isArray(thought.raw)) {
|
|
12765
|
-
const hasConfirmationEvent = thought.raw.some((
|
|
12766
|
-
const type =
|
|
12767
|
-
return excludedTypes.includes(type) ||
|
|
13400
|
+
const hasConfirmationEvent = thought.raw.some((r3) => {
|
|
13401
|
+
const type = r3?.type || "";
|
|
13402
|
+
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
13403
|
});
|
|
12769
13404
|
if (hasConfirmationEvent) {
|
|
12770
13405
|
return null;
|
|
@@ -12776,12 +13411,19 @@ var ThoughtTimelineCard = React20.memo(function ThoughtTimelineCard2({ thought,
|
|
|
12776
13411
|
if (!cleaned || !cleaned.trim()) return null;
|
|
12777
13412
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-3 py-2", children: [
|
|
12778
13413
|
/* @__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
|
|
13414
|
+
/* @__PURE__ */ jsxRuntime.jsx(MarkdownContent, { content: cleaned, skipImages, config, variant: "thought" }),
|
|
12780
13415
|
isLoading && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-block w-2 h-4 ml-0.5 bg-[#d8ff00] animate-pulse rounded-sm" })
|
|
12781
13416
|
] }) }),
|
|
12782
13417
|
thought?.raw?.length > 0 && showItemTime && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-zinc-500 mt-2", children: new Date(
|
|
12783
13418
|
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", {
|
|
13419
|
+
).toLocaleTimeString("zh-CN", {
|
|
13420
|
+
year: "numeric",
|
|
13421
|
+
month: "2-digit",
|
|
13422
|
+
day: "2-digit",
|
|
13423
|
+
hour: "2-digit",
|
|
13424
|
+
minute: "2-digit",
|
|
13425
|
+
second: "2-digit"
|
|
13426
|
+
}) })
|
|
12785
13427
|
] }) });
|
|
12786
13428
|
});
|
|
12787
13429
|
var COMPONENT_TAGS_TO_STRIP = [
|
|
@@ -13781,7 +14423,8 @@ ${m.content}`;
|
|
|
13781
14423
|
}
|
|
13782
14424
|
var ThoughtBlockItem = React20.memo(function ThoughtBlockItem2({
|
|
13783
14425
|
content,
|
|
13784
|
-
config
|
|
14426
|
+
config,
|
|
14427
|
+
skipImages = false
|
|
13785
14428
|
}) {
|
|
13786
14429
|
const [expanded, setExpanded] = React20.useState(false);
|
|
13787
14430
|
const lineCount = React20.useMemo(() => content.split("\n").length, [content]);
|
|
@@ -13794,7 +14437,7 @@ var ThoughtBlockItem = React20.memo(function ThoughtBlockItem2({
|
|
|
13794
14437
|
"text-sm text-zinc-400 leading-relaxed prose prose-invert prose-sm max-w-none [&_*]:break-words",
|
|
13795
14438
|
shouldToggle && !expanded ? "max-h-[3.5em] overflow-hidden" : ""
|
|
13796
14439
|
),
|
|
13797
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(MarkdownContent, { content, skipImages
|
|
14440
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(MarkdownContent, { content, skipImages, config, variant: "thought" })
|
|
13798
14441
|
}
|
|
13799
14442
|
),
|
|
13800
14443
|
shouldToggle && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -13980,7 +14623,6 @@ var MessageBubble = React20.memo(function MessageBubble2({
|
|
|
13980
14623
|
const shouldShowAvatar = isUser ? showUserAvatar : showAssistantAvatar;
|
|
13981
14624
|
const shouldShowName = isUser ? showUserName : showAssistantName;
|
|
13982
14625
|
const shouldShowDescription = isUser ? showUserDescription : showAssistantDescription;
|
|
13983
|
-
console.log("[MessageBubble] \u6E32\u67D3\u6D88\u606F\u6C14\u6CE1, config?.identity:", config?.identity);
|
|
13984
14626
|
const resolveFileName = (url) => {
|
|
13985
14627
|
try {
|
|
13986
14628
|
const pathname = new URL(url, "http://dummy").pathname;
|
|
@@ -14041,7 +14683,8 @@ var MessageBubble = React20.memo(function MessageBubble2({
|
|
|
14041
14683
|
{
|
|
14042
14684
|
thought: item.data,
|
|
14043
14685
|
config,
|
|
14044
|
-
isLoading: showLoadingCursor
|
|
14686
|
+
isLoading: showLoadingCursor,
|
|
14687
|
+
skipImages: hasToolCallImages
|
|
14045
14688
|
},
|
|
14046
14689
|
item.id
|
|
14047
14690
|
);
|
|
@@ -14141,7 +14784,8 @@ var MessageBubble = React20.memo(function MessageBubble2({
|
|
|
14141
14784
|
ThoughtBlockItem,
|
|
14142
14785
|
{
|
|
14143
14786
|
content: block.content,
|
|
14144
|
-
config
|
|
14787
|
+
config,
|
|
14788
|
+
skipImages: hasToolCallImages
|
|
14145
14789
|
},
|
|
14146
14790
|
`${block.ts}-${index}`
|
|
14147
14791
|
)),
|
|
@@ -14186,15 +14830,23 @@ var MessageBubble = React20.memo(function MessageBubble2({
|
|
|
14186
14830
|
const isVideo = att.type === "video" || att.type?.startsWith("video/") || isVideoUrl2(att.url);
|
|
14187
14831
|
const isImage2 = att.type === "image" || att.type?.startsWith("image/") || !isVideo && /\.(jpg|jpeg|png|gif|webp|bmp|svg)(\?|#|$)/i.test(att.url);
|
|
14188
14832
|
const fileName = att.name || resolveFileName(att.url);
|
|
14833
|
+
if (att.url.includes("industryai")) {
|
|
14834
|
+
att.url = att.url.split("?")[0];
|
|
14835
|
+
}
|
|
14836
|
+
const assets = config?.asset?.transform?.({
|
|
14837
|
+
type: att.type,
|
|
14838
|
+
url: att.url,
|
|
14839
|
+
name: fileName
|
|
14840
|
+
}) || { url: att.url, type: att.type };
|
|
14189
14841
|
if (isImage2 || isVideo) {
|
|
14190
14842
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14191
14843
|
"button",
|
|
14192
14844
|
{
|
|
14193
14845
|
type: "button",
|
|
14194
|
-
onClick: () => setPreviewMedia({ url:
|
|
14846
|
+
onClick: () => setPreviewMedia({ url: assets.url, isVideo }),
|
|
14195
14847
|
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
14848
|
children: [
|
|
14197
|
-
isVideo ? /* @__PURE__ */ jsxRuntime.jsx(MessageVideoComp, { src:
|
|
14849
|
+
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
14850
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 bg-black/20 opacity-0 group-hover/att:opacity-100 transition-opacity" })
|
|
14199
14851
|
]
|
|
14200
14852
|
},
|
|
@@ -14299,7 +14951,14 @@ var MessageBubble = React20.memo(function MessageBubble2({
|
|
|
14299
14951
|
]
|
|
14300
14952
|
}
|
|
14301
14953
|
) }),
|
|
14302
|
-
message.gmtCreate && !isStreaming && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-zinc-600 text-[10px] mt-1", children: new Date(message.gmtCreate).toLocaleTimeString("zh-CN", {
|
|
14954
|
+
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", {
|
|
14955
|
+
year: "numeric",
|
|
14956
|
+
month: "2-digit",
|
|
14957
|
+
day: "2-digit",
|
|
14958
|
+
hour: "2-digit",
|
|
14959
|
+
minute: "2-digit",
|
|
14960
|
+
second: "2-digit"
|
|
14961
|
+
}) })
|
|
14303
14962
|
] })
|
|
14304
14963
|
] });
|
|
14305
14964
|
});
|
|
@@ -15174,9 +15833,24 @@ var DialogDescription = React20__namespace.forwardRef(({ className, ...props },
|
|
|
15174
15833
|
));
|
|
15175
15834
|
DialogDescription.displayName = DialogPrimitive__namespace.Description.displayName;
|
|
15176
15835
|
|
|
15836
|
+
// ../../node_modules/clsx/dist/clsx.mjs
|
|
15837
|
+
function r2(e) {
|
|
15838
|
+
var t, f, n = "";
|
|
15839
|
+
if ("string" == typeof e || "number" == typeof e) n += e;
|
|
15840
|
+
else if ("object" == typeof e) if (Array.isArray(e)) {
|
|
15841
|
+
var o = e.length;
|
|
15842
|
+
for (t = 0; t < o; t++) e[t] && (f = r2(e[t])) && (n && (n += " "), n += f);
|
|
15843
|
+
} else for (f in e) e[f] && (n && (n += " "), n += f);
|
|
15844
|
+
return n;
|
|
15845
|
+
}
|
|
15846
|
+
function clsx2() {
|
|
15847
|
+
for (var e, t, f = 0, n = "", o = arguments.length; f < o; f++) (e = arguments[f]) && (t = r2(e)) && (n && (n += " "), n += t);
|
|
15848
|
+
return n;
|
|
15849
|
+
}
|
|
15850
|
+
|
|
15177
15851
|
// ../../node_modules/class-variance-authority/dist/index.mjs
|
|
15178
15852
|
var falsyToString = (value) => typeof value === "boolean" ? `${value}` : value === 0 ? "0" : value;
|
|
15179
|
-
var cx =
|
|
15853
|
+
var cx = clsx2;
|
|
15180
15854
|
var cva = (base, config) => (props) => {
|
|
15181
15855
|
var _config_compoundVariants;
|
|
15182
15856
|
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 +16668,10 @@ var Observer = class {
|
|
|
15994
16668
|
});
|
|
15995
16669
|
}
|
|
15996
16670
|
};
|
|
15997
|
-
this.custom = (
|
|
16671
|
+
this.custom = (jsx59, data) => {
|
|
15998
16672
|
const id = (data == null ? void 0 : data.id) || toastsCounter++;
|
|
15999
16673
|
this.create({
|
|
16000
|
-
jsx:
|
|
16674
|
+
jsx: jsx59(id),
|
|
16001
16675
|
id,
|
|
16002
16676
|
...data
|
|
16003
16677
|
});
|
|
@@ -18498,7 +19172,57 @@ var ToolbarButton = React20.memo(function ToolbarButton2({
|
|
|
18498
19172
|
}
|
|
18499
19173
|
);
|
|
18500
19174
|
});
|
|
18501
|
-
var
|
|
19175
|
+
var artifactTypeConfig = {
|
|
19176
|
+
html: {
|
|
19177
|
+
icon: lucideReact.Globe,
|
|
19178
|
+
label: "HTML",
|
|
19179
|
+
color: "text-orange-400",
|
|
19180
|
+
bgColor: "bg-orange-500/10"
|
|
19181
|
+
},
|
|
19182
|
+
svg: {
|
|
19183
|
+
icon: lucideReact.Globe,
|
|
19184
|
+
label: "SVG",
|
|
19185
|
+
color: "text-orange-300",
|
|
19186
|
+
bgColor: "bg-orange-500/10"
|
|
19187
|
+
},
|
|
19188
|
+
markdown: {
|
|
19189
|
+
icon: lucideReact.FileText,
|
|
19190
|
+
label: "Markdown",
|
|
19191
|
+
color: "text-blue-400",
|
|
19192
|
+
bgColor: "bg-blue-500/10"
|
|
19193
|
+
},
|
|
19194
|
+
json: {
|
|
19195
|
+
icon: lucideReact.FileJson,
|
|
19196
|
+
label: "JSON",
|
|
19197
|
+
color: "text-yellow-400",
|
|
19198
|
+
bgColor: "bg-yellow-500/10"
|
|
19199
|
+
},
|
|
19200
|
+
code: {
|
|
19201
|
+
icon: lucideReact.FileCode,
|
|
19202
|
+
label: "Code",
|
|
19203
|
+
color: "text-purple-400",
|
|
19204
|
+
bgColor: "bg-purple-500/10"
|
|
19205
|
+
},
|
|
19206
|
+
text: {
|
|
19207
|
+
icon: lucideReact.FileText,
|
|
19208
|
+
label: "Text",
|
|
19209
|
+
color: "text-zinc-400",
|
|
19210
|
+
bgColor: "bg-zinc-500/10"
|
|
19211
|
+
},
|
|
19212
|
+
image: {
|
|
19213
|
+
icon: lucideReact.FileImage,
|
|
19214
|
+
label: "Image",
|
|
19215
|
+
color: "text-green-400",
|
|
19216
|
+
bgColor: "bg-green-500/10"
|
|
19217
|
+
},
|
|
19218
|
+
video: {
|
|
19219
|
+
icon: lucideReact.Video,
|
|
19220
|
+
label: "Video",
|
|
19221
|
+
color: "text-pink-400",
|
|
19222
|
+
bgColor: "bg-pink-500/10"
|
|
19223
|
+
}
|
|
19224
|
+
};
|
|
19225
|
+
var CodeBlock3 = React20.memo(function CodeBlock4({
|
|
18502
19226
|
code: code3,
|
|
18503
19227
|
language,
|
|
18504
19228
|
showLineNumbers = true
|
|
@@ -18786,38 +19510,1305 @@ React20.memo(function JsonPreview2({ content }) {
|
|
|
18786
19510
|
}
|
|
18787
19511
|
return /* @__PURE__ */ jsxRuntime.jsx(CodeBlock3, { code: formattedJson, language: "json" });
|
|
18788
19512
|
});
|
|
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
|
-
|
|
19513
|
+
var CodeEditor = React20.memo(function CodeEditor2({
|
|
19514
|
+
code: code3,
|
|
19515
|
+
language,
|
|
19516
|
+
onChange
|
|
19517
|
+
}) {
|
|
19518
|
+
const textareaRef = React20.useRef(null);
|
|
19519
|
+
const handleKeyDown = React20.useCallback((e) => {
|
|
19520
|
+
if (e.key === "Tab") {
|
|
19521
|
+
e.preventDefault();
|
|
19522
|
+
const textarea = e.currentTarget;
|
|
19523
|
+
const start = textarea.selectionStart;
|
|
19524
|
+
const end = textarea.selectionEnd;
|
|
19525
|
+
const newValue = code3.substring(0, start) + " " + code3.substring(end);
|
|
19526
|
+
onChange(newValue);
|
|
19527
|
+
requestAnimationFrame(() => {
|
|
19528
|
+
textarea.selectionStart = textarea.selectionEnd = start + 2;
|
|
19529
|
+
});
|
|
19530
|
+
}
|
|
19531
|
+
}, [code3, onChange]);
|
|
19532
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "h-full flex flex-col bg-zinc-950 agent-sdk-light:bg-white", children: [
|
|
19533
|
+
/* @__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: [
|
|
19534
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, { size: 12, className: "text-[#d8ff00]" }),
|
|
19535
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-[#d8ff00] font-medium", children: "\u7F16\u8F91\u6A21\u5F0F" }),
|
|
19536
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-zinc-500 agent-sdk-light:text-zinc-600 font-mono uppercase ml-2", children: language || "text" })
|
|
19537
|
+
] }) }),
|
|
19538
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
19539
|
+
"textarea",
|
|
19540
|
+
{
|
|
19541
|
+
ref: textareaRef,
|
|
19542
|
+
value: code3,
|
|
19543
|
+
onChange: (e) => onChange(e.target.value),
|
|
19544
|
+
onKeyDown: handleKeyDown,
|
|
19545
|
+
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",
|
|
19546
|
+
spellCheck: false,
|
|
19547
|
+
autoComplete: "off",
|
|
19548
|
+
autoCorrect: "off",
|
|
19549
|
+
autoCapitalize: "off"
|
|
19550
|
+
}
|
|
19551
|
+
) })
|
|
19552
|
+
] });
|
|
19553
|
+
});
|
|
19554
|
+
function useResolvedMediaUrl(content, options) {
|
|
19555
|
+
const { fileId, type = "image", config } = options || {};
|
|
19556
|
+
const [resolvedUrl, setResolvedUrl] = React20.useState(content);
|
|
19557
|
+
const [resolvedHdUrl, setResolvedHdUrl] = React20.useState(content);
|
|
19558
|
+
const [isLoading, setIsLoading] = React20.useState(true);
|
|
19559
|
+
React20.useEffect(() => {
|
|
19560
|
+
let active = true;
|
|
19561
|
+
setIsLoading(true);
|
|
19562
|
+
const resolve = async () => {
|
|
19563
|
+
const httpUrl = isHttpUrl(content) ? content : void 0;
|
|
19564
|
+
const asset = createAssetFromSource({
|
|
19565
|
+
fileId: fileId || (!httpUrl ? content : void 0),
|
|
19566
|
+
fileUrl: httpUrl,
|
|
19567
|
+
type
|
|
19568
|
+
});
|
|
19569
|
+
if (!asset) {
|
|
19570
|
+
if (active) {
|
|
19571
|
+
setResolvedUrl(content);
|
|
19572
|
+
setResolvedHdUrl(content);
|
|
19573
|
+
setIsLoading(false);
|
|
19574
|
+
}
|
|
19575
|
+
return;
|
|
19576
|
+
}
|
|
19577
|
+
const resolved = await resolveAssetForDisplay(asset, config);
|
|
19578
|
+
if (!active) return;
|
|
19579
|
+
if (resolved) {
|
|
19580
|
+
setResolvedUrl(resolved.url);
|
|
19581
|
+
setResolvedHdUrl(resolved.hdUrl || resolved.url);
|
|
19582
|
+
} else {
|
|
19583
|
+
setResolvedUrl(content);
|
|
19584
|
+
setResolvedHdUrl(content);
|
|
19585
|
+
}
|
|
19586
|
+
setIsLoading(false);
|
|
19587
|
+
};
|
|
19588
|
+
resolve();
|
|
19589
|
+
return () => {
|
|
19590
|
+
active = false;
|
|
19591
|
+
};
|
|
19592
|
+
}, [content, fileId, type, config]);
|
|
19593
|
+
return { url: resolvedUrl, hdUrl: resolvedHdUrl, isLoading };
|
|
19594
|
+
}
|
|
19595
|
+
function useResolvedThumbnailUrl(content, options) {
|
|
19596
|
+
const { fileId, type = "image", config, enabled = true } = options || {};
|
|
19597
|
+
const [url, setUrl] = React20.useState(null);
|
|
19598
|
+
React20.useEffect(() => {
|
|
19599
|
+
if (!enabled || !content) {
|
|
19600
|
+
setUrl(null);
|
|
19601
|
+
return;
|
|
19602
|
+
}
|
|
19603
|
+
if (type === "video") {
|
|
19604
|
+
setUrl(null);
|
|
19605
|
+
return;
|
|
19606
|
+
}
|
|
19607
|
+
let active = true;
|
|
19608
|
+
const resolve = async () => {
|
|
19609
|
+
const httpUrl = isHttpUrl(content) ? content : void 0;
|
|
19610
|
+
const asset = createAssetFromSource({
|
|
19611
|
+
fileId: fileId || (!httpUrl ? content : void 0),
|
|
19612
|
+
fileUrl: httpUrl,
|
|
19613
|
+
type
|
|
19614
|
+
});
|
|
19615
|
+
if (!asset) {
|
|
19616
|
+
if (active) setUrl(isHttpUrl(content) ? content : null);
|
|
19617
|
+
return;
|
|
19618
|
+
}
|
|
19619
|
+
const resolved = await resolveAssetForDisplay(asset, config);
|
|
19620
|
+
if (!active) return;
|
|
19621
|
+
setUrl(resolved?.url || (isHttpUrl(content) ? content : null));
|
|
19622
|
+
};
|
|
19623
|
+
resolve();
|
|
19624
|
+
return () => {
|
|
19625
|
+
active = false;
|
|
19626
|
+
};
|
|
19627
|
+
}, [content, fileId, type, config, enabled]);
|
|
19628
|
+
return url;
|
|
19629
|
+
}
|
|
19630
|
+
var ImageArtifactPreview = React20.memo(function ImageArtifactPreview2({
|
|
19631
|
+
content,
|
|
19632
|
+
metadata,
|
|
19633
|
+
config
|
|
19634
|
+
}) {
|
|
19635
|
+
const [isZoomed, setIsZoomed] = React20.useState(false);
|
|
19636
|
+
const [showInfo, setShowInfo] = React20.useState(true);
|
|
19637
|
+
const [imgNaturalSize, setImgNaturalSize] = React20.useState(null);
|
|
19638
|
+
const [copied, setCopied] = React20.useState(null);
|
|
19639
|
+
const { hdUrl: resolvedHdUrl } = useResolvedMediaUrl(content, {
|
|
19640
|
+
fileId: metadata?.fileId,
|
|
19641
|
+
type: "image",
|
|
19642
|
+
config
|
|
19643
|
+
});
|
|
19644
|
+
const generationParams = metadata?.generationParams;
|
|
19645
|
+
const toolName = metadata?.toolName;
|
|
19646
|
+
const relation = metadata?.relation;
|
|
19647
|
+
const handleCopy = React20.useCallback(async (text3, label) => {
|
|
19648
|
+
try {
|
|
19649
|
+
await navigator.clipboard.writeText(text3);
|
|
19650
|
+
setCopied(label);
|
|
19651
|
+
setTimeout(() => setCopied(null), 2e3);
|
|
19652
|
+
} catch {
|
|
19653
|
+
}
|
|
19654
|
+
}, []);
|
|
19655
|
+
const handleDownload = React20.useCallback(() => {
|
|
19656
|
+
const link2 = document.createElement("a");
|
|
19657
|
+
link2.href = resolvedHdUrl;
|
|
19658
|
+
link2.download = `generated-${Date.now()}.png`;
|
|
19659
|
+
link2.target = "_blank";
|
|
19660
|
+
document.body.appendChild(link2);
|
|
19661
|
+
link2.click();
|
|
19662
|
+
document.body.removeChild(link2);
|
|
19663
|
+
}, [resolvedHdUrl]);
|
|
19664
|
+
const formatParamKey = (key) => {
|
|
19665
|
+
const keyMap = {
|
|
19666
|
+
content: "Prompt",
|
|
19667
|
+
width: "\u5BBD\u5EA6",
|
|
19668
|
+
height: "\u9AD8\u5EA6",
|
|
19669
|
+
batchSize: "\u751F\u6210\u6570\u91CF",
|
|
19670
|
+
steps: "\u6B65\u6570",
|
|
19671
|
+
cfg_scale: "CFG Scale",
|
|
19672
|
+
seed: "\u79CD\u5B50",
|
|
19673
|
+
sampler: "\u91C7\u6837\u5668",
|
|
19674
|
+
model: "\u6A21\u578B",
|
|
19675
|
+
negative_prompt: "\u53CD\u5411\u63D0\u793A\u8BCD",
|
|
19676
|
+
style: "\u98CE\u683C",
|
|
19677
|
+
quality: "\u8D28\u91CF"
|
|
19678
|
+
};
|
|
19679
|
+
return keyMap[key] || key.replace(/([A-Z])/g, " $1").replace(/_/g, " ").replace(/^./, (s) => s.toUpperCase());
|
|
19680
|
+
};
|
|
19681
|
+
const promptText = generationParams?.content ? String(generationParams.content) : null;
|
|
19682
|
+
const otherParams = generationParams ? Object.entries(generationParams).filter(([key]) => key !== "content") : [];
|
|
19683
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "h-full flex flex-col bg-zinc-950 agent-sdk-light:bg-white", children: [
|
|
19684
|
+
/* @__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: [
|
|
19685
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 opacity-[0.03]", style: {
|
|
19686
|
+
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%)",
|
|
19687
|
+
backgroundSize: "20px 20px",
|
|
19688
|
+
backgroundPosition: "0 0, 0 10px, 10px -10px, -10px 0px"
|
|
19689
|
+
} }),
|
|
19690
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
19691
|
+
"div",
|
|
19692
|
+
{
|
|
19693
|
+
className: cn2(
|
|
19694
|
+
"relative transition-transform duration-300 cursor-zoom-in z-10",
|
|
19695
|
+
isZoomed && "cursor-zoom-out scale-[2] z-50"
|
|
19696
|
+
),
|
|
19697
|
+
onClick: () => setIsZoomed((prev) => !prev),
|
|
19698
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
19699
|
+
"img",
|
|
19700
|
+
{
|
|
19701
|
+
src: resolvedHdUrl,
|
|
19702
|
+
alt: "Generated image",
|
|
19703
|
+
className: "max-w-full max-h-[60vh] object-contain rounded-lg shadow-2xl",
|
|
19704
|
+
loading: "lazy",
|
|
19705
|
+
onLoad: (e) => {
|
|
19706
|
+
const img = e.target;
|
|
19707
|
+
setImgNaturalSize({ width: img.naturalWidth, height: img.naturalHeight });
|
|
19708
|
+
}
|
|
19709
|
+
}
|
|
19710
|
+
)
|
|
19711
|
+
}
|
|
19712
|
+
),
|
|
19713
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute top-4 right-4 flex items-center gap-1.5 z-20", children: [
|
|
19714
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
19715
|
+
"button",
|
|
19716
|
+
{
|
|
19717
|
+
onClick: () => setShowInfo((prev) => !prev),
|
|
19718
|
+
className: cn2(
|
|
19719
|
+
"p-2 rounded-lg backdrop-blur-sm transition-colors",
|
|
19720
|
+
showInfo ? "bg-[#d8ff00]/20 text-[#d8ff00]" : "bg-black/30 text-white/70 hover:text-white hover:bg-black/50"
|
|
19721
|
+
),
|
|
19722
|
+
title: showInfo ? "\u9690\u85CF\u8BE6\u60C5" : "\u663E\u793A\u8BE6\u60C5",
|
|
19723
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileText, { size: 16 })
|
|
19724
|
+
}
|
|
19725
|
+
),
|
|
19726
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
19727
|
+
"button",
|
|
19728
|
+
{
|
|
19729
|
+
onClick: handleDownload,
|
|
19730
|
+
className: "p-2 bg-black/30 text-white/70 hover:text-white hover:bg-black/50 rounded-lg backdrop-blur-sm transition-colors",
|
|
19731
|
+
title: "\u4E0B\u8F7D\u56FE\u7247",
|
|
19732
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Download, { size: 16 })
|
|
19733
|
+
}
|
|
19734
|
+
)
|
|
19735
|
+
] }),
|
|
19736
|
+
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: [
|
|
19737
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileImage, { size: 12, className: "text-white/60" }),
|
|
19738
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[11px] text-white/80 font-mono", children: [
|
|
19739
|
+
imgNaturalSize.width,
|
|
19740
|
+
" \xD7 ",
|
|
19741
|
+
imgNaturalSize.height
|
|
19742
|
+
] })
|
|
19743
|
+
] })
|
|
19744
|
+
] }),
|
|
19745
|
+
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: [
|
|
19746
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
19747
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2.5", children: [
|
|
19748
|
+
/* @__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]" }) }),
|
|
19749
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
19750
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-zinc-200 agent-sdk-light:text-zinc-800", children: toolName || "\u56FE\u7247\u751F\u6210" }),
|
|
19751
|
+
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 })
|
|
19752
|
+
] })
|
|
19753
|
+
] }),
|
|
19754
|
+
metadata?.taskId && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[10px] text-zinc-600 font-mono", children: [
|
|
19755
|
+
"Task: ",
|
|
19756
|
+
metadata.taskId
|
|
19757
|
+
] })
|
|
19758
|
+
] }),
|
|
19759
|
+
promptText && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
|
|
19760
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
19761
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-zinc-500 uppercase tracking-wider font-medium", children: "Prompt" }),
|
|
19762
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
19763
|
+
"button",
|
|
19764
|
+
{
|
|
19765
|
+
onClick: () => handleCopy(promptText, "prompt"),
|
|
19766
|
+
className: "text-[10px] text-zinc-500 hover:text-zinc-300 transition-colors flex items-center gap-1",
|
|
19767
|
+
children: copied === "prompt" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
19768
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCheck, { size: 10, className: "text-green-400" }),
|
|
19769
|
+
" \u5DF2\u590D\u5236"
|
|
19770
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
19771
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { size: 10 }),
|
|
19772
|
+
" \u590D\u5236"
|
|
19773
|
+
] })
|
|
19774
|
+
}
|
|
19775
|
+
)
|
|
19776
|
+
] }),
|
|
19777
|
+
/* @__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 }) })
|
|
19778
|
+
] }),
|
|
19779
|
+
otherParams.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
|
|
19780
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-zinc-500 uppercase tracking-wider font-medium", children: "\u53C2\u6570" }),
|
|
19781
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 sm:grid-cols-3 gap-2", children: otherParams.map(([key, value]) => {
|
|
19782
|
+
const displayValue = String(value);
|
|
19783
|
+
if (displayValue.length > 100) return null;
|
|
19784
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
19785
|
+
"div",
|
|
19786
|
+
{
|
|
19787
|
+
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",
|
|
19788
|
+
children: [
|
|
19789
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-zinc-500 agent-sdk-light:text-zinc-500", children: formatParamKey(key) }),
|
|
19790
|
+
/* @__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 })
|
|
19791
|
+
]
|
|
19792
|
+
},
|
|
19793
|
+
key
|
|
19794
|
+
);
|
|
19795
|
+
}) })
|
|
19796
|
+
] }),
|
|
19797
|
+
(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: [
|
|
19798
|
+
metadata.workId && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
19799
|
+
"ID: ",
|
|
19800
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-zinc-500", children: metadata.workId })
|
|
19801
|
+
] }),
|
|
19802
|
+
metadata.fileId && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "truncate max-w-[200px]", title: metadata.fileId, children: [
|
|
19803
|
+
"File: ",
|
|
19804
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-zinc-500", children: metadata.fileId })
|
|
19805
|
+
] })
|
|
19806
|
+
] }) })
|
|
19807
|
+
] }) })
|
|
19808
|
+
] });
|
|
19809
|
+
});
|
|
19810
|
+
var VideoArtifactPreview = React20.memo(function VideoArtifactPreview2({
|
|
19811
|
+
content,
|
|
19812
|
+
metadata,
|
|
19813
|
+
config
|
|
19814
|
+
}) {
|
|
19815
|
+
const { hdUrl: resolvedUrl } = useResolvedMediaUrl(content, {
|
|
19816
|
+
fileId: metadata?.fileId,
|
|
19817
|
+
type: "video",
|
|
19818
|
+
config
|
|
19819
|
+
});
|
|
19820
|
+
const videoRef = React20.useRef(null);
|
|
19821
|
+
const progressRef = React20.useRef(null);
|
|
19822
|
+
const [isPlaying, setIsPlaying] = React20.useState(false);
|
|
19823
|
+
const [isMuted, setIsMuted] = React20.useState(false);
|
|
19824
|
+
const [duration, setDuration] = React20.useState(0);
|
|
19825
|
+
const [currentTime, setCurrentTime] = React20.useState(0);
|
|
19826
|
+
const [volume, setVolume] = React20.useState(1);
|
|
19827
|
+
const [isLoaded, setIsLoaded] = React20.useState(false);
|
|
19828
|
+
const [showVolumeSlider, setShowVolumeSlider] = React20.useState(false);
|
|
19829
|
+
const [posterUrl, setPosterUrl] = React20.useState(null);
|
|
19830
|
+
const [isDraggingProgress, setIsDraggingProgress] = React20.useState(false);
|
|
19831
|
+
const generationParams = metadata?.generationParams;
|
|
19832
|
+
const toolName = metadata?.toolName;
|
|
19833
|
+
React20.useEffect(() => {
|
|
19834
|
+
const video = document.createElement("video");
|
|
19835
|
+
video.crossOrigin = "anonymous";
|
|
19836
|
+
video.preload = "metadata";
|
|
19837
|
+
video.muted = true;
|
|
19838
|
+
video.addEventListener("loadeddata", () => {
|
|
19839
|
+
video.currentTime = Math.min(0.5, video.duration * 0.1);
|
|
19840
|
+
});
|
|
19841
|
+
video.addEventListener("seeked", () => {
|
|
19842
|
+
try {
|
|
19843
|
+
const canvas = document.createElement("canvas");
|
|
19844
|
+
canvas.width = video.videoWidth;
|
|
19845
|
+
canvas.height = video.videoHeight;
|
|
19846
|
+
const ctx = canvas.getContext("2d");
|
|
19847
|
+
if (ctx) {
|
|
19848
|
+
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
|
|
19849
|
+
setPosterUrl(canvas.toDataURL("image/jpeg", 0.8));
|
|
19850
|
+
}
|
|
19851
|
+
} catch {
|
|
19852
|
+
}
|
|
19853
|
+
video.remove();
|
|
19854
|
+
});
|
|
19855
|
+
video.addEventListener("error", () => video.remove());
|
|
19856
|
+
video.src = resolvedUrl;
|
|
19857
|
+
video.load();
|
|
19858
|
+
return () => {
|
|
19859
|
+
video.remove();
|
|
19860
|
+
};
|
|
19861
|
+
}, [resolvedUrl]);
|
|
19862
|
+
const handleLoadedMetadata = () => {
|
|
19863
|
+
const video = videoRef.current;
|
|
19864
|
+
if (video) {
|
|
19865
|
+
setDuration(video.duration);
|
|
19866
|
+
setIsLoaded(true);
|
|
19867
|
+
}
|
|
19868
|
+
};
|
|
19869
|
+
const handleTimeUpdate = () => {
|
|
19870
|
+
if (!isDraggingProgress && videoRef.current) {
|
|
19871
|
+
setCurrentTime(videoRef.current.currentTime);
|
|
19872
|
+
}
|
|
19873
|
+
};
|
|
19874
|
+
const togglePlay = React20.useCallback(() => {
|
|
19875
|
+
const video = videoRef.current;
|
|
19876
|
+
if (!video) return;
|
|
19877
|
+
if (isPlaying) {
|
|
19878
|
+
video.pause();
|
|
19879
|
+
setIsPlaying(false);
|
|
19880
|
+
} else {
|
|
19881
|
+
video.play().then(() => setIsPlaying(true)).catch(() => {
|
|
19882
|
+
});
|
|
19883
|
+
}
|
|
19884
|
+
}, [isPlaying]);
|
|
19885
|
+
const toggleMute = React20.useCallback(() => {
|
|
19886
|
+
const video = videoRef.current;
|
|
19887
|
+
if (video) {
|
|
19888
|
+
video.muted = !isMuted;
|
|
19889
|
+
setIsMuted(!isMuted);
|
|
19890
|
+
}
|
|
19891
|
+
}, [isMuted]);
|
|
19892
|
+
const handleVolumeChange = React20.useCallback((e) => {
|
|
19893
|
+
const newVolume = parseFloat(e.target.value);
|
|
19894
|
+
setVolume(newVolume);
|
|
19895
|
+
if (videoRef.current) {
|
|
19896
|
+
videoRef.current.volume = newVolume;
|
|
19897
|
+
if (newVolume === 0) {
|
|
19898
|
+
setIsMuted(true);
|
|
19899
|
+
videoRef.current.muted = true;
|
|
19900
|
+
} else if (isMuted) {
|
|
19901
|
+
setIsMuted(false);
|
|
19902
|
+
videoRef.current.muted = false;
|
|
19903
|
+
}
|
|
19904
|
+
}
|
|
19905
|
+
}, [isMuted]);
|
|
19906
|
+
const handleProgressClick = React20.useCallback((e) => {
|
|
19907
|
+
const video = videoRef.current;
|
|
19908
|
+
const bar = progressRef.current;
|
|
19909
|
+
if (!video || !bar || !duration) return;
|
|
19910
|
+
const rect = bar.getBoundingClientRect();
|
|
19911
|
+
const ratio = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width));
|
|
19912
|
+
video.currentTime = ratio * duration;
|
|
19913
|
+
setCurrentTime(ratio * duration);
|
|
19914
|
+
}, [duration]);
|
|
19915
|
+
const handleProgressDrag = React20.useCallback((e) => {
|
|
19916
|
+
if (!isDraggingProgress) return;
|
|
19917
|
+
const bar = progressRef.current;
|
|
19918
|
+
if (!bar || !duration) return;
|
|
19919
|
+
const rect = bar.getBoundingClientRect();
|
|
19920
|
+
const ratio = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width));
|
|
19921
|
+
setCurrentTime(ratio * duration);
|
|
19922
|
+
}, [isDraggingProgress, duration]);
|
|
19923
|
+
const handleProgressDragEnd = React20.useCallback(() => {
|
|
19924
|
+
if (isDraggingProgress && videoRef.current) {
|
|
19925
|
+
videoRef.current.currentTime = currentTime;
|
|
19926
|
+
}
|
|
19927
|
+
setIsDraggingProgress(false);
|
|
19928
|
+
}, [isDraggingProgress, currentTime]);
|
|
19929
|
+
React20.useEffect(() => {
|
|
19930
|
+
if (!isDraggingProgress) return;
|
|
19931
|
+
const handleMouseUp = () => handleProgressDragEnd();
|
|
19932
|
+
const handleMouseMove = (e) => {
|
|
19933
|
+
const bar = progressRef.current;
|
|
19934
|
+
if (!bar || !duration) return;
|
|
19935
|
+
const rect = bar.getBoundingClientRect();
|
|
19936
|
+
const ratio = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width));
|
|
19937
|
+
setCurrentTime(ratio * duration);
|
|
19938
|
+
};
|
|
19939
|
+
window.addEventListener("mouseup", handleMouseUp);
|
|
19940
|
+
window.addEventListener("mousemove", handleMouseMove);
|
|
19941
|
+
return () => {
|
|
19942
|
+
window.removeEventListener("mouseup", handleMouseUp);
|
|
19943
|
+
window.removeEventListener("mousemove", handleMouseMove);
|
|
19944
|
+
};
|
|
19945
|
+
}, [isDraggingProgress, duration, handleProgressDragEnd]);
|
|
19946
|
+
const handleDownload = React20.useCallback(() => {
|
|
19947
|
+
const link2 = document.createElement("a");
|
|
19948
|
+
link2.href = resolvedUrl;
|
|
19949
|
+
link2.download = `video-${Date.now()}.mp4`;
|
|
19950
|
+
document.body.appendChild(link2);
|
|
19951
|
+
link2.click();
|
|
19952
|
+
document.body.removeChild(link2);
|
|
19953
|
+
}, [resolvedUrl]);
|
|
19954
|
+
const formatTime2 = (seconds) => {
|
|
19955
|
+
const mins = Math.floor(seconds / 60);
|
|
19956
|
+
const secs = Math.floor(seconds % 60);
|
|
19957
|
+
return `${mins}:${secs.toString().padStart(2, "0")}`;
|
|
19958
|
+
};
|
|
19959
|
+
const progressPercent = duration > 0 ? currentTime / duration * 100 : 0;
|
|
19960
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "h-full flex flex-col bg-zinc-950 agent-sdk-light:bg-white", children: [
|
|
19961
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 overflow-hidden flex items-center justify-center bg-black relative group/player", children: [
|
|
19962
|
+
posterUrl && !isPlaying && !currentTime && /* @__PURE__ */ jsxRuntime.jsx(
|
|
19963
|
+
"img",
|
|
19964
|
+
{
|
|
19965
|
+
src: posterUrl,
|
|
19966
|
+
alt: "Video cover",
|
|
19967
|
+
className: "absolute inset-0 w-full h-full object-contain z-[1]"
|
|
19968
|
+
}
|
|
19969
|
+
),
|
|
19970
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
19971
|
+
"video",
|
|
19972
|
+
{
|
|
19973
|
+
ref: videoRef,
|
|
19974
|
+
src: resolvedUrl,
|
|
19975
|
+
muted: isMuted,
|
|
19976
|
+
playsInline: true,
|
|
19977
|
+
preload: "metadata",
|
|
19978
|
+
onLoadedMetadata: handleLoadedMetadata,
|
|
19979
|
+
onTimeUpdate: handleTimeUpdate,
|
|
19980
|
+
onEnded: () => setIsPlaying(false),
|
|
19981
|
+
onClick: togglePlay,
|
|
19982
|
+
className: cn2(
|
|
19983
|
+
"max-w-full max-h-full object-contain cursor-pointer",
|
|
19984
|
+
!isPlaying && posterUrl && !currentTime && "opacity-0"
|
|
19985
|
+
)
|
|
19986
|
+
}
|
|
19987
|
+
),
|
|
19988
|
+
!isPlaying && /* @__PURE__ */ jsxRuntime.jsx(
|
|
19989
|
+
"div",
|
|
19990
|
+
{
|
|
19991
|
+
className: "absolute inset-0 z-[2] flex items-center justify-center cursor-pointer",
|
|
19992
|
+
onClick: togglePlay,
|
|
19993
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn2(
|
|
19994
|
+
"w-16 h-16 rounded-full bg-white/15 backdrop-blur-md",
|
|
19995
|
+
"flex items-center justify-center",
|
|
19996
|
+
"transition-all duration-200",
|
|
19997
|
+
"group-hover/player:scale-110 group-hover/player:bg-white/25",
|
|
19998
|
+
"shadow-2xl shadow-black/30"
|
|
19999
|
+
), 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" }) }) })
|
|
20000
|
+
}
|
|
20001
|
+
),
|
|
20002
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn2(
|
|
20003
|
+
"absolute bottom-0 left-0 right-0 z-[3]",
|
|
20004
|
+
"bg-gradient-to-t from-black/90 via-black/50 to-transparent",
|
|
20005
|
+
"px-4 pb-3 pt-10",
|
|
20006
|
+
"transition-opacity duration-300",
|
|
20007
|
+
"opacity-0 group-hover/player:opacity-100",
|
|
20008
|
+
isPlaying ? "" : "opacity-100"
|
|
20009
|
+
), children: [
|
|
20010
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20011
|
+
"div",
|
|
20012
|
+
{
|
|
20013
|
+
ref: progressRef,
|
|
20014
|
+
className: "w-full h-1.5 bg-white/20 rounded-full mb-3 cursor-pointer group/progress hover:h-2 transition-all",
|
|
20015
|
+
onClick: handleProgressClick,
|
|
20016
|
+
onMouseDown: () => setIsDraggingProgress(true),
|
|
20017
|
+
onMouseMove: handleProgressDrag,
|
|
20018
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
20019
|
+
"div",
|
|
20020
|
+
{
|
|
20021
|
+
className: "h-full bg-[#d8ff00] rounded-full relative",
|
|
20022
|
+
style: { width: `${progressPercent}%` },
|
|
20023
|
+
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" })
|
|
20024
|
+
}
|
|
20025
|
+
)
|
|
20026
|
+
}
|
|
20027
|
+
),
|
|
20028
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
20029
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
20030
|
+
/* @__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: [
|
|
20031
|
+
/* @__PURE__ */ jsxRuntime.jsx("rect", { x: "6", y: "4", width: "4", height: "16", rx: "1" }),
|
|
20032
|
+
/* @__PURE__ */ jsxRuntime.jsx("rect", { x: "14", y: "4", width: "4", height: "16", rx: "1" })
|
|
20033
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 5v14l11-7z" }) }) }),
|
|
20034
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
20035
|
+
"div",
|
|
20036
|
+
{
|
|
20037
|
+
className: "flex items-center gap-1.5 relative",
|
|
20038
|
+
onMouseEnter: () => setShowVolumeSlider(true),
|
|
20039
|
+
onMouseLeave: () => setShowVolumeSlider(false),
|
|
20040
|
+
children: [
|
|
20041
|
+
/* @__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: [
|
|
20042
|
+
/* @__PURE__ */ jsxRuntime.jsx("polygon", { points: "11 5 6 9 2 9 2 15 6 15 11 19 11 5" }),
|
|
20043
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "23", y1: "9", x2: "17", y2: "15" }),
|
|
20044
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "17", y1: "9", x2: "23", y2: "15" })
|
|
20045
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
20046
|
+
/* @__PURE__ */ jsxRuntime.jsx("polygon", { points: "11 5 6 9 2 9 2 15 6 15 11 19 11 5" }),
|
|
20047
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M19.07 4.93a10 10 0 0 1 0 14.14" }),
|
|
20048
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15.54 8.46a5 5 0 0 1 0 7.07" })
|
|
20049
|
+
] }) }),
|
|
20050
|
+
showVolumeSlider && /* @__PURE__ */ jsxRuntime.jsx(
|
|
20051
|
+
"input",
|
|
20052
|
+
{
|
|
20053
|
+
type: "range",
|
|
20054
|
+
min: "0",
|
|
20055
|
+
max: "1",
|
|
20056
|
+
step: "0.05",
|
|
20057
|
+
value: isMuted ? 0 : volume,
|
|
20058
|
+
onChange: handleVolumeChange,
|
|
20059
|
+
className: "w-20 h-1 appearance-none bg-white/20 rounded-full cursor-pointer accent-[#d8ff00]"
|
|
20060
|
+
}
|
|
20061
|
+
)
|
|
20062
|
+
]
|
|
20063
|
+
}
|
|
20064
|
+
),
|
|
20065
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-white/60 font-mono tabular-nums", children: [
|
|
20066
|
+
formatTime2(currentTime),
|
|
20067
|
+
" / ",
|
|
20068
|
+
formatTime2(duration)
|
|
20069
|
+
] })
|
|
20070
|
+
] }),
|
|
20071
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
20072
|
+
"button",
|
|
20073
|
+
{
|
|
20074
|
+
onClick: handleDownload,
|
|
20075
|
+
className: "p-1.5 text-white/60 hover:text-white transition-colors",
|
|
20076
|
+
title: "\u4E0B\u8F7D\u89C6\u9891",
|
|
20077
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Download, { size: 16 })
|
|
20078
|
+
}
|
|
20079
|
+
) })
|
|
20080
|
+
] })
|
|
20081
|
+
] })
|
|
20082
|
+
] }),
|
|
20083
|
+
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: [
|
|
20084
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mb-2", children: [
|
|
20085
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { size: 12, className: "text-[#d8ff00]" }),
|
|
20086
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-zinc-300 agent-sdk-light:text-zinc-700", children: toolName || "\u751F\u6210\u53C2\u6570" })
|
|
20087
|
+
] }),
|
|
20088
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-x-4 gap-y-1.5", children: Object.entries(generationParams).map(([key, value]) => {
|
|
20089
|
+
const displayValue = String(value);
|
|
20090
|
+
if (displayValue.length > 80) return null;
|
|
20091
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-xs", children: [
|
|
20092
|
+
/* @__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()) }),
|
|
20093
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-zinc-300 agent-sdk-light:text-zinc-700 font-mono", children: displayValue })
|
|
20094
|
+
] }, key);
|
|
20095
|
+
}) }),
|
|
20096
|
+
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: [
|
|
20097
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-zinc-500 agent-sdk-light:text-zinc-500 uppercase tracking-wider", children: "Prompt" }),
|
|
20098
|
+
/* @__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) })
|
|
20099
|
+
] })
|
|
20100
|
+
] }) })
|
|
20101
|
+
] });
|
|
20102
|
+
});
|
|
20103
|
+
function htmlToMarkdown(element) {
|
|
20104
|
+
const lines = [];
|
|
20105
|
+
function processNode(node2, listDepth = 0) {
|
|
20106
|
+
if (node2.nodeType === Node.TEXT_NODE) {
|
|
20107
|
+
return node2.textContent || "";
|
|
20108
|
+
}
|
|
20109
|
+
if (node2.nodeType !== Node.ELEMENT_NODE) return "";
|
|
20110
|
+
const el = node2;
|
|
20111
|
+
const tag = el.tagName.toLowerCase();
|
|
20112
|
+
const childContent = () => {
|
|
20113
|
+
let result = "";
|
|
20114
|
+
el.childNodes.forEach((child) => {
|
|
20115
|
+
result += processNode(child, listDepth);
|
|
20116
|
+
});
|
|
20117
|
+
return result;
|
|
20118
|
+
};
|
|
20119
|
+
switch (tag) {
|
|
20120
|
+
case "h1":
|
|
20121
|
+
return `# ${childContent().trim()}
|
|
20122
|
+
|
|
20123
|
+
`;
|
|
20124
|
+
case "h2":
|
|
20125
|
+
return `## ${childContent().trim()}
|
|
20126
|
+
|
|
20127
|
+
`;
|
|
20128
|
+
case "h3":
|
|
20129
|
+
return `### ${childContent().trim()}
|
|
20130
|
+
|
|
20131
|
+
`;
|
|
20132
|
+
case "h4":
|
|
20133
|
+
return `#### ${childContent().trim()}
|
|
20134
|
+
|
|
20135
|
+
`;
|
|
20136
|
+
case "h5":
|
|
20137
|
+
return `##### ${childContent().trim()}
|
|
20138
|
+
|
|
20139
|
+
`;
|
|
20140
|
+
case "h6":
|
|
20141
|
+
return `###### ${childContent().trim()}
|
|
20142
|
+
|
|
20143
|
+
`;
|
|
20144
|
+
case "p": {
|
|
20145
|
+
const inner = childContent().trim();
|
|
20146
|
+
return inner ? `${inner}
|
|
20147
|
+
|
|
20148
|
+
` : "\n";
|
|
20149
|
+
}
|
|
20150
|
+
case "br":
|
|
20151
|
+
return "\n";
|
|
20152
|
+
case "strong":
|
|
20153
|
+
case "b":
|
|
20154
|
+
return `**${childContent()}**`;
|
|
20155
|
+
case "em":
|
|
20156
|
+
case "i":
|
|
20157
|
+
return `*${childContent()}*`;
|
|
20158
|
+
case "del":
|
|
20159
|
+
case "s":
|
|
20160
|
+
return `~~${childContent()}~~`;
|
|
20161
|
+
case "code": {
|
|
20162
|
+
if (el.parentElement?.tagName.toLowerCase() === "pre") {
|
|
20163
|
+
return childContent();
|
|
20164
|
+
}
|
|
20165
|
+
return `\`${childContent()}\``;
|
|
20166
|
+
}
|
|
20167
|
+
case "pre": {
|
|
20168
|
+
const codeEl = el.querySelector("code");
|
|
20169
|
+
const codeContent = codeEl ? codeEl.textContent || "" : el.textContent || "";
|
|
20170
|
+
const langClass = codeEl?.className?.match(/language-(\w+)/);
|
|
20171
|
+
const lang = langClass ? langClass[1] : "";
|
|
20172
|
+
return `\`\`\`${lang}
|
|
20173
|
+
${codeContent.trim()}
|
|
20174
|
+
\`\`\`
|
|
20175
|
+
|
|
20176
|
+
`;
|
|
20177
|
+
}
|
|
20178
|
+
case "blockquote": {
|
|
20179
|
+
const inner = childContent().trim();
|
|
20180
|
+
return inner.split("\n").map((line) => `> ${line}`).join("\n") + "\n\n";
|
|
20181
|
+
}
|
|
20182
|
+
case "ul": {
|
|
20183
|
+
let result = "";
|
|
20184
|
+
el.childNodes.forEach((child) => {
|
|
20185
|
+
if (child.tagName?.toLowerCase() === "li") {
|
|
20186
|
+
const indent2 = " ".repeat(listDepth);
|
|
20187
|
+
const liContent = processListItem(child, listDepth);
|
|
20188
|
+
result += `${indent2}- ${liContent}
|
|
20189
|
+
`;
|
|
20190
|
+
}
|
|
20191
|
+
});
|
|
20192
|
+
return listDepth === 0 ? result + "\n" : result;
|
|
20193
|
+
}
|
|
20194
|
+
case "ol": {
|
|
20195
|
+
let result = "";
|
|
20196
|
+
let index = 1;
|
|
20197
|
+
el.childNodes.forEach((child) => {
|
|
20198
|
+
if (child.tagName?.toLowerCase() === "li") {
|
|
20199
|
+
const indent2 = " ".repeat(listDepth);
|
|
20200
|
+
const liContent = processListItem(child, listDepth);
|
|
20201
|
+
result += `${indent2}${index}. ${liContent}
|
|
20202
|
+
`;
|
|
20203
|
+
index++;
|
|
20204
|
+
}
|
|
20205
|
+
});
|
|
20206
|
+
return listDepth === 0 ? result + "\n" : result;
|
|
20207
|
+
}
|
|
20208
|
+
case "li": {
|
|
20209
|
+
return childContent();
|
|
20210
|
+
}
|
|
20211
|
+
case "a": {
|
|
20212
|
+
const href = el.getAttribute("href") || "";
|
|
20213
|
+
const text3 = childContent();
|
|
20214
|
+
return `[${text3}](${href})`;
|
|
20215
|
+
}
|
|
20216
|
+
case "img": {
|
|
20217
|
+
const src = el.getAttribute("src") || "";
|
|
20218
|
+
const alt = el.getAttribute("alt") || "";
|
|
20219
|
+
return ``;
|
|
20220
|
+
}
|
|
20221
|
+
case "hr":
|
|
20222
|
+
return "---\n\n";
|
|
20223
|
+
case "table": {
|
|
20224
|
+
return processTable(el) + "\n";
|
|
20225
|
+
}
|
|
20226
|
+
case "input": {
|
|
20227
|
+
if (el.getAttribute("type") === "checkbox") {
|
|
20228
|
+
return el.hasAttribute("checked") ? "[x] " : "[ ] ";
|
|
20229
|
+
}
|
|
20230
|
+
return "";
|
|
20231
|
+
}
|
|
20232
|
+
case "div":
|
|
20233
|
+
case "span":
|
|
20234
|
+
case "section":
|
|
20235
|
+
case "article":
|
|
20236
|
+
case "main":
|
|
20237
|
+
case "header":
|
|
20238
|
+
case "footer":
|
|
20239
|
+
return childContent();
|
|
20240
|
+
default:
|
|
20241
|
+
return childContent();
|
|
20242
|
+
}
|
|
20243
|
+
}
|
|
20244
|
+
function processListItem(li, depth, _ordered) {
|
|
20245
|
+
let textParts = [];
|
|
20246
|
+
let subLists = "";
|
|
20247
|
+
li.childNodes.forEach((child) => {
|
|
20248
|
+
const childTag = child.tagName?.toLowerCase();
|
|
20249
|
+
if (childTag === "ul" || childTag === "ol") {
|
|
20250
|
+
subLists += processNode(child, depth + 1);
|
|
20251
|
+
} else {
|
|
20252
|
+
textParts.push(processNode(child, depth));
|
|
20253
|
+
}
|
|
20254
|
+
});
|
|
20255
|
+
let result = textParts.join("").trim();
|
|
20256
|
+
if (subLists) {
|
|
20257
|
+
result += "\n" + subLists;
|
|
20258
|
+
}
|
|
20259
|
+
return result;
|
|
20260
|
+
}
|
|
20261
|
+
function processTable(table) {
|
|
20262
|
+
const rows = [];
|
|
20263
|
+
table.querySelectorAll("tr").forEach((tr) => {
|
|
20264
|
+
const cells = [];
|
|
20265
|
+
tr.querySelectorAll("th, td").forEach((cell) => {
|
|
20266
|
+
cells.push((cell.textContent || "").trim());
|
|
20267
|
+
});
|
|
20268
|
+
rows.push(cells);
|
|
20269
|
+
});
|
|
20270
|
+
if (rows.length === 0) return "";
|
|
20271
|
+
const colCount = Math.max(...rows.map((r3) => r3.length));
|
|
20272
|
+
const colWidths = Array(colCount).fill(3);
|
|
20273
|
+
rows.forEach((row) => {
|
|
20274
|
+
row.forEach((cell, i) => {
|
|
20275
|
+
colWidths[i] = Math.max(colWidths[i], cell.length);
|
|
20276
|
+
});
|
|
20277
|
+
});
|
|
20278
|
+
let result = "";
|
|
20279
|
+
rows.forEach((row, rowIndex) => {
|
|
20280
|
+
const paddedCells = Array(colCount).fill("").map((_, i) => {
|
|
20281
|
+
const cell = row[i] || "";
|
|
20282
|
+
return cell.padEnd(colWidths[i]);
|
|
20283
|
+
});
|
|
20284
|
+
result += `| ${paddedCells.join(" | ")} |
|
|
20285
|
+
`;
|
|
20286
|
+
if (rowIndex === 0) {
|
|
20287
|
+
const separators = colWidths.map((w) => "-".repeat(w));
|
|
20288
|
+
result += `| ${separators.join(" | ")} |
|
|
20289
|
+
`;
|
|
20290
|
+
}
|
|
20291
|
+
});
|
|
20292
|
+
return result;
|
|
20293
|
+
}
|
|
20294
|
+
element.childNodes.forEach((child) => {
|
|
20295
|
+
lines.push(processNode(child));
|
|
20296
|
+
});
|
|
20297
|
+
return lines.join("").replace(/\n{3,}/g, "\n\n").trim() + "\n";
|
|
20298
|
+
}
|
|
20299
|
+
var MarkdownEditor = React20.memo(function MarkdownEditor2({
|
|
20300
|
+
content,
|
|
20301
|
+
onChange,
|
|
20302
|
+
config
|
|
20303
|
+
}) {
|
|
20304
|
+
const editorRef = React20.useRef(null);
|
|
20305
|
+
const textareaRef = React20.useRef(null);
|
|
20306
|
+
const [isSourceMode, setIsSourceMode] = React20.useState(false);
|
|
20307
|
+
const isInternalUpdate = React20.useRef(false);
|
|
20308
|
+
const lastMarkdownRef = React20.useRef(content);
|
|
20309
|
+
const contentToHtml = React20.useCallback((markdown) => {
|
|
20310
|
+
return marked.marked.parse(markdown, { breaks: true, gfm: true });
|
|
20311
|
+
}, []);
|
|
20312
|
+
React20.useEffect(() => {
|
|
20313
|
+
if (isSourceMode) return;
|
|
20314
|
+
if (isInternalUpdate.current) {
|
|
20315
|
+
isInternalUpdate.current = false;
|
|
20316
|
+
return;
|
|
20317
|
+
}
|
|
20318
|
+
if (editorRef.current && content !== lastMarkdownRef.current) {
|
|
20319
|
+
const html2 = contentToHtml(content);
|
|
20320
|
+
editorRef.current.innerHTML = html2;
|
|
20321
|
+
lastMarkdownRef.current = content;
|
|
20322
|
+
}
|
|
20323
|
+
}, [content, isSourceMode, contentToHtml]);
|
|
20324
|
+
React20.useEffect(() => {
|
|
20325
|
+
if (editorRef.current && !isSourceMode) {
|
|
20326
|
+
const html2 = contentToHtml(content);
|
|
20327
|
+
editorRef.current.innerHTML = html2;
|
|
20328
|
+
}
|
|
20329
|
+
}, []);
|
|
20330
|
+
const handleInput = React20.useCallback(() => {
|
|
20331
|
+
if (!editorRef.current) return;
|
|
20332
|
+
const markdown = htmlToMarkdown(editorRef.current);
|
|
20333
|
+
lastMarkdownRef.current = markdown;
|
|
20334
|
+
isInternalUpdate.current = true;
|
|
20335
|
+
onChange(markdown);
|
|
20336
|
+
}, [onChange]);
|
|
20337
|
+
const execCommand = React20.useCallback((command, value) => {
|
|
20338
|
+
editorRef.current?.focus();
|
|
20339
|
+
document.execCommand(command, false, value);
|
|
20340
|
+
requestAnimationFrame(() => handleInput());
|
|
20341
|
+
}, [handleInput]);
|
|
20342
|
+
const formatBlock = React20.useCallback((tag) => {
|
|
20343
|
+
execCommand("formatBlock", tag);
|
|
20344
|
+
}, [execCommand]);
|
|
20345
|
+
const insertHorizontalRule = React20.useCallback(() => {
|
|
20346
|
+
execCommand("insertHorizontalRule");
|
|
20347
|
+
}, [execCommand]);
|
|
20348
|
+
const insertLink = React20.useCallback(() => {
|
|
20349
|
+
const selection = window.getSelection();
|
|
20350
|
+
const selectedText = selection?.toString() || "\u94FE\u63A5\u6587\u672C";
|
|
20351
|
+
const url = prompt("\u8BF7\u8F93\u5165\u94FE\u63A5\u5730\u5740:", "https://");
|
|
20352
|
+
if (url) {
|
|
20353
|
+
if (selection && selection.rangeCount > 0) {
|
|
20354
|
+
const range = selection.getRangeAt(0);
|
|
20355
|
+
range.deleteContents();
|
|
20356
|
+
const anchor = document.createElement("a");
|
|
20357
|
+
anchor.href = url;
|
|
20358
|
+
anchor.textContent = selectedText;
|
|
20359
|
+
range.insertNode(anchor);
|
|
20360
|
+
range.setStartAfter(anchor);
|
|
20361
|
+
range.collapse(true);
|
|
20362
|
+
selection.removeAllRanges();
|
|
20363
|
+
selection.addRange(range);
|
|
20364
|
+
}
|
|
20365
|
+
requestAnimationFrame(() => handleInput());
|
|
20366
|
+
}
|
|
20367
|
+
}, [handleInput]);
|
|
20368
|
+
const insertImage = React20.useCallback(() => {
|
|
20369
|
+
const url = prompt("\u8BF7\u8F93\u5165\u56FE\u7247\u5730\u5740:", "https://");
|
|
20370
|
+
if (url) {
|
|
20371
|
+
execCommand("insertImage", url);
|
|
20372
|
+
}
|
|
20373
|
+
}, [execCommand]);
|
|
20374
|
+
const insertCodeBlock = React20.useCallback(() => {
|
|
20375
|
+
const editor = editorRef.current;
|
|
20376
|
+
if (!editor) return;
|
|
20377
|
+
const selection = window.getSelection();
|
|
20378
|
+
if (selection && selection.rangeCount > 0) {
|
|
20379
|
+
const range = selection.getRangeAt(0);
|
|
20380
|
+
const pre = document.createElement("pre");
|
|
20381
|
+
const code3 = document.createElement("code");
|
|
20382
|
+
code3.textContent = selection.toString() || "\u4EE3\u7801\u5185\u5BB9";
|
|
20383
|
+
pre.appendChild(code3);
|
|
20384
|
+
range.deleteContents();
|
|
20385
|
+
range.insertNode(pre);
|
|
20386
|
+
const paragraph2 = document.createElement("p");
|
|
20387
|
+
paragraph2.innerHTML = "<br>";
|
|
20388
|
+
pre.parentNode?.insertBefore(paragraph2, pre.nextSibling);
|
|
20389
|
+
range.setStart(paragraph2, 0);
|
|
20390
|
+
range.collapse(true);
|
|
20391
|
+
selection.removeAllRanges();
|
|
20392
|
+
selection.addRange(range);
|
|
20393
|
+
}
|
|
20394
|
+
requestAnimationFrame(() => handleInput());
|
|
20395
|
+
}, [handleInput]);
|
|
20396
|
+
const handleKeyDown = React20.useCallback((e) => {
|
|
20397
|
+
const isMod = e.metaKey || e.ctrlKey;
|
|
20398
|
+
if (isMod && e.key === "b") {
|
|
20399
|
+
e.preventDefault();
|
|
20400
|
+
execCommand("bold");
|
|
20401
|
+
} else if (isMod && e.key === "i") {
|
|
20402
|
+
e.preventDefault();
|
|
20403
|
+
execCommand("italic");
|
|
20404
|
+
} else if (isMod && e.key === "u") {
|
|
20405
|
+
e.preventDefault();
|
|
20406
|
+
execCommand("underline");
|
|
20407
|
+
} else if (isMod && e.key === "e") {
|
|
20408
|
+
e.preventDefault();
|
|
20409
|
+
const selection = window.getSelection();
|
|
20410
|
+
if (selection && selection.rangeCount > 0) {
|
|
20411
|
+
const selectedText = selection.toString() || "code";
|
|
20412
|
+
execCommand("insertHTML", `<code>${selectedText}</code>`);
|
|
20413
|
+
}
|
|
20414
|
+
} else if (e.key === "Tab") {
|
|
20415
|
+
e.preventDefault();
|
|
20416
|
+
execCommand("insertHTML", " ");
|
|
20417
|
+
}
|
|
20418
|
+
}, [execCommand]);
|
|
20419
|
+
const handleSourceKeyDown = React20.useCallback((e) => {
|
|
20420
|
+
if (e.key === "Tab") {
|
|
20421
|
+
e.preventDefault();
|
|
20422
|
+
const textarea = e.currentTarget;
|
|
20423
|
+
const start = textarea.selectionStart;
|
|
20424
|
+
const end = textarea.selectionEnd;
|
|
20425
|
+
const newValue = content.substring(0, start) + " " + content.substring(end);
|
|
20426
|
+
onChange(newValue);
|
|
20427
|
+
requestAnimationFrame(() => {
|
|
20428
|
+
textarea.selectionStart = textarea.selectionEnd = start + 2;
|
|
20429
|
+
});
|
|
20430
|
+
}
|
|
20431
|
+
}, [content, onChange]);
|
|
20432
|
+
const toggleSourceMode = React20.useCallback(() => {
|
|
20433
|
+
if (isSourceMode) {
|
|
20434
|
+
setIsSourceMode(false);
|
|
20435
|
+
requestAnimationFrame(() => {
|
|
20436
|
+
if (editorRef.current) {
|
|
20437
|
+
const html2 = contentToHtml(content);
|
|
20438
|
+
editorRef.current.innerHTML = html2;
|
|
20439
|
+
lastMarkdownRef.current = content;
|
|
20440
|
+
}
|
|
20441
|
+
});
|
|
20442
|
+
} else {
|
|
20443
|
+
if (editorRef.current) {
|
|
20444
|
+
const markdown = htmlToMarkdown(editorRef.current);
|
|
20445
|
+
lastMarkdownRef.current = markdown;
|
|
20446
|
+
isInternalUpdate.current = true;
|
|
20447
|
+
onChange(markdown);
|
|
20448
|
+
}
|
|
20449
|
+
setIsSourceMode(true);
|
|
20450
|
+
}
|
|
20451
|
+
}, [isSourceMode, content, contentToHtml, onChange]);
|
|
20452
|
+
const toolbarGroups = React20.useMemo(() => [
|
|
20453
|
+
{
|
|
20454
|
+
items: [
|
|
20455
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-bold text-[11px]", children: "B" }), label: "\u52A0\u7C97 (\u2318B)", onClick: () => execCommand("bold") },
|
|
20456
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "italic text-[11px]", children: "I" }), label: "\u659C\u4F53 (\u2318I)", onClick: () => execCommand("italic") },
|
|
20457
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "line-through text-[11px]", children: "S" }), label: "\u5220\u9664\u7EBF", onClick: () => execCommand("strikeThrough") },
|
|
20458
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Code2, { size: 13 }), label: "\u884C\u5185\u4EE3\u7801 (\u2318E)", onClick: () => {
|
|
20459
|
+
const selection = window.getSelection();
|
|
20460
|
+
const text3 = selection?.toString() || "code";
|
|
20461
|
+
execCommand("insertHTML", `<code>${text3}</code>`);
|
|
20462
|
+
} }
|
|
20463
|
+
]
|
|
20464
|
+
},
|
|
20465
|
+
{
|
|
20466
|
+
items: [
|
|
20467
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] font-bold", children: "H1" }), label: "\u4E00\u7EA7\u6807\u9898", onClick: () => formatBlock("h1") },
|
|
20468
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] font-bold", children: "H2" }), label: "\u4E8C\u7EA7\u6807\u9898", onClick: () => formatBlock("h2") },
|
|
20469
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] font-bold", children: "H3" }), label: "\u4E09\u7EA7\u6807\u9898", onClick: () => formatBlock("h3") }
|
|
20470
|
+
]
|
|
20471
|
+
},
|
|
20472
|
+
{
|
|
20473
|
+
items: [
|
|
20474
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px]", children: "\u2022" }), label: "\u65E0\u5E8F\u5217\u8868", onClick: () => execCommand("insertUnorderedList") },
|
|
20475
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px]", children: "1." }), label: "\u6709\u5E8F\u5217\u8868", onClick: () => execCommand("insertOrderedList") },
|
|
20476
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px]", children: "\u275D" }), label: "\u5F15\u7528", onClick: () => formatBlock("blockquote") }
|
|
20477
|
+
]
|
|
20478
|
+
},
|
|
20479
|
+
{
|
|
20480
|
+
items: [
|
|
20481
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px]", children: "\u2014" }), label: "\u5206\u5272\u7EBF", onClick: insertHorizontalRule },
|
|
20482
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Globe, { size: 13 }), label: "\u94FE\u63A5", onClick: insertLink },
|
|
20483
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileImage, { size: 13 }), label: "\u56FE\u7247", onClick: insertImage },
|
|
20484
|
+
{ icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Code2, { size: 13, className: "opacity-60" }), label: "\u4EE3\u7801\u5757", onClick: insertCodeBlock }
|
|
20485
|
+
]
|
|
20486
|
+
}
|
|
20487
|
+
], [execCommand, formatBlock, insertHorizontalRule, insertLink, insertImage, insertCodeBlock]);
|
|
20488
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "h-full flex flex-col bg-zinc-950 agent-sdk-light:bg-white", children: [
|
|
20489
|
+
/* @__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: [
|
|
20490
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 mr-2", children: [
|
|
20491
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, { size: 12, className: "text-[#d8ff00]" }),
|
|
20492
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] text-[#d8ff00] font-medium whitespace-nowrap", children: isSourceMode ? "Markdown \u6E90\u7801" : "\u5BCC\u6587\u672C\u7F16\u8F91" })
|
|
20493
|
+
] }),
|
|
20494
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-4 w-px bg-zinc-700/50 agent-sdk-light:bg-zinc-300 mx-1" }),
|
|
20495
|
+
!isSourceMode && toolbarGroups.map((group, groupIndex) => /* @__PURE__ */ jsxRuntime.jsxs(React20__namespace.default.Fragment, { children: [
|
|
20496
|
+
group.items.map((action, actionIndex) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
20497
|
+
"button",
|
|
20498
|
+
{
|
|
20499
|
+
onClick: action.onClick,
|
|
20500
|
+
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",
|
|
20501
|
+
title: action.label,
|
|
20502
|
+
children: action.icon
|
|
20503
|
+
},
|
|
20504
|
+
actionIndex
|
|
20505
|
+
)),
|
|
20506
|
+
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" })
|
|
20507
|
+
] }, groupIndex)),
|
|
20508
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-4 w-px bg-zinc-700/50 agent-sdk-light:bg-zinc-300 mx-1 ml-auto" }),
|
|
20509
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
20510
|
+
"button",
|
|
20511
|
+
{
|
|
20512
|
+
onClick: toggleSourceMode,
|
|
20513
|
+
className: cn2(
|
|
20514
|
+
"p-1.5 flex items-center gap-1 text-[11px] rounded transition-colors whitespace-nowrap",
|
|
20515
|
+
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"
|
|
20516
|
+
),
|
|
20517
|
+
title: isSourceMode ? "\u5207\u6362\u5230\u5BCC\u6587\u672C\u6A21\u5F0F" : "\u5207\u6362\u5230\u6E90\u7801\u6A21\u5F0F",
|
|
20518
|
+
children: [
|
|
20519
|
+
isSourceMode ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Eye, { size: 13 }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Code2, { size: 13 }),
|
|
20520
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:inline", children: isSourceMode ? "\u5BCC\u6587\u672C" : "\u6E90\u7801" })
|
|
20521
|
+
]
|
|
20522
|
+
}
|
|
20523
|
+
)
|
|
20524
|
+
] }),
|
|
20525
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-h-0 overflow-hidden", children: isSourceMode ? (
|
|
20526
|
+
/* 源码编辑模式 */
|
|
20527
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20528
|
+
"textarea",
|
|
20529
|
+
{
|
|
20530
|
+
ref: textareaRef,
|
|
20531
|
+
value: content,
|
|
20532
|
+
onChange: (e) => onChange(e.target.value),
|
|
20533
|
+
onKeyDown: handleSourceKeyDown,
|
|
20534
|
+
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",
|
|
20535
|
+
style: { fontFamily: '"SF Mono", "Fira Code", "JetBrains Mono", Menlo, Monaco, monospace' },
|
|
20536
|
+
spellCheck: false,
|
|
20537
|
+
autoComplete: "off",
|
|
20538
|
+
autoCorrect: "off",
|
|
20539
|
+
autoCapitalize: "off",
|
|
20540
|
+
placeholder: "\u7F16\u5199 Markdown \u6E90\u7801..."
|
|
20541
|
+
}
|
|
20542
|
+
)
|
|
20543
|
+
) : (
|
|
20544
|
+
/* WYSIWYG 富文本编辑模式 */
|
|
20545
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20546
|
+
"div",
|
|
20547
|
+
{
|
|
20548
|
+
ref: editorRef,
|
|
20549
|
+
contentEditable: true,
|
|
20550
|
+
suppressContentEditableWarning: true,
|
|
20551
|
+
onInput: handleInput,
|
|
20552
|
+
onKeyDown: handleKeyDown,
|
|
20553
|
+
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",
|
|
20554
|
+
"data-placeholder": "\u5F00\u59CB\u7F16\u5199\u5185\u5BB9..."
|
|
20555
|
+
}
|
|
20556
|
+
)
|
|
20557
|
+
) })
|
|
20558
|
+
] });
|
|
20559
|
+
});
|
|
20560
|
+
var ArtifactThumbnail = React20.memo(function ArtifactThumbnail2({
|
|
20561
|
+
artifact,
|
|
20562
|
+
config
|
|
20563
|
+
}) {
|
|
20564
|
+
const typeConf = artifactTypeConfig[artifact.type] || artifactTypeConfig.text;
|
|
20565
|
+
const TypeIcon = typeConf.icon;
|
|
20566
|
+
const isMedia = artifact.type === "image" || artifact.type === "video";
|
|
20567
|
+
const thumbnailUrl = useResolvedThumbnailUrl(
|
|
20568
|
+
artifact.currentContent,
|
|
20569
|
+
{
|
|
20570
|
+
fileId: artifact.metadata?.fileId,
|
|
20571
|
+
type: artifact.type,
|
|
20572
|
+
config,
|
|
20573
|
+
enabled: isMedia
|
|
20574
|
+
}
|
|
20575
|
+
);
|
|
20576
|
+
if (isMedia && thumbnailUrl) {
|
|
20577
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
20578
|
+
"img",
|
|
20579
|
+
{
|
|
20580
|
+
src: thumbnailUrl,
|
|
20581
|
+
alt: "",
|
|
20582
|
+
className: "w-6 h-6 rounded object-cover flex-shrink-0",
|
|
20583
|
+
loading: "lazy"
|
|
20584
|
+
}
|
|
20585
|
+
);
|
|
20586
|
+
}
|
|
20587
|
+
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 }) });
|
|
20588
|
+
});
|
|
20589
|
+
var ArtifactTabs = React20.memo(function ArtifactTabs2({
|
|
20590
|
+
artifacts,
|
|
20591
|
+
activeId,
|
|
20592
|
+
onSwitch,
|
|
20593
|
+
onClose,
|
|
20594
|
+
onReorder,
|
|
20595
|
+
config
|
|
20596
|
+
}) {
|
|
20597
|
+
const scrollContainerRef = React20.useRef(null);
|
|
20598
|
+
const [canScrollLeft, setCanScrollLeft] = React20.useState(false);
|
|
20599
|
+
const [canScrollRight, setCanScrollRight] = React20.useState(false);
|
|
20600
|
+
const [showAllPanel, setShowAllPanel] = React20.useState(false);
|
|
20601
|
+
const allPanelRef = React20.useRef(null);
|
|
20602
|
+
const [dragState, setDragState] = React20.useState({ draggingId: null, dragOverId: null, dragStartX: 0, isDragging: false });
|
|
20603
|
+
const checkScrollState = React20.useCallback(() => {
|
|
20604
|
+
const container = scrollContainerRef.current;
|
|
20605
|
+
if (!container) return;
|
|
20606
|
+
setCanScrollLeft(container.scrollLeft > 2);
|
|
20607
|
+
setCanScrollRight(container.scrollLeft < container.scrollWidth - container.clientWidth - 2);
|
|
20608
|
+
}, []);
|
|
20609
|
+
React20.useEffect(() => {
|
|
20610
|
+
checkScrollState();
|
|
20611
|
+
const container = scrollContainerRef.current;
|
|
20612
|
+
if (!container) return;
|
|
20613
|
+
container.addEventListener("scroll", checkScrollState, { passive: true });
|
|
20614
|
+
const resizeObserver = new ResizeObserver(checkScrollState);
|
|
20615
|
+
resizeObserver.observe(container);
|
|
20616
|
+
return () => {
|
|
20617
|
+
container.removeEventListener("scroll", checkScrollState);
|
|
20618
|
+
resizeObserver.disconnect();
|
|
20619
|
+
};
|
|
20620
|
+
}, [checkScrollState, artifacts.length]);
|
|
20621
|
+
React20.useEffect(() => {
|
|
20622
|
+
if (!showAllPanel) return;
|
|
20623
|
+
const handleClickOutside = (e) => {
|
|
20624
|
+
if (allPanelRef.current && !allPanelRef.current.contains(e.target)) {
|
|
20625
|
+
setShowAllPanel(false);
|
|
20626
|
+
}
|
|
20627
|
+
};
|
|
20628
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
20629
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
20630
|
+
}, [showAllPanel]);
|
|
20631
|
+
const scrollBy = React20.useCallback((direction) => {
|
|
20632
|
+
const container = scrollContainerRef.current;
|
|
20633
|
+
if (!container) return;
|
|
20634
|
+
const scrollAmount = 200;
|
|
20635
|
+
container.scrollBy({
|
|
20636
|
+
left: direction === "left" ? -scrollAmount : scrollAmount,
|
|
20637
|
+
behavior: "smooth"
|
|
20638
|
+
});
|
|
20639
|
+
}, []);
|
|
20640
|
+
const handleDragStart = React20.useCallback((e, artifactId) => {
|
|
20641
|
+
e.dataTransfer.effectAllowed = "move";
|
|
20642
|
+
e.dataTransfer.setData("text/plain", artifactId);
|
|
20643
|
+
setDragState((prev) => ({ ...prev, draggingId: artifactId, dragStartX: e.clientX, isDragging: true }));
|
|
20644
|
+
}, []);
|
|
20645
|
+
const handleDragOver = React20.useCallback((e, artifactId) => {
|
|
20646
|
+
e.preventDefault();
|
|
20647
|
+
e.dataTransfer.dropEffect = "move";
|
|
20648
|
+
setDragState((prev) => ({ ...prev, dragOverId: artifactId }));
|
|
20649
|
+
}, []);
|
|
20650
|
+
const handleDragEnd = React20.useCallback(() => {
|
|
20651
|
+
setDragState({ draggingId: null, dragOverId: null, dragStartX: 0, isDragging: false });
|
|
20652
|
+
}, []);
|
|
20653
|
+
const handleDrop = React20.useCallback((e, targetId) => {
|
|
20654
|
+
e.preventDefault();
|
|
20655
|
+
const sourceId = e.dataTransfer.getData("text/plain");
|
|
20656
|
+
if (!sourceId || sourceId === targetId || !onReorder) {
|
|
20657
|
+
handleDragEnd();
|
|
20658
|
+
return;
|
|
20659
|
+
}
|
|
20660
|
+
const fromIndex = artifacts.findIndex((a) => a.id === sourceId);
|
|
20661
|
+
const toIndex = artifacts.findIndex((a) => a.id === targetId);
|
|
20662
|
+
if (fromIndex !== -1 && toIndex !== -1 && fromIndex !== toIndex) {
|
|
20663
|
+
onReorder(fromIndex, toIndex);
|
|
20664
|
+
}
|
|
20665
|
+
handleDragEnd();
|
|
20666
|
+
}, [artifacts, onReorder, handleDragEnd]);
|
|
20667
|
+
const handleCloseTab = React20.useCallback((e, artifactId) => {
|
|
20668
|
+
e.stopPropagation();
|
|
20669
|
+
if (!onClose) return;
|
|
20670
|
+
if (artifactId === activeId && artifacts.length > 1) {
|
|
20671
|
+
const currentIndex = artifacts.findIndex((a) => a.id === artifactId);
|
|
20672
|
+
const nextIndex = currentIndex < artifacts.length - 1 ? currentIndex + 1 : currentIndex - 1;
|
|
20673
|
+
if (nextIndex >= 0 && nextIndex < artifacts.length) {
|
|
20674
|
+
onSwitch(artifacts[nextIndex].id);
|
|
20675
|
+
}
|
|
20676
|
+
}
|
|
20677
|
+
onClose(artifactId);
|
|
20678
|
+
}, [onClose, activeId, artifacts, onSwitch]);
|
|
20679
|
+
if (artifacts.length <= 1) return null;
|
|
20680
|
+
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: [
|
|
20681
|
+
canScrollLeft && /* @__PURE__ */ jsxRuntime.jsx(
|
|
20682
|
+
"button",
|
|
20683
|
+
{
|
|
20684
|
+
onClick: () => scrollBy("left"),
|
|
20685
|
+
className: "flex-shrink-0 p-1 text-zinc-500 hover:text-zinc-300 hover:bg-zinc-800/50 transition-colors z-10",
|
|
20686
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeft, { size: 14 })
|
|
20687
|
+
}
|
|
20688
|
+
),
|
|
20689
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20690
|
+
"div",
|
|
20691
|
+
{
|
|
20692
|
+
ref: scrollContainerRef,
|
|
20693
|
+
className: "flex items-center gap-0.5 px-1 py-1 overflow-x-auto flex-1 min-w-0",
|
|
20694
|
+
style: { scrollbarWidth: "none", msOverflowStyle: "none" },
|
|
20695
|
+
children: artifacts.map((artifact) => {
|
|
20696
|
+
const typeConf = artifactTypeConfig[artifact.type] || artifactTypeConfig.text;
|
|
20697
|
+
const isActive = artifact.id === activeId;
|
|
20698
|
+
const isDragging = dragState.draggingId === artifact.id;
|
|
20699
|
+
const isDragOver = dragState.dragOverId === artifact.id && dragState.draggingId !== artifact.id;
|
|
20700
|
+
const TypeIcon = typeConf.icon;
|
|
20701
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
20702
|
+
"div",
|
|
20703
|
+
{
|
|
20704
|
+
draggable: !!onReorder,
|
|
20705
|
+
onDragStart: (e) => handleDragStart(e, artifact.id),
|
|
20706
|
+
onDragOver: (e) => handleDragOver(e, artifact.id),
|
|
20707
|
+
onDragEnd: handleDragEnd,
|
|
20708
|
+
onDrop: (e) => handleDrop(e, artifact.id),
|
|
20709
|
+
onClick: () => onSwitch(artifact.id),
|
|
20710
|
+
className: cn2(
|
|
20711
|
+
"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",
|
|
20712
|
+
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",
|
|
20713
|
+
isDragging && "opacity-40",
|
|
20714
|
+
isDragOver && "ring-1 ring-[#d8ff00]/50",
|
|
20715
|
+
onReorder && "cursor-grab active:cursor-grabbing"
|
|
20716
|
+
),
|
|
20717
|
+
title: artifact.title,
|
|
20718
|
+
children: [
|
|
20719
|
+
/* @__PURE__ */ jsxRuntime.jsx(TypeIcon, { size: 12, className: cn2("flex-shrink-0", isActive ? typeConf.color : "") }),
|
|
20720
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "max-w-[120px] truncate", children: artifact.title }),
|
|
20721
|
+
onClose && /* @__PURE__ */ jsxRuntime.jsx(
|
|
20722
|
+
"button",
|
|
20723
|
+
{
|
|
20724
|
+
onClick: (e) => handleCloseTab(e, artifact.id),
|
|
20725
|
+
className: cn2(
|
|
20726
|
+
"ml-0.5 p-0.5 rounded transition-colors flex-shrink-0",
|
|
20727
|
+
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"
|
|
20728
|
+
),
|
|
20729
|
+
title: "\u5173\u95ED",
|
|
20730
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 10 })
|
|
20731
|
+
}
|
|
20732
|
+
)
|
|
20733
|
+
]
|
|
20734
|
+
},
|
|
20735
|
+
artifact.id
|
|
20736
|
+
);
|
|
20737
|
+
})
|
|
20738
|
+
}
|
|
20739
|
+
),
|
|
20740
|
+
canScrollRight && /* @__PURE__ */ jsxRuntime.jsx(
|
|
20741
|
+
"button",
|
|
20742
|
+
{
|
|
20743
|
+
onClick: () => scrollBy("right"),
|
|
20744
|
+
className: "flex-shrink-0 p-1 text-zinc-500 hover:text-zinc-300 hover:bg-zinc-800/50 transition-colors z-10",
|
|
20745
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { size: 14 })
|
|
20746
|
+
}
|
|
20747
|
+
),
|
|
20748
|
+
artifacts.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex-shrink-0", ref: allPanelRef, children: [
|
|
20749
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20750
|
+
"button",
|
|
20751
|
+
{
|
|
20752
|
+
onClick: () => setShowAllPanel((prev) => !prev),
|
|
20753
|
+
className: cn2(
|
|
20754
|
+
"p-1.5 mr-1 text-zinc-500 hover:text-zinc-300 hover:bg-zinc-800/50 rounded transition-colors",
|
|
20755
|
+
showAllPanel && "bg-zinc-800 text-zinc-300"
|
|
20756
|
+
),
|
|
20757
|
+
title: "\u5168\u90E8\u4EA7\u7269",
|
|
20758
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.LayoutGrid, { size: 14 })
|
|
20759
|
+
}
|
|
20760
|
+
),
|
|
20761
|
+
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: [
|
|
20762
|
+
/* @__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: [
|
|
20763
|
+
"\u5168\u90E8\u4EA7\u7269 (",
|
|
20764
|
+
artifacts.length,
|
|
20765
|
+
")"
|
|
20766
|
+
] }) }),
|
|
20767
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-1.5 grid grid-cols-1 gap-0.5", children: artifacts.map((artifact) => {
|
|
20768
|
+
const typeConf = artifactTypeConfig[artifact.type] || artifactTypeConfig.text;
|
|
20769
|
+
const isActive = artifact.id === activeId;
|
|
20770
|
+
typeConf.icon;
|
|
20771
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
20772
|
+
"button",
|
|
20773
|
+
{
|
|
20774
|
+
onClick: () => {
|
|
20775
|
+
onSwitch(artifact.id);
|
|
20776
|
+
setShowAllPanel(false);
|
|
20777
|
+
},
|
|
20778
|
+
className: cn2(
|
|
20779
|
+
"flex items-center gap-2.5 px-2.5 py-2 text-xs rounded-md transition-all w-full text-left",
|
|
20780
|
+
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"
|
|
20781
|
+
),
|
|
20782
|
+
children: [
|
|
20783
|
+
/* @__PURE__ */ jsxRuntime.jsx(ArtifactThumbnail, { artifact, config }),
|
|
20784
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
20785
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "truncate font-medium", children: artifact.title }),
|
|
20786
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-[10px] text-zinc-600 agent-sdk-light:text-zinc-500 mt-0.5", children: [
|
|
20787
|
+
typeConf.label,
|
|
20788
|
+
artifact.language && artifact.language !== artifact.type && ` \u2022 ${artifact.language}`
|
|
20789
|
+
] })
|
|
20790
|
+
] }),
|
|
20791
|
+
onClose && /* @__PURE__ */ jsxRuntime.jsx(
|
|
20792
|
+
"button",
|
|
20793
|
+
{
|
|
20794
|
+
onClick: (e) => {
|
|
20795
|
+
e.stopPropagation();
|
|
20796
|
+
handleCloseTab(e, artifact.id);
|
|
20797
|
+
},
|
|
20798
|
+
className: "p-1 text-zinc-600 hover:text-zinc-300 hover:bg-zinc-700 rounded transition-colors flex-shrink-0",
|
|
20799
|
+
title: "\u5173\u95ED",
|
|
20800
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 12 })
|
|
20801
|
+
}
|
|
20802
|
+
)
|
|
20803
|
+
]
|
|
20804
|
+
},
|
|
20805
|
+
artifact.id
|
|
20806
|
+
);
|
|
20807
|
+
}) })
|
|
20808
|
+
] })
|
|
20809
|
+
] })
|
|
20810
|
+
] });
|
|
20811
|
+
});
|
|
18821
20812
|
var ArtifactViewer = React20.memo(function ArtifactViewer2({
|
|
18822
20813
|
artifact,
|
|
18823
20814
|
isOpen,
|
|
@@ -18826,41 +20817,127 @@ var ArtifactViewer = React20.memo(function ArtifactViewer2({
|
|
|
18826
20817
|
defaultView = "preview",
|
|
18827
20818
|
isFullscreen,
|
|
18828
20819
|
onFullscreenToggle,
|
|
18829
|
-
embedded = false
|
|
20820
|
+
embedded = false,
|
|
20821
|
+
artifacts = [],
|
|
20822
|
+
activeArtifactId,
|
|
20823
|
+
onSwitchArtifact,
|
|
20824
|
+
onCloseArtifact,
|
|
20825
|
+
onReorderArtifacts,
|
|
20826
|
+
onContentChange,
|
|
20827
|
+
onSave
|
|
18830
20828
|
}) {
|
|
18831
20829
|
const [viewMode, setViewMode] = React20.useState(defaultView);
|
|
20830
|
+
const [isEditing, setIsEditing] = React20.useState(false);
|
|
20831
|
+
const [editContent, setEditContent] = React20.useState("");
|
|
20832
|
+
const [undoStack, setUndoStack] = React20.useState([]);
|
|
20833
|
+
const [redoStack, setRedoStack] = React20.useState([]);
|
|
18832
20834
|
React20.useEffect(() => {
|
|
18833
20835
|
if (artifact) {
|
|
18834
|
-
if (artifact.type === "html" || artifact.type === "markdown") {
|
|
20836
|
+
if (artifact.type === "html" || artifact.type === "markdown" || artifact.type === "svg") {
|
|
18835
20837
|
setViewMode("preview");
|
|
18836
20838
|
} else {
|
|
18837
20839
|
setViewMode("code");
|
|
18838
20840
|
}
|
|
20841
|
+
setIsEditing(false);
|
|
20842
|
+
setEditContent(artifact.content);
|
|
20843
|
+
setUndoStack([]);
|
|
20844
|
+
setRedoStack([]);
|
|
18839
20845
|
}
|
|
18840
20846
|
}, [artifact?.id]);
|
|
20847
|
+
React20.useEffect(() => {
|
|
20848
|
+
if (artifact && !isEditing) {
|
|
20849
|
+
setEditContent(artifact.content);
|
|
20850
|
+
}
|
|
20851
|
+
}, [artifact?.content, isEditing]);
|
|
18841
20852
|
if (!artifact) return null;
|
|
18842
|
-
const typeConfig = artifactTypeConfig[artifact.type];
|
|
18843
|
-
const canPreview = artifact.type === "html" || artifact.type === "markdown";
|
|
20853
|
+
const typeConfig = artifactTypeConfig[artifact.type] || artifactTypeConfig.text;
|
|
20854
|
+
const canPreview = artifact.type === "html" || artifact.type === "markdown" || artifact.type === "svg";
|
|
20855
|
+
const canEdit = artifact.type !== "image" && artifact.type !== "video";
|
|
20856
|
+
const handleStartEdit = () => {
|
|
20857
|
+
setEditContent(artifact.content);
|
|
20858
|
+
setUndoStack([artifact.content]);
|
|
20859
|
+
setRedoStack([]);
|
|
20860
|
+
setIsEditing(true);
|
|
20861
|
+
setViewMode("code");
|
|
20862
|
+
};
|
|
20863
|
+
const handleEditChange = (newContent) => {
|
|
20864
|
+
setUndoStack((prev) => [...prev, editContent]);
|
|
20865
|
+
setRedoStack([]);
|
|
20866
|
+
setEditContent(newContent);
|
|
20867
|
+
onContentChange?.(newContent);
|
|
20868
|
+
};
|
|
20869
|
+
const handleUndo = () => {
|
|
20870
|
+
if (undoStack.length === 0) return;
|
|
20871
|
+
const previous2 = undoStack[undoStack.length - 1];
|
|
20872
|
+
setUndoStack((prev) => prev.slice(0, -1));
|
|
20873
|
+
setRedoStack((prev) => [...prev, editContent]);
|
|
20874
|
+
setEditContent(previous2);
|
|
20875
|
+
onContentChange?.(previous2);
|
|
20876
|
+
};
|
|
20877
|
+
const handleRedo = () => {
|
|
20878
|
+
if (redoStack.length === 0) return;
|
|
20879
|
+
const next = redoStack[redoStack.length - 1];
|
|
20880
|
+
setRedoStack((prev) => prev.slice(0, -1));
|
|
20881
|
+
setUndoStack((prev) => [...prev, editContent]);
|
|
20882
|
+
setEditContent(next);
|
|
20883
|
+
onContentChange?.(next);
|
|
20884
|
+
};
|
|
20885
|
+
const handleSave = () => {
|
|
20886
|
+
onSave?.(artifact.id, editContent);
|
|
20887
|
+
setIsEditing(false);
|
|
20888
|
+
};
|
|
20889
|
+
const handleCancelEdit = () => {
|
|
20890
|
+
setEditContent(artifact.content);
|
|
20891
|
+
setIsEditing(false);
|
|
20892
|
+
};
|
|
20893
|
+
const displayContent = isEditing ? editContent : artifact.content;
|
|
18844
20894
|
const renderContent = () => {
|
|
20895
|
+
if (isEditing) {
|
|
20896
|
+
if (artifact.type === "markdown") {
|
|
20897
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
20898
|
+
MarkdownEditor,
|
|
20899
|
+
{
|
|
20900
|
+
content: editContent,
|
|
20901
|
+
onChange: handleEditChange,
|
|
20902
|
+
config
|
|
20903
|
+
}
|
|
20904
|
+
);
|
|
20905
|
+
}
|
|
20906
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
20907
|
+
CodeEditor,
|
|
20908
|
+
{
|
|
20909
|
+
code: editContent,
|
|
20910
|
+
language: artifact.language || artifact.type,
|
|
20911
|
+
onChange: handleEditChange
|
|
20912
|
+
}
|
|
20913
|
+
);
|
|
20914
|
+
}
|
|
20915
|
+
if (artifact.type === "image") {
|
|
20916
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ImageArtifactPreview, { content: displayContent, metadata: artifact.metadata, config });
|
|
20917
|
+
}
|
|
20918
|
+
if (artifact.type === "video") {
|
|
20919
|
+
return /* @__PURE__ */ jsxRuntime.jsx(VideoArtifactPreview, { content: displayContent, metadata: artifact.metadata, config });
|
|
20920
|
+
}
|
|
18845
20921
|
if (viewMode === "code" || !canPreview) {
|
|
18846
20922
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
18847
20923
|
CodeBlock3,
|
|
18848
20924
|
{
|
|
18849
|
-
code:
|
|
20925
|
+
code: displayContent,
|
|
18850
20926
|
language: artifact.language || artifact.type
|
|
18851
20927
|
}
|
|
18852
20928
|
);
|
|
18853
20929
|
}
|
|
18854
20930
|
switch (artifact.type) {
|
|
18855
20931
|
case "html":
|
|
18856
|
-
|
|
20932
|
+
case "svg":
|
|
20933
|
+
return /* @__PURE__ */ jsxRuntime.jsx(HtmlPreview3, { content: displayContent });
|
|
18857
20934
|
case "markdown":
|
|
18858
|
-
return /* @__PURE__ */ jsxRuntime.jsx(MarkdownPreview, { content:
|
|
20935
|
+
return /* @__PURE__ */ jsxRuntime.jsx(MarkdownPreview, { content: displayContent, config });
|
|
18859
20936
|
default:
|
|
18860
20937
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
18861
20938
|
CodeBlock3,
|
|
18862
20939
|
{
|
|
18863
|
-
code:
|
|
20940
|
+
code: displayContent,
|
|
18864
20941
|
language: artifact.language || artifact.type
|
|
18865
20942
|
}
|
|
18866
20943
|
);
|
|
@@ -18883,26 +20960,79 @@ var ArtifactViewer = React20.memo(function ArtifactViewer2({
|
|
|
18883
20960
|
] })
|
|
18884
20961
|
] }),
|
|
18885
20962
|
/* @__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
|
-
|
|
20963
|
+
isEditing ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
20964
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20965
|
+
"button",
|
|
20966
|
+
{
|
|
20967
|
+
onClick: handleUndo,
|
|
20968
|
+
disabled: undoStack.length === 0,
|
|
20969
|
+
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",
|
|
20970
|
+
title: "\u64A4\u9500",
|
|
20971
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Undo2, { size: 14 })
|
|
20972
|
+
}
|
|
20973
|
+
),
|
|
20974
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20975
|
+
"button",
|
|
20976
|
+
{
|
|
20977
|
+
onClick: handleRedo,
|
|
20978
|
+
disabled: redoStack.length === 0,
|
|
20979
|
+
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",
|
|
20980
|
+
title: "\u91CD\u505A",
|
|
20981
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Redo2, { size: 14 })
|
|
20982
|
+
}
|
|
20983
|
+
),
|
|
20984
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
20985
|
+
"button",
|
|
20986
|
+
{
|
|
20987
|
+
onClick: handleSave,
|
|
20988
|
+
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",
|
|
20989
|
+
title: "\u4FDD\u5B58",
|
|
20990
|
+
children: [
|
|
20991
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Save, { size: 12 }),
|
|
20992
|
+
"\u4FDD\u5B58"
|
|
20993
|
+
]
|
|
20994
|
+
}
|
|
20995
|
+
),
|
|
20996
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20997
|
+
"button",
|
|
20998
|
+
{
|
|
20999
|
+
onClick: handleCancelEdit,
|
|
21000
|
+
className: "px-2.5 py-1 text-xs text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800 rounded-lg transition-colors",
|
|
21001
|
+
title: "\u53D6\u6D88\u7F16\u8F91",
|
|
21002
|
+
children: "\u53D6\u6D88"
|
|
21003
|
+
}
|
|
21004
|
+
)
|
|
21005
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
21006
|
+
canEdit && onContentChange && /* @__PURE__ */ jsxRuntime.jsx(
|
|
21007
|
+
"button",
|
|
21008
|
+
{
|
|
21009
|
+
onClick: handleStartEdit,
|
|
21010
|
+
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",
|
|
21011
|
+
title: "\u7F16\u8F91",
|
|
21012
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, { size: 14 })
|
|
21013
|
+
}
|
|
21014
|
+
),
|
|
21015
|
+
onFullscreenToggle && /* @__PURE__ */ jsxRuntime.jsx(
|
|
21016
|
+
"button",
|
|
21017
|
+
{
|
|
21018
|
+
onClick: onFullscreenToggle,
|
|
21019
|
+
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",
|
|
21020
|
+
title: isFullscreen ? "\u9000\u51FA\u5168\u5C4F" : "\u5168\u5C4F",
|
|
21021
|
+
children: isFullscreen ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Minimize2, { size: 14 }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Maximize2, { size: 14 })
|
|
21022
|
+
}
|
|
21023
|
+
),
|
|
21024
|
+
canPreview && /* @__PURE__ */ jsxRuntime.jsx(
|
|
21025
|
+
ViewTabs,
|
|
21026
|
+
{
|
|
21027
|
+
activeView: viewMode,
|
|
21028
|
+
onViewChange: (v) => setViewMode(v),
|
|
21029
|
+
views: [
|
|
21030
|
+
{ id: "preview", label: "Preview", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Eye, { size: 12 }) },
|
|
21031
|
+
{ id: "code", label: "Code", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Code2, { size: 12 }) }
|
|
21032
|
+
]
|
|
21033
|
+
}
|
|
21034
|
+
)
|
|
21035
|
+
] }),
|
|
18906
21036
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
18907
21037
|
"button",
|
|
18908
21038
|
{
|
|
@@ -18917,6 +21047,16 @@ var ArtifactViewer = React20.memo(function ArtifactViewer2({
|
|
|
18917
21047
|
)
|
|
18918
21048
|
] })
|
|
18919
21049
|
] }),
|
|
21050
|
+
onSwitchArtifact && /* @__PURE__ */ jsxRuntime.jsx(
|
|
21051
|
+
ArtifactTabs,
|
|
21052
|
+
{
|
|
21053
|
+
artifacts,
|
|
21054
|
+
activeId: activeArtifactId ?? artifact.id,
|
|
21055
|
+
onSwitch: onSwitchArtifact,
|
|
21056
|
+
onClose: onCloseArtifact,
|
|
21057
|
+
onReorder: onReorderArtifacts
|
|
21058
|
+
}
|
|
21059
|
+
),
|
|
18920
21060
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-hidden", children: renderContent() })
|
|
18921
21061
|
] });
|
|
18922
21062
|
}
|
|
@@ -18962,6 +21102,145 @@ var ArtifactViewer = React20.memo(function ArtifactViewer2({
|
|
|
18962
21102
|
}
|
|
18963
21103
|
);
|
|
18964
21104
|
});
|
|
21105
|
+
|
|
21106
|
+
// src/utils/artifactExtractor.ts
|
|
21107
|
+
function getMediaTypeFromParamType(paramType) {
|
|
21108
|
+
const upper = paramType?.toUpperCase();
|
|
21109
|
+
if (upper === "IMAGE") return "image";
|
|
21110
|
+
if (upper === "VIDEO") return "video";
|
|
21111
|
+
return null;
|
|
21112
|
+
}
|
|
21113
|
+
function inferMediaTypeFromUrl(url) {
|
|
21114
|
+
if (!url) return null;
|
|
21115
|
+
const lower = url.toLowerCase();
|
|
21116
|
+
if (/\.(jpg|jpeg|png|gif|webp|svg|bmp)(\?|#|$)/.test(lower)) return "image";
|
|
21117
|
+
if (/\.(mp4|mov|webm|avi|mkv|m4v)(\?|#|$)/.test(lower)) return "video";
|
|
21118
|
+
if (/\.(jpg|jpeg|png|gif|webp)/.test(lower)) return "image";
|
|
21119
|
+
if (/\.(mp4|mov|webm)/.test(lower)) return "video";
|
|
21120
|
+
return null;
|
|
21121
|
+
}
|
|
21122
|
+
function extractArtifactsFromToolCall(toolCall, sessionId, messageId) {
|
|
21123
|
+
const artifacts = [];
|
|
21124
|
+
if (!toolCall || toolCall.status?.toLowerCase() !== "completed") return artifacts;
|
|
21125
|
+
const result = toolCall.result;
|
|
21126
|
+
if (!result) return artifacts;
|
|
21127
|
+
const toolName = result?.relation?.toolName || toolCall.name || "AI Tool";
|
|
21128
|
+
const args = toolCall.arguments || {};
|
|
21129
|
+
if (result.works && Array.isArray(result.works)) {
|
|
21130
|
+
result.works.forEach((work, index) => {
|
|
21131
|
+
const paramType = work.customResponse?.paramType;
|
|
21132
|
+
const fileId = work.fileId;
|
|
21133
|
+
const fileUrl = work.fileUrl || work.customResponse?.url;
|
|
21134
|
+
if (!fileId && !fileUrl) return;
|
|
21135
|
+
const mediaType = getMediaTypeFromParamType(paramType) || (fileUrl ? inferMediaTypeFromUrl(fileUrl) : null) || (fileId ? inferMediaTypeFromUrl(fileId) : null);
|
|
21136
|
+
if (!mediaType) return;
|
|
21137
|
+
const artifactId = work.publicId || `media-${toolCall.id}-${index}`;
|
|
21138
|
+
artifacts.push({
|
|
21139
|
+
id: artifactId,
|
|
21140
|
+
sessionId,
|
|
21141
|
+
type: mediaType,
|
|
21142
|
+
title: `${toolName} #${index + 1}`,
|
|
21143
|
+
// 优先存 fileId,resolveAssetForDisplay 会将其转换为可用 URL
|
|
21144
|
+
currentContent: fileId || fileUrl,
|
|
21145
|
+
version: 1,
|
|
21146
|
+
source: "tool",
|
|
21147
|
+
sourceId: toolCall.id,
|
|
21148
|
+
metadata: {
|
|
21149
|
+
toolName,
|
|
21150
|
+
generationParams: args,
|
|
21151
|
+
messageId,
|
|
21152
|
+
workflowCode: result.workflowCode,
|
|
21153
|
+
taskId: result.taskId,
|
|
21154
|
+
fileId: work.fileId,
|
|
21155
|
+
fileUrl: work.fileUrl
|
|
21156
|
+
},
|
|
21157
|
+
gmtCreate: (/* @__PURE__ */ new Date()).toISOString(),
|
|
21158
|
+
gmtModified: (/* @__PURE__ */ new Date()).toISOString()
|
|
21159
|
+
});
|
|
21160
|
+
});
|
|
21161
|
+
}
|
|
21162
|
+
if (artifacts.length === 0 && result.outputs?.images) {
|
|
21163
|
+
const imgUrl = typeof result.outputs.images === "string" ? result.outputs.images : null;
|
|
21164
|
+
if (imgUrl) {
|
|
21165
|
+
artifacts.push({
|
|
21166
|
+
id: `media-${toolCall.id}-output`,
|
|
21167
|
+
sessionId,
|
|
21168
|
+
type: "image",
|
|
21169
|
+
title: `${toolName}`,
|
|
21170
|
+
currentContent: imgUrl,
|
|
21171
|
+
version: 1,
|
|
21172
|
+
source: "tool",
|
|
21173
|
+
sourceId: toolCall.id,
|
|
21174
|
+
metadata: {
|
|
21175
|
+
toolName,
|
|
21176
|
+
generationParams: args,
|
|
21177
|
+
messageId
|
|
21178
|
+
},
|
|
21179
|
+
gmtCreate: (/* @__PURE__ */ new Date()).toISOString(),
|
|
21180
|
+
gmtModified: (/* @__PURE__ */ new Date()).toISOString()
|
|
21181
|
+
});
|
|
21182
|
+
}
|
|
21183
|
+
}
|
|
21184
|
+
if (result.works && Array.isArray(result.works)) {
|
|
21185
|
+
result.works.forEach((work, index) => {
|
|
21186
|
+
if (work.customResponse?.value) {
|
|
21187
|
+
const parsed = detectContentType(work.customResponse.value);
|
|
21188
|
+
if (parsed.content && parsed.type !== "text") {
|
|
21189
|
+
artifacts.push({
|
|
21190
|
+
id: `content-${toolCall.id}-${index}`,
|
|
21191
|
+
sessionId,
|
|
21192
|
+
type: parsed.type,
|
|
21193
|
+
title: parsed.title || `${toolName} - ${parsed.type.toUpperCase()}`,
|
|
21194
|
+
currentContent: parsed.content,
|
|
21195
|
+
language: parsed.language,
|
|
21196
|
+
version: 1,
|
|
21197
|
+
source: "tool",
|
|
21198
|
+
sourceId: toolCall.id,
|
|
21199
|
+
metadata: {
|
|
21200
|
+
toolName,
|
|
21201
|
+
messageId
|
|
21202
|
+
},
|
|
21203
|
+
gmtCreate: (/* @__PURE__ */ new Date()).toISOString(),
|
|
21204
|
+
gmtModified: (/* @__PURE__ */ new Date()).toISOString()
|
|
21205
|
+
});
|
|
21206
|
+
}
|
|
21207
|
+
}
|
|
21208
|
+
});
|
|
21209
|
+
}
|
|
21210
|
+
return artifacts;
|
|
21211
|
+
}
|
|
21212
|
+
function extractArtifactsFromMessages(messages, sessionId) {
|
|
21213
|
+
const allArtifacts = [];
|
|
21214
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
21215
|
+
for (const message of messages) {
|
|
21216
|
+
if (message.role !== "assistant") continue;
|
|
21217
|
+
const toolCalls = message.extraData?.tool_calls || [];
|
|
21218
|
+
for (const tc of toolCalls) {
|
|
21219
|
+
const extracted = extractArtifactsFromToolCall(tc, sessionId, message.messageId);
|
|
21220
|
+
for (const artifact of extracted) {
|
|
21221
|
+
if (!seenIds.has(artifact.id)) {
|
|
21222
|
+
seenIds.add(artifact.id);
|
|
21223
|
+
allArtifacts.push(artifact);
|
|
21224
|
+
}
|
|
21225
|
+
}
|
|
21226
|
+
}
|
|
21227
|
+
const thoughts = message.extraData?.thoughts || message.thoughts || [];
|
|
21228
|
+
for (const thought of thoughts) {
|
|
21229
|
+
if (thought.toolCalls) {
|
|
21230
|
+
for (const tc of thought.toolCalls) {
|
|
21231
|
+
const extracted = extractArtifactsFromToolCall(tc, sessionId, message.messageId);
|
|
21232
|
+
for (const artifact of extracted) {
|
|
21233
|
+
if (!seenIds.has(artifact.id)) {
|
|
21234
|
+
seenIds.add(artifact.id);
|
|
21235
|
+
allArtifacts.push(artifact);
|
|
21236
|
+
}
|
|
21237
|
+
}
|
|
21238
|
+
}
|
|
21239
|
+
}
|
|
21240
|
+
}
|
|
21241
|
+
}
|
|
21242
|
+
return allArtifacts;
|
|
21243
|
+
}
|
|
18965
21244
|
var Field = ({ label, value }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-3 text-xs text-zinc-400", children: [
|
|
18966
21245
|
/* @__PURE__ */ jsxRuntime.jsx("span", { children: label }),
|
|
18967
21246
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-zinc-200 truncate max-w-[60%]", children: value ?? "-" })
|
|
@@ -19293,7 +21572,9 @@ function ChatInputArea({
|
|
|
19293
21572
|
onSend,
|
|
19294
21573
|
onStop,
|
|
19295
21574
|
isStreaming,
|
|
19296
|
-
config
|
|
21575
|
+
config,
|
|
21576
|
+
activeArtifact,
|
|
21577
|
+
onDetachArtifact
|
|
19297
21578
|
}) {
|
|
19298
21579
|
const textareaRef = React20.useRef(null);
|
|
19299
21580
|
const fileInputRef = React20.useRef(null);
|
|
@@ -19374,6 +21655,20 @@ function ChatInputArea({
|
|
|
19374
21655
|
};
|
|
19375
21656
|
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
21657
|
/* @__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: [
|
|
21658
|
+
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: [
|
|
21659
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileCode, { size: 12, className: "text-[#d8ff00] flex-shrink-0" }),
|
|
21660
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-zinc-400", children: "\u5173\u8054\u4EA7\u7269\uFF1A" }),
|
|
21661
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-zinc-200 font-medium max-w-[200px] truncate", children: activeArtifact.title }),
|
|
21662
|
+
onDetachArtifact && /* @__PURE__ */ jsxRuntime.jsx(
|
|
21663
|
+
"button",
|
|
21664
|
+
{
|
|
21665
|
+
onClick: onDetachArtifact,
|
|
21666
|
+
className: "p-0.5 text-zinc-500 hover:text-zinc-300 rounded transition-colors",
|
|
21667
|
+
title: "\u53D6\u6D88\u5173\u8054",
|
|
21668
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Unlink, { size: 10 })
|
|
21669
|
+
}
|
|
21670
|
+
)
|
|
21671
|
+
] }) }),
|
|
19377
21672
|
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
21673
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
19379
21674
|
"img",
|
|
@@ -19538,6 +21833,188 @@ var DragHandle = React20__namespace.default.memo(function DragHandle2({
|
|
|
19538
21833
|
}
|
|
19539
21834
|
);
|
|
19540
21835
|
});
|
|
21836
|
+
var artifactTypeIconMap = {
|
|
21837
|
+
html: lucideReact.Globe,
|
|
21838
|
+
svg: lucideReact.Globe,
|
|
21839
|
+
markdown: lucideReact.FileText,
|
|
21840
|
+
json: lucideReact.FileJson,
|
|
21841
|
+
code: lucideReact.FileCode,
|
|
21842
|
+
text: lucideReact.FileText,
|
|
21843
|
+
image: lucideReact.FileImage,
|
|
21844
|
+
video: lucideReact.Video
|
|
21845
|
+
};
|
|
21846
|
+
var ArtifactBarItemThumbnail = React20.memo(function ArtifactBarItemThumbnail2({
|
|
21847
|
+
artifact,
|
|
21848
|
+
config
|
|
21849
|
+
}) {
|
|
21850
|
+
const TypeIcon = artifactTypeIconMap[artifact.type] || lucideReact.FileText;
|
|
21851
|
+
const isMedia = artifact.type === "image" || artifact.type === "video";
|
|
21852
|
+
const thumbnailUrl = useResolvedThumbnailUrl(
|
|
21853
|
+
artifact.currentContent,
|
|
21854
|
+
{
|
|
21855
|
+
fileId: artifact.metadata?.fileId,
|
|
21856
|
+
type: artifact.type,
|
|
21857
|
+
config,
|
|
21858
|
+
enabled: isMedia
|
|
21859
|
+
}
|
|
21860
|
+
);
|
|
21861
|
+
if (isMedia && thumbnailUrl) {
|
|
21862
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
21863
|
+
"img",
|
|
21864
|
+
{
|
|
21865
|
+
src: thumbnailUrl,
|
|
21866
|
+
alt: "",
|
|
21867
|
+
className: "w-10 h-10 rounded-lg object-cover flex-shrink-0 border border-zinc-700/50 agent-sdk-light:border-zinc-300",
|
|
21868
|
+
loading: "lazy"
|
|
21869
|
+
}
|
|
21870
|
+
);
|
|
21871
|
+
}
|
|
21872
|
+
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" }) });
|
|
21873
|
+
});
|
|
21874
|
+
var ArtifactBarMiniThumbnail = React20.memo(function ArtifactBarMiniThumbnail2({
|
|
21875
|
+
artifact,
|
|
21876
|
+
config
|
|
21877
|
+
}) {
|
|
21878
|
+
const TypeIcon = artifactTypeIconMap[artifact.type] || lucideReact.FileText;
|
|
21879
|
+
const isMedia = artifact.type === "image" || artifact.type === "video";
|
|
21880
|
+
const thumbnailUrl = useResolvedThumbnailUrl(
|
|
21881
|
+
artifact.currentContent,
|
|
21882
|
+
{
|
|
21883
|
+
fileId: artifact.metadata?.fileId,
|
|
21884
|
+
type: artifact.type,
|
|
21885
|
+
config,
|
|
21886
|
+
enabled: isMedia
|
|
21887
|
+
}
|
|
21888
|
+
);
|
|
21889
|
+
if (isMedia && thumbnailUrl) {
|
|
21890
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
21891
|
+
"img",
|
|
21892
|
+
{
|
|
21893
|
+
src: thumbnailUrl,
|
|
21894
|
+
alt: "",
|
|
21895
|
+
className: "w-6 h-6 rounded border border-zinc-700 agent-sdk-light:border-zinc-300 object-cover",
|
|
21896
|
+
loading: "lazy"
|
|
21897
|
+
}
|
|
21898
|
+
);
|
|
21899
|
+
}
|
|
21900
|
+
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" }) });
|
|
21901
|
+
});
|
|
21902
|
+
var ArtifactBar = React20__namespace.default.memo(function ArtifactBar2({
|
|
21903
|
+
artifacts,
|
|
21904
|
+
onOpenArtifact,
|
|
21905
|
+
config
|
|
21906
|
+
}) {
|
|
21907
|
+
const [expanded, setExpanded] = React20.useState(false);
|
|
21908
|
+
const barRef = React20.useRef(null);
|
|
21909
|
+
React20.useEffect(() => {
|
|
21910
|
+
if (!expanded) return;
|
|
21911
|
+
const handleClickOutside = (e) => {
|
|
21912
|
+
if (barRef.current && !barRef.current.contains(e.target)) {
|
|
21913
|
+
setExpanded(false);
|
|
21914
|
+
}
|
|
21915
|
+
};
|
|
21916
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
21917
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
21918
|
+
}, [expanded]);
|
|
21919
|
+
if (artifacts.length === 0) return null;
|
|
21920
|
+
const imageCount = artifacts.filter((a) => a.type === "image").length;
|
|
21921
|
+
const codeCount = artifacts.filter((a) => ["code", "html", "svg", "json"].includes(a.type)).length;
|
|
21922
|
+
const docCount = artifacts.filter((a) => ["markdown", "text"].includes(a.type)).length;
|
|
21923
|
+
const videoCount = artifacts.filter((a) => a.type === "video").length;
|
|
21924
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: barRef, className: "relative flex-shrink-0 mx-auto max-w-md", children: [
|
|
21925
|
+
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: [
|
|
21926
|
+
/* @__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: [
|
|
21927
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
21928
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.LayoutGrid, { size: 14, className: "text-[#d8ff00]" }),
|
|
21929
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-zinc-200 agent-sdk-light:text-zinc-800", children: "\u5168\u90E8\u4EA7\u7269" }),
|
|
21930
|
+
/* @__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 })
|
|
21931
|
+
] }),
|
|
21932
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21933
|
+
"button",
|
|
21934
|
+
{
|
|
21935
|
+
onClick: () => setExpanded(false),
|
|
21936
|
+
className: "p-1 text-zinc-500 hover:text-zinc-300 agent-sdk-light:hover:text-zinc-700 rounded transition-colors",
|
|
21937
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { size: 16 })
|
|
21938
|
+
}
|
|
21939
|
+
)
|
|
21940
|
+
] }),
|
|
21941
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2 grid grid-cols-1 gap-1", children: artifacts.map((artifact) => {
|
|
21942
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
21943
|
+
"button",
|
|
21944
|
+
{
|
|
21945
|
+
onClick: () => {
|
|
21946
|
+
onOpenArtifact(artifact.id);
|
|
21947
|
+
setExpanded(false);
|
|
21948
|
+
},
|
|
21949
|
+
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",
|
|
21950
|
+
children: [
|
|
21951
|
+
/* @__PURE__ */ jsxRuntime.jsx(ArtifactBarItemThumbnail, { artifact, config }),
|
|
21952
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
21953
|
+
/* @__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 }),
|
|
21954
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-[11px] text-zinc-500 agent-sdk-light:text-zinc-500 mt-0.5", children: [
|
|
21955
|
+
artifact.type.toUpperCase(),
|
|
21956
|
+
artifact.language && artifact.language !== artifact.type && ` \u2022 ${artifact.language}`
|
|
21957
|
+
] })
|
|
21958
|
+
] })
|
|
21959
|
+
]
|
|
21960
|
+
},
|
|
21961
|
+
artifact.id
|
|
21962
|
+
);
|
|
21963
|
+
}) })
|
|
21964
|
+
] }),
|
|
21965
|
+
/* @__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(
|
|
21966
|
+
"button",
|
|
21967
|
+
{
|
|
21968
|
+
onClick: () => setExpanded((prev) => !prev),
|
|
21969
|
+
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",
|
|
21970
|
+
children: [
|
|
21971
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
21972
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { size: 14, className: "text-[#d8ff00]" }),
|
|
21973
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs font-medium text-zinc-300 agent-sdk-light:text-zinc-700", children: [
|
|
21974
|
+
artifacts.length,
|
|
21975
|
+
" \u4E2A\u4EA7\u7269"
|
|
21976
|
+
] })
|
|
21977
|
+
] }),
|
|
21978
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 flex-1 min-w-0", children: [
|
|
21979
|
+
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: [
|
|
21980
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileImage, { size: 10 }),
|
|
21981
|
+
" ",
|
|
21982
|
+
imageCount
|
|
21983
|
+
] }),
|
|
21984
|
+
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: [
|
|
21985
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileCode, { size: 10 }),
|
|
21986
|
+
" ",
|
|
21987
|
+
codeCount
|
|
21988
|
+
] }),
|
|
21989
|
+
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: [
|
|
21990
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileText, { size: 10 }),
|
|
21991
|
+
" ",
|
|
21992
|
+
docCount
|
|
21993
|
+
] }),
|
|
21994
|
+
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: [
|
|
21995
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Video, { size: 10 }),
|
|
21996
|
+
" ",
|
|
21997
|
+
videoCount
|
|
21998
|
+
] })
|
|
21999
|
+
] }),
|
|
22000
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center -space-x-1.5", children: [
|
|
22001
|
+
artifacts.slice(0, 4).map((artifact) => {
|
|
22002
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ArtifactBarMiniThumbnail, { artifact, config }, artifact.id);
|
|
22003
|
+
}),
|
|
22004
|
+
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: [
|
|
22005
|
+
"+",
|
|
22006
|
+
artifacts.length - 4
|
|
22007
|
+
] }) })
|
|
22008
|
+
] }),
|
|
22009
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronUp, { size: 14, className: cn2(
|
|
22010
|
+
"text-zinc-500 transition-transform flex-shrink-0",
|
|
22011
|
+
expanded && "rotate-180"
|
|
22012
|
+
) })
|
|
22013
|
+
]
|
|
22014
|
+
}
|
|
22015
|
+
) })
|
|
22016
|
+
] });
|
|
22017
|
+
});
|
|
19541
22018
|
var AgentChat = React20__namespace.default.forwardRef(({
|
|
19542
22019
|
agentId,
|
|
19543
22020
|
projectId,
|
|
@@ -19580,7 +22057,7 @@ var AgentChat = React20__namespace.default.forwardRef(({
|
|
|
19580
22057
|
ComponentRegistry: mergedRegistry
|
|
19581
22058
|
};
|
|
19582
22059
|
}, [config?.components, outerComponents]);
|
|
19583
|
-
const { sessions, setSessions, currentSession, setCurrentSession, addSession, removeSession, tools: _tools, setTools, setSkills, setShowItemTime } = useAgentStore();
|
|
22060
|
+
const { sessions, setSessions, currentSession, setCurrentSession, addSession, removeSession, tools: _tools, setTools, setSkills, setShowItemTime, artifacts, artifactOrder, activeArtifactId, upsertArtifact, updateArtifactContent, setActiveArtifact, removeArtifact, clearArtifacts, setArtifacts, reorderArtifacts } = useAgentStore();
|
|
19584
22061
|
const [loading, setLoading] = React20.useState(true);
|
|
19585
22062
|
const [messagesLoading, setMessagesLoading] = React20.useState(false);
|
|
19586
22063
|
const [collapsed, setCollapsed] = React20.useState(false);
|
|
@@ -19592,7 +22069,23 @@ var AgentChat = React20__namespace.default.forwardRef(({
|
|
|
19592
22069
|
const lastUserMessageRef = React20.useRef("");
|
|
19593
22070
|
const [shareModalOpen, setShareModalOpen] = React20.useState(false);
|
|
19594
22071
|
const [shareSession, setShareSession] = React20.useState(null);
|
|
19595
|
-
const
|
|
22072
|
+
const artifactList = React20.useMemo(() => {
|
|
22073
|
+
const ordered = artifactOrder.map((id) => artifacts[id]).filter(Boolean);
|
|
22074
|
+
const unordered = Object.values(artifacts).filter(
|
|
22075
|
+
(a) => !artifactOrder.includes(a.id)
|
|
22076
|
+
);
|
|
22077
|
+
return [...ordered, ...unordered];
|
|
22078
|
+
}, [artifacts, artifactOrder]);
|
|
22079
|
+
const activeArtifact = activeArtifactId ? artifacts[activeArtifactId] ?? null : null;
|
|
22080
|
+
const currentArtifact = activeArtifact ? {
|
|
22081
|
+
id: activeArtifact.id,
|
|
22082
|
+
type: activeArtifact.type,
|
|
22083
|
+
title: activeArtifact.title,
|
|
22084
|
+
content: activeArtifact.currentContent,
|
|
22085
|
+
language: activeArtifact.language,
|
|
22086
|
+
source: activeArtifact.sourceId,
|
|
22087
|
+
metadata: activeArtifact.metadata
|
|
22088
|
+
} : null;
|
|
19596
22089
|
const [isArtifactFullscreen, setIsArtifactFullscreen] = React20.useState(false);
|
|
19597
22090
|
const [artifactPanelWidth, setArtifactPanelWidth] = React20.useState(50);
|
|
19598
22091
|
const [isDragging, setIsDragging] = React20.useState(false);
|
|
@@ -19618,7 +22111,11 @@ var AgentChat = React20__namespace.default.forwardRef(({
|
|
|
19618
22111
|
const deltaX = dragStartRef.current.startX - e.clientX;
|
|
19619
22112
|
const deltaPercent = deltaX / containerWidth * 100;
|
|
19620
22113
|
const newWidth = dragStartRef.current.startWidth + deltaPercent;
|
|
19621
|
-
const
|
|
22114
|
+
const minChatPx = 350;
|
|
22115
|
+
const minArtifactPx = 400;
|
|
22116
|
+
const maxArtifactPercent = (containerWidth - minChatPx) / containerWidth * 100;
|
|
22117
|
+
const minArtifactPercent = minArtifactPx / containerWidth * 100;
|
|
22118
|
+
const clampedWidth = Math.max(minArtifactPercent, Math.min(maxArtifactPercent, newWidth));
|
|
19622
22119
|
setArtifactPanelWidth(clampedWidth);
|
|
19623
22120
|
};
|
|
19624
22121
|
const handleMouseUp = () => {
|
|
@@ -19640,38 +22137,52 @@ var AgentChat = React20__namespace.default.forwardRef(({
|
|
|
19640
22137
|
setShowItemTime(showItemTime);
|
|
19641
22138
|
}, [showItemTime]);
|
|
19642
22139
|
const handleOpenArtifact = React20.useCallback((data) => {
|
|
19643
|
-
if (
|
|
19644
|
-
|
|
22140
|
+
if (activeArtifact && activeArtifact.currentContent === data.content && activeArtifact.type === data.type) {
|
|
22141
|
+
setActiveArtifact(null);
|
|
19645
22142
|
setIsArtifactFullscreen(false);
|
|
19646
22143
|
return;
|
|
19647
22144
|
}
|
|
19648
|
-
const
|
|
19649
|
-
|
|
19650
|
-
|
|
19651
|
-
|
|
19652
|
-
|
|
19653
|
-
|
|
19654
|
-
|
|
19655
|
-
|
|
19656
|
-
|
|
19657
|
-
|
|
22145
|
+
const existingArtifact = Object.values(artifacts).find(
|
|
22146
|
+
(a) => a.currentContent === data.content && a.type === data.type
|
|
22147
|
+
);
|
|
22148
|
+
if (existingArtifact) {
|
|
22149
|
+
setActiveArtifact(existingArtifact.id);
|
|
22150
|
+
} else {
|
|
22151
|
+
const sessionId = currentSession?.sessionId || "";
|
|
22152
|
+
const newArtifactEntry = {
|
|
22153
|
+
id: `artifact-${Date.now()}`,
|
|
22154
|
+
sessionId,
|
|
22155
|
+
type: data.type,
|
|
22156
|
+
title: data.title,
|
|
22157
|
+
currentContent: data.content,
|
|
22158
|
+
language: data.language,
|
|
22159
|
+
metadata: data.metadata,
|
|
22160
|
+
version: 1,
|
|
22161
|
+
source: "llm",
|
|
22162
|
+
gmtCreate: (/* @__PURE__ */ new Date()).toISOString(),
|
|
22163
|
+
gmtModified: (/* @__PURE__ */ new Date()).toISOString()
|
|
22164
|
+
};
|
|
22165
|
+
upsertArtifact(newArtifactEntry);
|
|
22166
|
+
setActiveArtifact(newArtifactEntry.id);
|
|
22167
|
+
}
|
|
22168
|
+
}, [activeArtifact, artifacts, currentSession, upsertArtifact, setActiveArtifact]);
|
|
19658
22169
|
const handleCloseArtifact = React20.useCallback(() => {
|
|
19659
|
-
|
|
22170
|
+
setActiveArtifact(null);
|
|
19660
22171
|
setIsArtifactFullscreen(false);
|
|
19661
|
-
}, []);
|
|
22172
|
+
}, [setActiveArtifact]);
|
|
19662
22173
|
React20.useEffect(() => {
|
|
19663
22174
|
const handleKeyDown = (e) => {
|
|
19664
|
-
if (e.key === "Escape" &&
|
|
22175
|
+
if (e.key === "Escape" && activeArtifactId) {
|
|
19665
22176
|
if (isArtifactFullscreen) {
|
|
19666
22177
|
setIsArtifactFullscreen(false);
|
|
19667
22178
|
} else {
|
|
19668
|
-
|
|
22179
|
+
setActiveArtifact(null);
|
|
19669
22180
|
}
|
|
19670
22181
|
}
|
|
19671
22182
|
};
|
|
19672
22183
|
document.addEventListener("keydown", handleKeyDown);
|
|
19673
22184
|
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
19674
|
-
}, [
|
|
22185
|
+
}, [activeArtifactId, isArtifactFullscreen, setActiveArtifact]);
|
|
19675
22186
|
const handleToggleArtifactFullscreen = React20.useCallback(() => {
|
|
19676
22187
|
setIsArtifactFullscreen((prev) => !prev);
|
|
19677
22188
|
}, []);
|
|
@@ -19873,8 +22384,9 @@ var AgentChat = React20__namespace.default.forwardRef(({
|
|
|
19873
22384
|
addSession(s);
|
|
19874
22385
|
setCurrentSession(s);
|
|
19875
22386
|
useAgentStore.getState().setMessages([]);
|
|
22387
|
+
clearArtifacts();
|
|
19876
22388
|
}
|
|
19877
|
-
}, [projectId, agentId]);
|
|
22389
|
+
}, [projectId, agentId, clearArtifacts]);
|
|
19878
22390
|
const handlePrompt = React20.useCallback(async (p) => {
|
|
19879
22391
|
await handleNew();
|
|
19880
22392
|
setInput(p);
|
|
@@ -19885,10 +22397,29 @@ var AgentChat = React20__namespace.default.forwardRef(({
|
|
|
19885
22397
|
onSessionIdChange?.(s.sessionId);
|
|
19886
22398
|
setMobileOpen(false);
|
|
19887
22399
|
useAgentStore.getState().setMessages([]);
|
|
22400
|
+
clearArtifacts();
|
|
19888
22401
|
setMessagesLoading(true);
|
|
19889
|
-
await
|
|
22402
|
+
await Promise.all([
|
|
22403
|
+
loadMessages(s.sessionId),
|
|
22404
|
+
artifactService.list(s.sessionId).then((res) => {
|
|
22405
|
+
if (res.success && res.data && res.data.length > 0) {
|
|
22406
|
+
setArtifacts(res.data);
|
|
22407
|
+
}
|
|
22408
|
+
}).catch((err) => {
|
|
22409
|
+
console.error("[AgentChat] Load artifacts failed:", err);
|
|
22410
|
+
})
|
|
22411
|
+
]);
|
|
22412
|
+
const currentArtifacts = useAgentStore.getState().artifacts;
|
|
22413
|
+
if (Object.keys(currentArtifacts).length === 0) {
|
|
22414
|
+
const currentMessages = useAgentStore.getState().messages;
|
|
22415
|
+
const extracted = extractArtifactsFromMessages(currentMessages, s.sessionId);
|
|
22416
|
+
if (extracted.length > 0) {
|
|
22417
|
+
console.log("[AgentChat] Fallback: extracted", extracted.length, "artifacts from messages");
|
|
22418
|
+
extracted.forEach((artifact) => upsertArtifact(artifact));
|
|
22419
|
+
}
|
|
22420
|
+
}
|
|
19890
22421
|
setMessagesLoading(false);
|
|
19891
|
-
}, []);
|
|
22422
|
+
}, [clearArtifacts, setArtifacts, upsertArtifact]);
|
|
19892
22423
|
const handleDelete2 = React20.useCallback(async (id) => {
|
|
19893
22424
|
toast("\u5220\u9664\u6B64\u5BF9\u8BDD\uFF1F", {
|
|
19894
22425
|
action: {
|
|
@@ -19984,8 +22515,14 @@ var AgentChat = React20__namespace.default.forwardRef(({
|
|
|
19984
22515
|
}
|
|
19985
22516
|
});
|
|
19986
22517
|
setImages([]);
|
|
19987
|
-
|
|
19988
|
-
|
|
22518
|
+
const currentActiveArtifact = activeArtifactId ? artifacts[activeArtifactId] : null;
|
|
22519
|
+
const artifactContext = currentActiveArtifact ? {
|
|
22520
|
+
artifactId: currentActiveArtifact.id,
|
|
22521
|
+
title: currentActiveArtifact.title,
|
|
22522
|
+
currentContent: currentActiveArtifact.currentContent
|
|
22523
|
+
} : void 0;
|
|
22524
|
+
await sendMessage(currentSession.sessionId, messageContent, { artifactContext });
|
|
22525
|
+
}, [input, images, currentSession, sendMessage, config, activeArtifactId, artifacts]);
|
|
19989
22526
|
const sendTextMessage = React20.useCallback(async (content) => {
|
|
19990
22527
|
if (!content.trim()) return;
|
|
19991
22528
|
if (!currentSession) return;
|
|
@@ -20150,6 +22687,13 @@ var AgentChat = React20__namespace.default.forwardRef(({
|
|
|
20150
22687
|
onOpenArtifact: handleOpenArtifact
|
|
20151
22688
|
}
|
|
20152
22689
|
),
|
|
22690
|
+
artifactList.length > 0 && !currentArtifact && /* @__PURE__ */ jsxRuntime.jsx(
|
|
22691
|
+
ArtifactBar,
|
|
22692
|
+
{
|
|
22693
|
+
artifacts: artifactList,
|
|
22694
|
+
onOpenArtifact: (id) => setActiveArtifact(id)
|
|
22695
|
+
}
|
|
22696
|
+
),
|
|
20153
22697
|
!hideInput && /* @__PURE__ */ jsxRuntime.jsx(
|
|
20154
22698
|
ChatInputArea,
|
|
20155
22699
|
{
|
|
@@ -20160,7 +22704,9 @@ var AgentChat = React20__namespace.default.forwardRef(({
|
|
|
20160
22704
|
onSend: handleSend,
|
|
20161
22705
|
onStop: handleStop,
|
|
20162
22706
|
isStreaming: isCurrentSessionStreaming,
|
|
20163
|
-
config
|
|
22707
|
+
config,
|
|
22708
|
+
activeArtifact,
|
|
22709
|
+
onDetachArtifact: () => setActiveArtifact(null)
|
|
20164
22710
|
}
|
|
20165
22711
|
)
|
|
20166
22712
|
]
|
|
@@ -20199,7 +22745,36 @@ var AgentChat = React20__namespace.default.forwardRef(({
|
|
|
20199
22745
|
config,
|
|
20200
22746
|
isFullscreen: isArtifactFullscreen,
|
|
20201
22747
|
onFullscreenToggle: handleToggleArtifactFullscreen,
|
|
20202
|
-
embedded: true
|
|
22748
|
+
embedded: true,
|
|
22749
|
+
artifacts: artifactList,
|
|
22750
|
+
activeArtifactId,
|
|
22751
|
+
onSwitchArtifact: (id) => setActiveArtifact(id),
|
|
22752
|
+
onCloseArtifact: (id) => {
|
|
22753
|
+
removeArtifact(id);
|
|
22754
|
+
if (artifactList.length <= 1) {
|
|
22755
|
+
setIsArtifactFullscreen(false);
|
|
22756
|
+
}
|
|
22757
|
+
},
|
|
22758
|
+
onReorderArtifacts: reorderArtifacts,
|
|
22759
|
+
onContentChange: (content) => {
|
|
22760
|
+
if (activeArtifactId) {
|
|
22761
|
+
updateArtifactContent(activeArtifactId, content, "user");
|
|
22762
|
+
}
|
|
22763
|
+
},
|
|
22764
|
+
onSave: async (artifactId, content) => {
|
|
22765
|
+
try {
|
|
22766
|
+
const res = await artifactService.updateContent(artifactId, content);
|
|
22767
|
+
if (res.success) {
|
|
22768
|
+
updateArtifactContent(artifactId, content, "user");
|
|
22769
|
+
toast.success("\u4EA7\u7269\u5DF2\u4FDD\u5B58");
|
|
22770
|
+
} else {
|
|
22771
|
+
toast.error("\u4FDD\u5B58\u5931\u8D25");
|
|
22772
|
+
}
|
|
22773
|
+
} catch (err) {
|
|
22774
|
+
console.error("[AgentChat] Save artifact failed:", err);
|
|
22775
|
+
toast.error("\u4FDD\u5B58\u4EA7\u7269\u5931\u8D25");
|
|
22776
|
+
}
|
|
22777
|
+
}
|
|
20203
22778
|
}
|
|
20204
22779
|
)
|
|
20205
22780
|
]
|
|
@@ -20709,6 +23284,7 @@ exports.VoiceWaveform = VoiceWaveform;
|
|
|
20709
23284
|
exports.agentService = agentService;
|
|
20710
23285
|
exports.agentSkillService = agentSkillService;
|
|
20711
23286
|
exports.agentToolService = agentToolService;
|
|
23287
|
+
exports.artifactService = artifactService;
|
|
20712
23288
|
exports.calculateReconnectDelay = calculateReconnectDelay;
|
|
20713
23289
|
exports.componentService = componentService;
|
|
20714
23290
|
exports.confirmAllPendingToolCalls = confirmAllPendingToolCalls;
|
|
@@ -20764,8 +23340,14 @@ exports.shareService = shareService;
|
|
|
20764
23340
|
exports.templateService = templateService;
|
|
20765
23341
|
exports.toolCallService = toolCallService;
|
|
20766
23342
|
exports.uploadOSS = uploadOSS;
|
|
23343
|
+
exports.useActiveArtifact = useActiveArtifact;
|
|
23344
|
+
exports.useActiveArtifactId = useActiveArtifactId;
|
|
20767
23345
|
exports.useActiveSubAgent = useActiveSubAgent;
|
|
20768
23346
|
exports.useAgentStore = useAgentStore;
|
|
23347
|
+
exports.useArtifactList = useArtifactList;
|
|
23348
|
+
exports.useArtifactOrder = useArtifactOrder;
|
|
23349
|
+
exports.useArtifacts = useArtifacts;
|
|
23350
|
+
exports.useCanvasBridge = useCanvasBridge;
|
|
20769
23351
|
exports.useChatError = useChatError;
|
|
20770
23352
|
exports.useChatUI = useChatUI;
|
|
20771
23353
|
exports.useComponent = useComponent;
|