@pactor-app/chat 1.16.0 → 1.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -30,6 +30,7 @@ __export(index_exports, {
30
30
  CHAT_LAYOUT_TYPE: () => CHAT_LAYOUT_TYPE,
31
31
  CHAT_SHELL_COMPONENT_TYPE: () => CHAT_SHELL_COMPONENT_TYPE,
32
32
  Chat: () => Chat,
33
+ ChatArtifactCard: () => ChatArtifactCard,
33
34
  ChatDenied: () => ChatDenied,
34
35
  ChatLayout: () => ChatLayout,
35
36
  ChatServicesProvider: () => ChatServicesProvider,
@@ -44,6 +45,7 @@ __export(index_exports, {
44
45
  MessageBubble: () => MessageBubble,
45
46
  PartRenderer: () => PartRenderer,
46
47
  applyChatEvent: () => applyChatEvent,
48
+ artifactCardMeta: () => artifactCardMeta,
47
49
  buildArtifactBlob: () => buildArtifactBlob,
48
50
  buildArtifactTree: () => buildArtifactTree,
49
51
  buildChatScope: () => buildChatScope,
@@ -57,6 +59,8 @@ __export(index_exports, {
57
59
  createSafeRegistry: () => createSafeRegistry,
58
60
  detectStreamingMode: () => detectStreamingMode,
59
61
  downloadArtifact: () => downloadArtifact,
62
+ formatArtifactSize: () => formatArtifactSize,
63
+ formatMessageTime: () => formatMessageTime,
60
64
  guardChatDsl: () => guardChatDsl,
61
65
  isImageArtifact: () => isImageArtifact,
62
66
  mergeArtifacts: () => mergeArtifacts,
@@ -67,6 +71,8 @@ __export(index_exports, {
67
71
  registerChatShellComponent: () => registerChatShellComponent,
68
72
  resolveArtifactFileType: () => resolveArtifactFileType,
69
73
  resolveArtifactFilename: () => resolveArtifactFilename,
74
+ resolveArtifactIcon: () => resolveArtifactIcon,
75
+ resolveArtifactIconName: () => resolveArtifactIconName,
70
76
  runChatTurn: () => runChatTurn,
71
77
  runRegenerateTurn: () => runRegenerateTurn,
72
78
  saveBlob: () => saveBlob,
@@ -220,6 +226,97 @@ function isImageArtifact(artifact) {
220
226
  const ext = resolveArtifactFileType(artifact);
221
227
  return ext !== null && ARTIFACT_IMAGE_EXTENSIONS.includes(ext);
222
228
  }
229
+ var ARTIFACT_ICON_BY_EXTENSION = {
230
+ // 表格数据(绿)
231
+ csv: { name: "table", tone: "green" },
232
+ tsv: { name: "table", tone: "green" },
233
+ xls: { name: "table", tone: "green" },
234
+ xlsx: { name: "table", tone: "green" },
235
+ // 数据 / 数据库(琥珀)
236
+ json: { name: "database", tone: "amber" },
237
+ sql: { name: "database", tone: "amber" },
238
+ // 脚本(蓝,终端图标)
239
+ sh: { name: "terminal", tone: "blue" },
240
+ bash: { name: "terminal", tone: "blue" },
241
+ zsh: { name: "terminal", tone: "blue" },
242
+ // 代码 / 配置(蓝)
243
+ js: { name: "code", tone: "blue" },
244
+ mjs: { name: "code", tone: "blue" },
245
+ cjs: { name: "code", tone: "blue" },
246
+ jsx: { name: "code", tone: "blue" },
247
+ ts: { name: "code", tone: "blue" },
248
+ mts: { name: "code", tone: "blue" },
249
+ cts: { name: "code", tone: "blue" },
250
+ tsx: { name: "code", tone: "blue" },
251
+ py: { name: "code", tone: "blue" },
252
+ rb: { name: "code", tone: "blue" },
253
+ go: { name: "code", tone: "blue" },
254
+ rs: { name: "code", tone: "blue" },
255
+ java: { name: "code", tone: "blue" },
256
+ kt: { name: "code", tone: "blue" },
257
+ c: { name: "code", tone: "blue" },
258
+ h: { name: "code", tone: "blue" },
259
+ cc: { name: "code", tone: "blue" },
260
+ cpp: { name: "code", tone: "blue" },
261
+ cs: { name: "code", tone: "blue" },
262
+ swift: { name: "code", tone: "blue" },
263
+ php: { name: "code", tone: "blue" },
264
+ css: { name: "code", tone: "blue" },
265
+ scss: { name: "code", tone: "blue" },
266
+ less: { name: "code", tone: "blue" },
267
+ html: { name: "code", tone: "blue" },
268
+ vue: { name: "code", tone: "blue" },
269
+ svelte: { name: "code", tone: "blue" },
270
+ yaml: { name: "code", tone: "blue" },
271
+ yml: { name: "code", tone: "blue" },
272
+ toml: { name: "code", tone: "blue" },
273
+ xml: { name: "code", tone: "blue" },
274
+ // 文档 / 文本(石板灰)
275
+ md: { name: "file-text", tone: "slate" },
276
+ markdown: { name: "file-text", tone: "slate" },
277
+ mdx: { name: "file-text", tone: "slate" },
278
+ txt: { name: "file-text", tone: "slate" },
279
+ text: { name: "file-text", tone: "slate" },
280
+ log: { name: "file-text", tone: "slate" },
281
+ rst: { name: "file-text", tone: "slate" },
282
+ pdf: { name: "file-text", tone: "slate" },
283
+ doc: { name: "file-text", tone: "slate" },
284
+ docx: { name: "file-text", tone: "slate" }
285
+ };
286
+ function resolveArtifactIcon(artifact) {
287
+ const ext = resolveArtifactFileType(artifact);
288
+ if (ext !== null) {
289
+ if (ARTIFACT_IMAGE_EXTENSIONS.includes(ext)) {
290
+ return { name: "image", tone: "violet" };
291
+ }
292
+ const spec = ARTIFACT_ICON_BY_EXTENSION[ext];
293
+ if (spec !== void 0) {
294
+ return spec;
295
+ }
296
+ }
297
+ if (artifact.kind === "code") {
298
+ return { name: "code", tone: "blue" };
299
+ }
300
+ if (artifact.kind === "dsl") {
301
+ return { name: "layout-grid", tone: "slate" };
302
+ }
303
+ return ext === null ? { name: "file-text", tone: "slate" } : { name: "file", tone: "slate" };
304
+ }
305
+ function resolveArtifactIconName(artifact) {
306
+ return resolveArtifactIcon(artifact).name;
307
+ }
308
+ function formatArtifactSize(size) {
309
+ if (typeof size !== "number" || !Number.isFinite(size) || size < 0) {
310
+ return null;
311
+ }
312
+ if (size < 1024) {
313
+ return `${size} B`;
314
+ }
315
+ if (size < 1024 * 1024) {
316
+ return `${(size / 1024).toFixed(1)} KB`;
317
+ }
318
+ return `${(size / 1024 / 1024).toFixed(1)} MB`;
319
+ }
223
320
  function collectArtifacts(messages) {
224
321
  const order = [];
225
322
  const byId = /* @__PURE__ */ new Map();
@@ -1044,7 +1141,7 @@ function useChatAutoScroll({
1044
1141
 
1045
1142
  // src/chat-composition.tsx
1046
1143
  var import_runtime5 = require("@pactor-app/runtime");
1047
- var import_react17 = require("react");
1144
+ var import_react19 = require("react");
1048
1145
 
1049
1146
  // src/hooks/use-chat-model.ts
1050
1147
  var import_react3 = require("react");
@@ -1098,14 +1195,14 @@ function AppShell({
1098
1195
  }
1099
1196
 
1100
1197
  // src/view/ArtifactPanel.tsx
1101
- var import_components4 = require("@pactor-app/ui/components");
1198
+ var import_components5 = require("@pactor-app/ui/components");
1102
1199
  var import_core3 = require("@pactor-app/core");
1103
1200
  var import_markdown2 = require("@pactor-app/markdown");
1104
1201
  var import_runtime4 = require("@pactor-app/runtime");
1105
- var import_react6 = require("react");
1202
+ var import_react8 = require("react");
1106
1203
 
1107
1204
  // src/view/PartRenderer.tsx
1108
- var import_components2 = require("@pactor-app/ui/components");
1205
+ var import_components3 = require("@pactor-app/ui/components");
1109
1206
  var import_markdown = require("@pactor-app/markdown");
1110
1207
  var import_runtime3 = require("@pactor-app/runtime");
1111
1208
 
@@ -1147,59 +1244,7 @@ function useThrottledValue(value, intervalMs, enabled) {
1147
1244
  }
1148
1245
 
1149
1246
  // src/view/chrome/artifact-card.tsx
1150
- function buildArtifactCardFragment(artifact) {
1151
- return {
1152
- requires: ["Card", "Flex", "Text", "Badge", "Button"],
1153
- node: {
1154
- type: "Card",
1155
- props: { className: "pactor-chat-artifact-card" },
1156
- children: [
1157
- {
1158
- type: "Flex",
1159
- props: { justify: "space-between", align: "center", gap: "small" },
1160
- children: [
1161
- {
1162
- type: "Text",
1163
- props: {
1164
- text: artifact.title,
1165
- strong: true,
1166
- className: "pactor-chat-artifact-card__title"
1167
- }
1168
- },
1169
- {
1170
- type: "Badge",
1171
- props: {
1172
- text: artifact.kind,
1173
- variant: "secondary",
1174
- className: "pactor-chat-artifact-card__kind"
1175
- }
1176
- },
1177
- {
1178
- type: "Button",
1179
- props: {
1180
- text: "\u5728\u9762\u677F\u4E2D\u6253\u5F00",
1181
- variant: "default",
1182
- size: "small",
1183
- className: "pactor-chat-artifact-card__open"
1184
- },
1185
- events: {
1186
- onClick: [
1187
- {
1188
- action: "chat.openArtifact",
1189
- params: { artifact }
1190
- }
1191
- ]
1192
- }
1193
- }
1194
- ]
1195
- }
1196
- ]
1197
- }
1198
- };
1199
- }
1200
-
1201
- // src/view/chrome/ChromeSlot.tsx
1202
- var import_runtime2 = require("@pactor-app/runtime");
1247
+ var import_components2 = require("@pactor-app/ui/components");
1203
1248
  var import_react5 = require("react");
1204
1249
 
1205
1250
  // src/view/chrome/actions.ts
@@ -1280,6 +1325,12 @@ function ensureChatChromeActions(actions) {
1280
1325
  function invokeChatPanelClose() {
1281
1326
  handlers.panelClose?.();
1282
1327
  }
1328
+ function invokeChatOpenArtifact(artifact) {
1329
+ handlers.openArtifact?.(artifact);
1330
+ }
1331
+ function invokeChatOpenArtifactList() {
1332
+ handlers.openArtifactList?.();
1333
+ }
1283
1334
  function invokeChatPanelToggleList() {
1284
1335
  handlers.panelToggleList?.();
1285
1336
  }
@@ -1287,8 +1338,112 @@ function invokeChatPanelDownload() {
1287
1338
  handlers.panelDownload?.();
1288
1339
  }
1289
1340
 
1290
- // src/view/chrome/ChromeSlot.tsx
1341
+ // src/view/chrome/artifact-card.tsx
1291
1342
  var import_jsx_runtime2 = require("react/jsx-runtime");
1343
+ function artifactCardMeta(artifact) {
1344
+ const ext = resolveArtifactFileType(artifact);
1345
+ const typeLabel = (ext ?? artifact.kind).toUpperCase();
1346
+ const sizeLabel = formatArtifactSize(artifact.meta?.["size"]);
1347
+ return [sizeLabel, typeLabel].filter(Boolean).join(" \xB7 ");
1348
+ }
1349
+ function ChatArtifactCard({
1350
+ artifact
1351
+ }) {
1352
+ const icon = resolveArtifactIcon(artifact);
1353
+ const meta = artifactCardMeta(artifact);
1354
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1355
+ "button",
1356
+ {
1357
+ type: "button",
1358
+ className: `pactor-chat-artifact-card pactor-chat-artifact-card--${icon.tone}`,
1359
+ "data-artifact-kind": artifact.kind,
1360
+ "aria-label": `\u5728\u9762\u677F\u4E2D\u6253\u5F00\uFF1A${artifact.title}`,
1361
+ title: `\u5728\u9762\u677F\u4E2D\u6253\u5F00\uFF1A${artifact.title}`,
1362
+ onClick: () => invokeChatOpenArtifact(artifact),
1363
+ children: [
1364
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "pactor-chat-artifact-card__icon", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_components2.Icon, { name: icon.name, size: 20 }) }),
1365
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "pactor-chat-artifact-card__text", children: [
1366
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "pactor-chat-artifact-card__title", children: artifact.title }),
1367
+ meta ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "pactor-chat-artifact-card__meta", children: meta }) : null
1368
+ ] }),
1369
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "pactor-chat-artifact-card__arrow", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_components2.Icon, { name: "arrow-up-right", size: 14 }) })
1370
+ ]
1371
+ }
1372
+ );
1373
+ }
1374
+ var ARTIFACT_CARD_INTERNAL_COMPONENTS = {
1375
+ ChatArtifactCard,
1376
+ ChatArtifactCardGroup
1377
+ };
1378
+ var ARTIFACT_CARD_GROUP_LIMIT = 4;
1379
+ function ChatArtifactCardGroup({
1380
+ artifacts
1381
+ }) {
1382
+ const [expanded, setExpanded] = (0, import_react5.useState)(false);
1383
+ const overflow = artifacts.length > ARTIFACT_CARD_GROUP_LIMIT;
1384
+ const visible = overflow && !expanded ? artifacts.slice(0, ARTIFACT_CARD_GROUP_LIMIT) : artifacts;
1385
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "pactor-chat-artifact-group", children: [
1386
+ visible.map((artifact) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ChatArtifactCard, { artifact }, artifact.id)),
1387
+ overflow ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "pactor-chat-artifact-group__footer", children: [
1388
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1389
+ "button",
1390
+ {
1391
+ type: "button",
1392
+ className: "pactor-chat-artifact-group__toggle",
1393
+ "aria-expanded": expanded,
1394
+ onClick: () => setExpanded((value) => !value),
1395
+ children: [
1396
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1397
+ import_components2.Icon,
1398
+ {
1399
+ name: expanded ? "chevron-up" : "chevron-down",
1400
+ size: 12
1401
+ }
1402
+ ),
1403
+ expanded ? "\u6536\u8D77" : "\u5C55\u5F00"
1404
+ ]
1405
+ }
1406
+ ),
1407
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1408
+ "button",
1409
+ {
1410
+ type: "button",
1411
+ className: "pactor-chat-artifact-group__all",
1412
+ onClick: () => invokeChatOpenArtifactList(),
1413
+ children: [
1414
+ "\u67E5\u770B\u6240\u6709\u4EA7\u7269(",
1415
+ artifacts.length,
1416
+ ")",
1417
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_components2.Icon, { name: "chevron-right", size: 12 })
1418
+ ]
1419
+ }
1420
+ )
1421
+ ] }) : null
1422
+ ] });
1423
+ }
1424
+ function buildArtifactCardFragment(artifact) {
1425
+ return {
1426
+ requires: ["ChatArtifactCard"],
1427
+ node: {
1428
+ type: "ChatArtifactCard",
1429
+ props: { artifact }
1430
+ }
1431
+ };
1432
+ }
1433
+ function buildArtifactCardGroupFragment(artifacts) {
1434
+ return {
1435
+ requires: ["ChatArtifactCardGroup"],
1436
+ node: {
1437
+ type: "ChatArtifactCardGroup",
1438
+ props: { artifacts }
1439
+ }
1440
+ };
1441
+ }
1442
+
1443
+ // src/view/chrome/ChromeSlot.tsx
1444
+ var import_runtime2 = require("@pactor-app/runtime");
1445
+ var import_react6 = require("react");
1446
+ var import_jsx_runtime3 = require("react/jsx-runtime");
1292
1447
  var warnedMissing = /* @__PURE__ */ new Set();
1293
1448
  function warnMissingOnce(key, detail) {
1294
1449
  if (!warnedMissing.has(key)) {
@@ -1306,7 +1461,7 @@ function ChromeSlotInner({
1306
1461
  try {
1307
1462
  renderer = (0, import_runtime2.useRenderer)();
1308
1463
  } catch {
1309
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: fallback });
1464
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: fallback });
1310
1465
  }
1311
1466
  ensureChatChromeActions(renderer.context.actions);
1312
1467
  if (components) {
@@ -1317,7 +1472,7 @@ function ChromeSlotInner({
1317
1472
  `conflict:${name}`,
1318
1473
  `[@pactor-app/chat] chrome \u5185\u90E8\u7EC4\u4EF6\u540D\u300C${name}\u300D\u88AB\u5BBF\u4E3B\u5360\u7528\uFF0C\u5DF2\u56DE\u9000\u5185\u5EFA\u5B9E\u73B0`
1319
1474
  );
1320
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: fallback });
1475
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: fallback });
1321
1476
  }
1322
1477
  if (existing === void 0) {
1323
1478
  renderer.context.components.register(
@@ -1335,12 +1490,12 @@ function ChromeSlotInner({
1335
1490
  `${fragment.node.type}:${missing.join(",")}`,
1336
1491
  `[@pactor-app/chat] chrome DSL \u7247\u6BB5\u6240\u9700\u7EC4\u4EF6\u7C7B\u578B\u7F3A\u5931\uFF08${missing.join(" / ")}\uFF09\uFF0C\u5DF2\u56DE\u9000\u5185\u5EFA\u5B9E\u73B0`
1337
1492
  );
1338
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: fallback });
1493
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: fallback });
1339
1494
  }
1340
- const rendered = /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "pactor-chat-chrome", children: renderer.renderChildren([fragment.node]) });
1341
- return wrap ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: wrap(rendered) }) : rendered;
1495
+ const rendered = /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "pactor-chat-chrome", children: renderer.renderChildren([fragment.node]) });
1496
+ return wrap ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: wrap(rendered) }) : rendered;
1342
1497
  }
1343
- var ChromeSlotGuard = class extends import_react5.Component {
1498
+ var ChromeSlotGuard = class extends import_react6.Component {
1344
1499
  constructor() {
1345
1500
  super(...arguments);
1346
1501
  this.state = { failed: false };
@@ -1353,7 +1508,7 @@ var ChromeSlotGuard = class extends import_react5.Component {
1353
1508
  }
1354
1509
  };
1355
1510
  function ChromeSlot(props) {
1356
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ChromeSlotGuard, { fallback: props.fallback, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ChromeSlotInner, { ...props }) });
1511
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ChromeSlotGuard, { fallback: props.fallback, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ChromeSlotInner, { ...props }) });
1357
1512
  }
1358
1513
 
1359
1514
  // src/view/chrome/feedback.tsx
@@ -1377,9 +1532,9 @@ function buildStatusFragment(text) {
1377
1532
  }
1378
1533
 
1379
1534
  // src/view/PartRenderer.tsx
1380
- var import_jsx_runtime3 = require("react/jsx-runtime");
1535
+ var import_jsx_runtime4 = require("react/jsx-runtime");
1381
1536
  function ChatDenied({ deniedType }) {
1382
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "pactor-chat-denied", "data-pactor-chat-denied": deniedType, children: [
1537
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "pactor-chat-denied", "data-pactor-chat-denied": deniedType, children: [
1383
1538
  "\u8BE5\u7EC4\u4EF6\u4E0D\u5141\u8BB8\u5728 Chat \u4E2D\u4F7F\u7528",
1384
1539
  deniedType ? `\uFF1A${deniedType}` : ""
1385
1540
  ] });
@@ -1390,89 +1545,68 @@ function ChatDslNode({
1390
1545
  }) {
1391
1546
  const renderer = (0, import_runtime3.useRenderer)();
1392
1547
  const extraScope = scope ? buildChatScope(scope) : void 0;
1393
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: renderer.renderChildren([node], extraScope) });
1548
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children: renderer.renderChildren([node], extraScope) });
1394
1549
  }
1395
1550
  function SmoothText({ content, streaming }) {
1396
1551
  const shown = useSmoothStreamText(content, streaming);
1397
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "pactor-chat-text", children: shown });
1552
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "pactor-chat-text", children: shown });
1398
1553
  }
1399
1554
  function SmoothMarkdown({ content, streaming }) {
1400
1555
  const shown = useSmoothStreamText(content, streaming);
1401
1556
  const throttled = useThrottledValue(shown, 100, streaming);
1402
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_markdown.MarkdownRenderer, { content: throttled });
1557
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_markdown.MarkdownRenderer, { content: throttled });
1403
1558
  }
1404
- function PartRenderer({ part, runtime, scope, streaming = false, onOpenArtifact }) {
1559
+ function PartRenderer({ part, runtime, scope, streaming = false }) {
1405
1560
  switch (part.type) {
1406
1561
  case "text":
1407
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SmoothText, { content: part.content, streaming });
1562
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SmoothText, { content: part.content, streaming });
1408
1563
  case "markdown":
1409
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SmoothMarkdown, { content: part.content, streaming });
1564
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SmoothMarkdown, { content: part.content, streaming });
1410
1565
  case "thinking":
1411
1566
  case "tool-call":
1412
1567
  case "tool-result":
1413
1568
  return null;
1414
1569
  case "dsl": {
1415
1570
  if (!part.schema || !runtime) {
1416
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1571
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1417
1572
  ChromeSlot,
1418
1573
  {
1419
1574
  fragment: buildStatusFragment(
1420
1575
  part.schema ? "DSL \u6E32\u67D3\u4E0D\u53EF\u7528\uFF08\u672A\u6CE8\u5165 Safe Registry\uFF09" : "\u5185\u5BB9\u751F\u6210\u4E2D\u2026"
1421
1576
  ),
1422
- fallback: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "pactor-chat-dsl-pending", children: part.schema ? "DSL \u6E32\u67D3\u4E0D\u53EF\u7528\uFF08\u672A\u6CE8\u5165 Safe Registry\uFF09" : "\u5185\u5BB9\u751F\u6210\u4E2D\u2026" })
1577
+ fallback: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "pactor-chat-dsl-pending", children: part.schema ? "DSL \u6E32\u67D3\u4E0D\u53EF\u7528\uFF08\u672A\u6CE8\u5165 Safe Registry\uFF09" : "\u5185\u5BB9\u751F\u6210\u4E2D\u2026" })
1423
1578
  }
1424
1579
  );
1425
1580
  }
1426
1581
  const guarded = guardChatDsl(part.schema, runtime.context.components);
1427
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "pactor-chat-dsl", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_runtime3.DslRenderer, { context: runtime.context, engine: runtime.engine, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ChatDslNode, { node: guarded, scope }) }) });
1582
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "pactor-chat-dsl", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_runtime3.DslRenderer, { context: runtime.context, engine: runtime.engine, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ChatDslNode, { node: guarded, scope }) }) });
1428
1583
  }
1429
1584
  case "error":
1430
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1585
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1431
1586
  ChromeSlot,
1432
1587
  {
1433
1588
  fragment: buildErrorFragment(part.message),
1434
- fallback: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "pactor-chat-error", role: "alert", children: [
1435
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_components2.Icon, { name: "error", size: 14 }),
1436
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: part.message })
1589
+ fallback: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "pactor-chat-error", role: "alert", children: [
1590
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_components3.Icon, { name: "error", size: 14 }),
1591
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: part.message })
1437
1592
  ] })
1438
1593
  }
1439
1594
  );
1440
1595
  case "status":
1441
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1596
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1442
1597
  ChromeSlot,
1443
1598
  {
1444
1599
  fragment: buildStatusFragment(part.text),
1445
- fallback: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "pactor-chat-status", children: part.text })
1600
+ fallback: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "pactor-chat-status", children: part.text })
1446
1601
  }
1447
1602
  );
1448
1603
  case "artifact":
1449
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1604
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1450
1605
  ChromeSlot,
1451
1606
  {
1452
1607
  fragment: buildArtifactCardFragment(part.artifact),
1453
- fallback: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1454
- "div",
1455
- {
1456
- className: "pactor-chat-artifact-card",
1457
- "data-artifact-kind": part.artifact.kind,
1458
- children: [
1459
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "pactor-chat-artifact-card__title", children: part.artifact.title }),
1460
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "pactor-chat-artifact-card__kind", children: part.artifact.kind }),
1461
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1462
- "button",
1463
- {
1464
- type: "button",
1465
- className: "pactor-chat-artifact-card__open",
1466
- onClick: () => onOpenArtifact?.(part.artifact),
1467
- children: [
1468
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_components2.Icon, { name: "panel-right-open", size: 13, strokeWidth: 1.7 }),
1469
- "\u5728\u9762\u677F\u4E2D\u6253\u5F00"
1470
- ]
1471
- }
1472
- )
1473
- ]
1474
- }
1475
- )
1608
+ components: ARTIFACT_CARD_INTERNAL_COMPONENTS,
1609
+ fallback: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ChatArtifactCard, { artifact: part.artifact })
1476
1610
  }
1477
1611
  );
1478
1612
  default:
@@ -1481,10 +1615,17 @@ function PartRenderer({ part, runtime, scope, streaming = false, onOpenArtifact
1481
1615
  }
1482
1616
 
1483
1617
  // src/view/chrome/panel-header.tsx
1484
- var import_components3 = require("@pactor-app/ui/components");
1485
- var import_jsx_runtime4 = require("react/jsx-runtime");
1618
+ var import_components4 = require("@pactor-app/ui/components");
1619
+ var import_react7 = require("react");
1620
+ var import_jsx_runtime5 = require("react/jsx-runtime");
1621
+ var ChatPanelContext = (0, import_react7.createContext)(
1622
+ null
1623
+ );
1624
+ function artifactIconName(artifact) {
1625
+ return artifact ? resolveArtifactIconName(artifact) : "file";
1626
+ }
1486
1627
  function ChatPanelCloseButton() {
1487
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1628
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1488
1629
  "button",
1489
1630
  {
1490
1631
  type: "button",
@@ -1492,17 +1633,16 @@ function ChatPanelCloseButton() {
1492
1633
  title: "\u5173\u95ED\u9762\u677F",
1493
1634
  "aria-label": "\u5173\u95ED\u9762\u677F",
1494
1635
  onClick: () => invokeChatPanelClose(),
1495
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_components3.Icon, { name: "x", size: 16 })
1636
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_components4.Icon, { name: "x", size: 16 })
1496
1637
  }
1497
1638
  );
1498
1639
  }
1499
- var PANEL_HEADER_INTERNAL_COMPONENTS = {
1500
- ChatPanelCloseButton,
1501
- ChatPanelDownloadButton,
1502
- ChatPanelListButton
1503
- };
1504
1640
  function ChatPanelListButton() {
1505
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1641
+ const ctx = (0, import_react7.useContext)(ChatPanelContext);
1642
+ if (ctx?.view === "list") {
1643
+ return null;
1644
+ }
1645
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1506
1646
  "button",
1507
1647
  {
1508
1648
  type: "button",
@@ -1510,12 +1650,12 @@ function ChatPanelListButton() {
1510
1650
  title: "\u4EA7\u7269\u76EE\u5F55",
1511
1651
  "aria-label": "\u4EA7\u7269\u76EE\u5F55",
1512
1652
  onClick: () => invokeChatPanelToggleList(),
1513
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_components3.Icon, { name: "arrow-left", size: 16 })
1653
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_components4.Icon, { name: "arrow-left", size: 16 })
1514
1654
  }
1515
1655
  );
1516
1656
  }
1517
1657
  function ChatPanelDownloadButton() {
1518
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1658
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1519
1659
  "button",
1520
1660
  {
1521
1661
  type: "button",
@@ -1523,10 +1663,58 @@ function ChatPanelDownloadButton() {
1523
1663
  title: "\u4E0B\u8F7D\u4EA7\u7269",
1524
1664
  "aria-label": "\u4E0B\u8F7D\u4EA7\u7269",
1525
1665
  onClick: () => invokeChatPanelDownload(),
1526
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_components3.Icon, { name: "download", size: 16 })
1666
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_components4.Icon, { name: "download", size: 16 })
1667
+ }
1668
+ );
1669
+ }
1670
+ function ChatPanelArtifactMenu() {
1671
+ const ctx = (0, import_react7.useContext)(ChatPanelContext);
1672
+ if (!ctx || ctx.artifacts.length === 0) {
1673
+ return null;
1674
+ }
1675
+ const active = ctx.artifacts.find((item) => item.id === ctx.activeId);
1676
+ const inList = ctx.view === "list";
1677
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1678
+ import_components4.DropdownMenu,
1679
+ {
1680
+ items: ctx.artifacts.map((item) => ({
1681
+ label: item.title,
1682
+ value: item.id,
1683
+ icon: artifactIconName(item)
1684
+ })),
1685
+ onSelect: (value) => {
1686
+ const target = ctx.artifacts.find((item) => item.id === value);
1687
+ if (target) {
1688
+ ctx.onSelectArtifact?.(target);
1689
+ }
1690
+ },
1691
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1692
+ "span",
1693
+ {
1694
+ className: "pactor-chat-inspector__menu-trigger",
1695
+ "data-view": ctx.view,
1696
+ children: [
1697
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1698
+ import_components4.Icon,
1699
+ {
1700
+ name: inList ? "folder" : artifactIconName(active),
1701
+ size: 13
1702
+ }
1703
+ ),
1704
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "pactor-chat-inspector__title", children: inList ? "\u4EA7\u7269\u76EE\u5F55" : active?.title ?? "\u4EA7\u51FA\u7269" }),
1705
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_components4.Icon, { name: "chevron-down", size: 12 })
1706
+ ]
1707
+ }
1708
+ )
1527
1709
  }
1528
1710
  );
1529
1711
  }
1712
+ var PANEL_HEADER_INTERNAL_COMPONENTS = {
1713
+ ChatPanelCloseButton,
1714
+ ChatPanelDownloadButton,
1715
+ ChatPanelListButton,
1716
+ ChatPanelArtifactMenu
1717
+ };
1530
1718
  function buildPanelHeaderFragment(props) {
1531
1719
  return {
1532
1720
  requires: [
@@ -1535,7 +1723,8 @@ function buildPanelHeaderFragment(props) {
1535
1723
  "Badge",
1536
1724
  "ChatPanelCloseButton",
1537
1725
  "ChatPanelDownloadButton",
1538
- "ChatPanelListButton"
1726
+ "ChatPanelListButton",
1727
+ "ChatPanelArtifactMenu"
1539
1728
  ],
1540
1729
  node: {
1541
1730
  type: "Flex",
@@ -1551,7 +1740,7 @@ function buildPanelHeaderFragment(props) {
1551
1740
  props: { align: "center", gap: "small" },
1552
1741
  children: [
1553
1742
  ...props.showListButton ? [{ type: "ChatPanelListButton" }] : [],
1554
- {
1743
+ props.showMenu ? { type: "ChatPanelArtifactMenu" } : {
1555
1744
  type: "Text",
1556
1745
  props: {
1557
1746
  text: props.title,
@@ -1559,14 +1748,16 @@ function buildPanelHeaderFragment(props) {
1559
1748
  className: "pactor-chat-inspector__title"
1560
1749
  }
1561
1750
  },
1562
- {
1563
- type: "Badge",
1564
- props: {
1565
- text: props.kind,
1566
- variant: "secondary",
1567
- className: "pactor-chat-inspector__kind"
1751
+ ...props.view === "list" ? [] : [
1752
+ {
1753
+ type: "Badge",
1754
+ props: {
1755
+ text: props.kind,
1756
+ variant: "secondary",
1757
+ className: "pactor-chat-inspector__kind"
1758
+ }
1568
1759
  }
1569
- }
1760
+ ]
1570
1761
  ]
1571
1762
  },
1572
1763
  {
@@ -1583,9 +1774,9 @@ function buildPanelHeaderFragment(props) {
1583
1774
  }
1584
1775
 
1585
1776
  // src/view/ArtifactPanel.tsx
1586
- var import_jsx_runtime5 = require("react/jsx-runtime");
1777
+ var import_jsx_runtime6 = require("react/jsx-runtime");
1587
1778
  function useArtifactRuntime(safeRegistry, user) {
1588
- return (0, import_react6.useMemo)(() => {
1779
+ return (0, import_react8.useMemo)(() => {
1589
1780
  if (!safeRegistry) {
1590
1781
  return void 0;
1591
1782
  }
@@ -1597,7 +1788,7 @@ function useArtifactRuntime(safeRegistry, user) {
1597
1788
  return createChatRuntime({ safeRegistry: components, user });
1598
1789
  }, [safeRegistry, user]);
1599
1790
  }
1600
- var ArtifactDslGuard = class extends import_react6.Component {
1791
+ var ArtifactDslGuard = class extends import_react8.Component {
1601
1792
  constructor() {
1602
1793
  super(...arguments);
1603
1794
  this.state = { failed: false };
@@ -1609,12 +1800,12 @@ var ArtifactDslGuard = class extends import_react6.Component {
1609
1800
  console.warn("[@pactor-app/chat] DSL \u4EA7\u51FA\u7269\u6E32\u67D3\u5931\u8D25\uFF0C\u5DF2\u964D\u7EA7\u5C55\u793A", error);
1610
1801
  }
1611
1802
  render() {
1612
- return this.state.failed ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "pactor-chat-denied", children: "DSL \u4EA7\u51FA\u7269\u6E32\u67D3\u5931\u8D25\uFF0C\u5DF2\u964D\u7EA7\u5C55\u793A" }) : this.props.children;
1803
+ return this.state.failed ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "pactor-chat-denied", children: "DSL \u4EA7\u51FA\u7269\u6E32\u67D3\u5931\u8D25\uFF0C\u5DF2\u964D\u7EA7\u5C55\u793A" }) : this.props.children;
1613
1804
  }
1614
1805
  };
1615
1806
  function ArtifactDslNode({ node }) {
1616
1807
  const { renderChildren } = (0, import_runtime4.useRenderer)();
1617
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children: renderChildren([node]) });
1808
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children: renderChildren([node]) });
1618
1809
  }
1619
1810
  function ArtifactDslContent({
1620
1811
  content,
@@ -1622,14 +1813,13 @@ function ArtifactDslContent({
1622
1813
  }) {
1623
1814
  const node = typeof content === "object" && content !== null && !Array.isArray(content) && typeof content.type === "string" ? content : void 0;
1624
1815
  if (!node || !runtime) {
1625
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "pactor-chat-denied", children: node ? "DSL \u9884\u89C8\u4E0D\u53EF\u7528\uFF08\u672A\u6CE8\u5165 Safe Registry\uFF09" : "DSL \u4EA7\u51FA\u7269\u5185\u5BB9\u65E0\u6548" });
1816
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "pactor-chat-denied", children: node ? "DSL \u9884\u89C8\u4E0D\u53EF\u7528\uFF08\u672A\u6CE8\u5165 Safe Registry\uFF09" : "DSL \u4EA7\u51FA\u7269\u5185\u5BB9\u65E0\u6548" });
1626
1817
  }
1627
1818
  const guarded = guardChatDsl(node, runtime.context.components);
1628
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_runtime4.DslRenderer, { context: runtime.context, engine: runtime.engine, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ArtifactDslGuard, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ArtifactDslNode, { node: guarded }) }) });
1819
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_runtime4.DslRenderer, { context: runtime.context, engine: runtime.engine, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ArtifactDslGuard, { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ArtifactDslNode, { node: guarded }) }) });
1629
1820
  }
1630
- function ArtifactKindIcon({ kind }) {
1631
- const name = kind === "code" ? "code" : kind === "dsl" ? "layout-grid" : "file-text";
1632
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_components4.Icon, { name, size: 13 });
1821
+ function ArtifactKindIcon({ artifact }) {
1822
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_components5.Icon, { name: resolveArtifactIconName(artifact), size: 13 });
1633
1823
  }
1634
1824
  function buildArtifactTree(artifacts) {
1635
1825
  const root = { name: "", path: "", children: [] };
@@ -1671,7 +1861,7 @@ function ArtifactListView({
1671
1861
  activeId,
1672
1862
  onSelect
1673
1863
  }) {
1674
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("ul", { className: "pactor-chat-inspector__list", children: nodes.map((node) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1864
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("ul", { className: "pactor-chat-inspector__list", children: nodes.map((node) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1675
1865
  ArtifactTreeRow,
1676
1866
  {
1677
1867
  node,
@@ -1686,9 +1876,9 @@ function ArtifactTreeRow({
1686
1876
  activeId,
1687
1877
  onSelect
1688
1878
  }) {
1689
- const [open, setOpen] = (0, import_react6.useState)(true);
1879
+ const [open, setOpen] = (0, import_react8.useState)(true);
1690
1880
  if (node.artifact) {
1691
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1881
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1692
1882
  "button",
1693
1883
  {
1694
1884
  type: "button",
@@ -1696,15 +1886,15 @@ function ArtifactTreeRow({
1696
1886
  "data-active": node.artifact.id === activeId,
1697
1887
  onClick: () => onSelect?.(node.artifact),
1698
1888
  children: [
1699
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ArtifactKindIcon, { kind: node.artifact.kind }),
1700
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "pactor-chat-inspector__list-item-title", children: node.artifact.title }),
1701
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "pactor-chat-inspector__kind", children: node.artifact.kind })
1889
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ArtifactKindIcon, { artifact: node.artifact }),
1890
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "pactor-chat-inspector__list-item-title", children: node.artifact.title }),
1891
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "pactor-chat-inspector__kind", children: node.artifact.kind })
1702
1892
  ]
1703
1893
  }
1704
1894
  ) });
1705
1895
  }
1706
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("li", { children: [
1707
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1896
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("li", { children: [
1897
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1708
1898
  "button",
1709
1899
  {
1710
1900
  type: "button",
@@ -1713,13 +1903,13 @@ function ArtifactTreeRow({
1713
1903
  "data-open": open,
1714
1904
  onClick: () => setOpen((value) => !value),
1715
1905
  children: [
1716
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "pactor-chat-trace__chevron", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_components4.Icon, { name: "chevron-right", size: 12 }) }),
1717
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_components4.Icon, { name: "folder", size: 13 }),
1718
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: node.name })
1906
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "pactor-chat-trace__chevron", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_components5.Icon, { name: "chevron-right", size: 12 }) }),
1907
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_components5.Icon, { name: "folder", size: 13 }),
1908
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: node.name })
1719
1909
  ]
1720
1910
  }
1721
1911
  ),
1722
- open && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "pactor-chat-inspector__list-children", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1912
+ open && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "pactor-chat-inspector__list-children", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1723
1913
  ArtifactListView,
1724
1914
  {
1725
1915
  nodes: node.children,
@@ -1732,7 +1922,7 @@ function ArtifactTreeRow({
1732
1922
  function ArtifactImageContent({ artifact }) {
1733
1923
  const raw = String(artifact.content).trim();
1734
1924
  const src = raw.startsWith("<svg") || raw.startsWith("<?xml") ? `data:image/svg+xml;utf8,${encodeURIComponent(raw)}` : raw;
1735
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "pactor-chat-inspector__image", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("img", { src, alt: artifact.title }) });
1925
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "pactor-chat-inspector__image", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("img", { src, alt: artifact.title }) });
1736
1926
  }
1737
1927
  function ArtifactContent({
1738
1928
  artifact,
@@ -1742,23 +1932,23 @@ function ArtifactContent({
1742
1932
  const ext = resolveArtifactFileType(artifact);
1743
1933
  const custom = (ext ? viewers?.[ext] : void 0) ?? viewers?.[artifact.kind];
1744
1934
  if (custom) {
1745
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children: custom(artifact) });
1935
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children: custom(artifact) });
1746
1936
  }
1747
1937
  if (isImageArtifact(artifact)) {
1748
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ArtifactImageContent, { artifact });
1938
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ArtifactImageContent, { artifact });
1749
1939
  }
1750
1940
  switch (artifact.kind) {
1751
1941
  case "markdown":
1752
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_markdown2.MarkdownRenderer, { content: String(artifact.content) });
1942
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_markdown2.MarkdownRenderer, { content: String(artifact.content) });
1753
1943
  case "code":
1754
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "pactor-chat-inspector__code", children: [
1755
- artifact.language ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "pactor-chat-inspector__code-lang", children: artifact.language }) : null,
1756
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("pre", { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("code", { children: String(artifact.content) }) })
1944
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "pactor-chat-inspector__code", children: [
1945
+ artifact.language ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "pactor-chat-inspector__code-lang", children: artifact.language }) : null,
1946
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("pre", { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("code", { children: String(artifact.content) }) })
1757
1947
  ] });
1758
1948
  case "text":
1759
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("pre", { className: "pactor-chat-inspector__text", children: String(artifact.content) });
1949
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("pre", { className: "pactor-chat-inspector__text", children: String(artifact.content) });
1760
1950
  case "dsl":
1761
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ArtifactDslContent, { content: artifact.content, runtime });
1951
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ArtifactDslContent, { content: artifact.content, runtime });
1762
1952
  default:
1763
1953
  return null;
1764
1954
  }
@@ -1768,6 +1958,8 @@ function ArtifactPanel({
1768
1958
  artifacts,
1769
1959
  activeArtifactId,
1770
1960
  onSelectArtifact,
1961
+ viewRequest,
1962
+ onViewRequestConsumed,
1771
1963
  inspector,
1772
1964
  onClose,
1773
1965
  safeRegistry,
@@ -1776,20 +1968,27 @@ function ArtifactPanel({
1776
1968
  className
1777
1969
  }) {
1778
1970
  const runtime = useArtifactRuntime(safeRegistry, user);
1779
- const [view, setView] = (0, import_react6.useState)("content");
1971
+ const [view, setView] = (0, import_react8.useState)("content");
1780
1972
  const activeId = activeArtifactId ?? artifact?.id;
1781
- (0, import_react6.useEffect)(() => {
1973
+ (0, import_react8.useEffect)(() => {
1782
1974
  setView("content");
1783
1975
  }, [activeId]);
1976
+ (0, import_react8.useEffect)(() => {
1977
+ if (viewRequest != null) {
1978
+ setView("list");
1979
+ onViewRequestConsumed?.();
1980
+ }
1981
+ }, [viewRequest]);
1784
1982
  const showListButton = artifacts !== void 0 && artifacts.length > 0;
1785
- const toggleListRef = (0, import_react6.useRef)(() => {
1983
+ const showMenu = artifacts !== void 0 && artifacts.length > 0;
1984
+ const toggleListRef = (0, import_react8.useRef)(() => {
1786
1985
  });
1787
1986
  toggleListRef.current = () => setView((value) => value === "list" ? "content" : "list");
1788
- const closeRef = (0, import_react6.useRef)(onClose);
1987
+ const closeRef = (0, import_react8.useRef)(onClose);
1789
1988
  closeRef.current = onClose;
1790
- const artifactRef = (0, import_react6.useRef)(artifact);
1989
+ const artifactRef = (0, import_react8.useRef)(artifact);
1791
1990
  artifactRef.current = artifact;
1792
- (0, import_react6.useEffect)(() => {
1991
+ (0, import_react8.useEffect)(() => {
1793
1992
  setChatChromeHandlers({
1794
1993
  panelClose: () => closeRef.current?.(),
1795
1994
  panelToggleList: () => toggleListRef.current(),
@@ -1801,8 +2000,8 @@ function ArtifactPanel({
1801
2000
  }
1802
2001
  });
1803
2002
  }, []);
1804
- const panelRef = (0, import_react6.useRef)(null);
1805
- const [width, setWidth] = (0, import_react6.useState)(null);
2003
+ const panelRef = (0, import_react8.useRef)(null);
2004
+ const [width, setWidth] = (0, import_react8.useState)(null);
1806
2005
  const handleResizeStart = (event) => {
1807
2006
  event.preventDefault();
1808
2007
  const panel = panelRef.current;
@@ -1811,14 +2010,14 @@ function ArtifactPanel({
1811
2010
  }
1812
2011
  const hostRect = panel.parentElement?.getBoundingClientRect();
1813
2012
  const hostWidth = hostRect !== void 0 && hostRect.width > 0 ? hostRect.width : window.innerWidth;
1814
- const maxWidth = hostWidth * 0.7;
2013
+ const maxWidth = hostWidth * 2 / 3;
1815
2014
  const startWidth = panel.getBoundingClientRect().width;
1816
2015
  const startX = event.clientX;
1817
2016
  const prevUserSelect = document.body.style.userSelect;
1818
2017
  document.body.style.userSelect = "none";
1819
2018
  const onMove = (moveEvent) => {
1820
2019
  const next = startWidth + (startX - moveEvent.clientX);
1821
- setWidth(Math.round(Math.min(Math.max(next, 320), maxWidth)));
2020
+ setWidth(Math.round(Math.min(Math.max(next, 480), maxWidth)));
1822
2021
  };
1823
2022
  const onUp = () => {
1824
2023
  document.body.style.userSelect = prevUserSelect;
@@ -1828,121 +2027,88 @@ function ArtifactPanel({
1828
2027
  document.addEventListener("pointermove", onMove);
1829
2028
  document.addEventListener("pointerup", onUp);
1830
2029
  };
1831
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1832
- "aside",
2030
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2031
+ ChatPanelContext.Provider,
1833
2032
  {
1834
- ref: panelRef,
1835
- className: `pactor-chat-inspector${className ? ` ${className}` : ""}`,
1836
- "data-kind": artifact?.kind,
1837
- style: width !== null ? { width: `${width}px` } : void 0,
1838
- children: [
1839
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1840
- "div",
1841
- {
1842
- className: "pactor-chat-inspector__resize",
1843
- role: "separator",
1844
- "aria-orientation": "vertical",
1845
- "aria-label": "\u62D6\u52A8\u8C03\u6574\u9762\u677F\u5BBD\u5EA6",
1846
- onPointerDown: handleResizeStart
1847
- }
1848
- ),
1849
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "pactor-chat-inspector__header", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1850
- ChromeSlot,
1851
- {
1852
- fragment: buildPanelHeaderFragment({
1853
- title: artifact?.title ?? "\u4EA7\u51FA\u7269",
1854
- kind: artifact?.kind ?? "text",
1855
- showListButton,
1856
- showDownload: artifact != null
1857
- }),
1858
- components: PANEL_HEADER_INTERNAL_COMPONENTS,
1859
- fallback: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1860
- showListButton ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1861
- "button",
1862
- {
1863
- type: "button",
1864
- className: "pactor-chat-icon-button pactor-chat-inspector__list-toggle",
1865
- title: "\u4EA7\u7269\u76EE\u5F55",
1866
- "aria-label": "\u4EA7\u7269\u76EE\u5F55",
1867
- onClick: () => toggleListRef.current(),
1868
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_components4.Icon, { name: "arrow-left", size: 16, strokeWidth: 1.7 })
1869
- }
1870
- ) : null,
1871
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "pactor-chat-inspector__title", children: artifact?.title ?? "\u4EA7\u51FA\u7269" }),
1872
- artifact ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "pactor-chat-inspector__kind", children: artifact.kind }) : null,
1873
- artifact ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1874
- "button",
1875
- {
1876
- type: "button",
1877
- className: "pactor-chat-icon-button pactor-chat-inspector__download",
1878
- title: "\u4E0B\u8F7D\u4EA7\u7269",
1879
- "aria-label": "\u4E0B\u8F7D\u4EA7\u7269",
1880
- onClick: () => void downloadArtifact(artifact),
1881
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_components4.Icon, { name: "download", size: 16, strokeWidth: 1.7 })
1882
- }
1883
- ) : null,
1884
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1885
- "button",
1886
- {
1887
- type: "button",
1888
- className: "pactor-chat-icon-button pactor-chat-inspector__close",
1889
- "aria-label": "\u5173\u95ED\u9762\u677F",
1890
- onClick: onClose,
1891
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_components4.Icon, { name: "x", size: 16, strokeWidth: 1.7 })
1892
- }
1893
- )
1894
- ] })
1895
- }
1896
- ) }),
1897
- artifacts !== void 0 && artifacts.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "pactor-chat-inspector__tabs", role: "tablist", children: artifacts.map((item) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1898
- "button",
1899
- {
1900
- type: "button",
1901
- role: "tab",
1902
- "aria-selected": item.id === activeId,
1903
- "data-active": item.id === activeId,
1904
- className: "pactor-chat-inspector__tab",
1905
- title: item.title,
1906
- onClick: () => onSelectArtifact?.(item),
1907
- children: [
1908
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ArtifactKindIcon, { kind: item.kind }),
1909
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "pactor-chat-inspector__tab-title", children: item.title })
1910
- ]
1911
- },
1912
- item.id
1913
- )) }) : null,
1914
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "pactor-chat-inspector__body", children: view === "list" && artifacts !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1915
- ArtifactListView,
1916
- {
1917
- nodes: buildArtifactTree(artifacts),
1918
- activeId,
1919
- onSelect: onSelectArtifact
1920
- }
1921
- ) : inspector !== void 0 && inspector !== null ? inspector : artifact ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1922
- ArtifactContent,
1923
- {
1924
- artifact,
1925
- runtime,
1926
- viewers: artifactViewers
1927
- }
1928
- ) : null })
1929
- ]
2033
+ value: {
2034
+ artifacts: artifacts ?? [],
2035
+ activeId,
2036
+ view,
2037
+ onSelectArtifact
2038
+ },
2039
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2040
+ "aside",
2041
+ {
2042
+ ref: panelRef,
2043
+ className: `pactor-chat-inspector${className ? ` ${className}` : ""}`,
2044
+ "data-kind": artifact?.kind,
2045
+ style: width !== null ? { width: `${width}px` } : void 0,
2046
+ children: [
2047
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2048
+ "div",
2049
+ {
2050
+ className: "pactor-chat-inspector__resize",
2051
+ role: "separator",
2052
+ "aria-orientation": "vertical",
2053
+ "aria-label": "\u62D6\u52A8\u8C03\u6574\u9762\u677F\u5BBD\u5EA6",
2054
+ onPointerDown: handleResizeStart
2055
+ }
2056
+ ),
2057
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "pactor-chat-inspector__header", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2058
+ ChromeSlot,
2059
+ {
2060
+ fragment: buildPanelHeaderFragment({
2061
+ title: view === "list" ? "\u4EA7\u7269\u76EE\u5F55" : artifact?.title ?? "\u4EA7\u51FA\u7269",
2062
+ kind: artifact?.kind ?? "text",
2063
+ showListButton,
2064
+ showDownload: artifact != null,
2065
+ showMenu,
2066
+ view
2067
+ }),
2068
+ components: PANEL_HEADER_INTERNAL_COMPONENTS,
2069
+ fallback: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
2070
+ showListButton ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ChatPanelListButton, {}) : null,
2071
+ showMenu ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ChatPanelArtifactMenu, {}) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "pactor-chat-inspector__title", children: view === "list" ? "\u4EA7\u7269\u76EE\u5F55" : artifact?.title ?? "\u4EA7\u51FA\u7269" }),
2072
+ view !== "list" && artifact ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "pactor-chat-inspector__kind", children: artifact.kind }) : null,
2073
+ artifact ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ChatPanelDownloadButton, {}) : null,
2074
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ChatPanelCloseButton, {})
2075
+ ] })
2076
+ }
2077
+ ) }),
2078
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "pactor-chat-inspector__body", children: view === "list" && artifacts !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2079
+ ArtifactListView,
2080
+ {
2081
+ nodes: buildArtifactTree(artifacts),
2082
+ activeId,
2083
+ onSelect: onSelectArtifact
2084
+ }
2085
+ ) : inspector !== void 0 && inspector !== null ? inspector : artifact ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2086
+ ArtifactContent,
2087
+ {
2088
+ artifact,
2089
+ runtime,
2090
+ viewers: artifactViewers
2091
+ }
2092
+ ) : null })
2093
+ ]
2094
+ }
2095
+ )
1930
2096
  }
1931
2097
  );
1932
2098
  }
1933
2099
 
1934
2100
  // src/view/ChatView.tsx
1935
- var import_components10 = require("@pactor-app/ui/components");
2101
+ var import_components11 = require("@pactor-app/ui/components");
1936
2102
  var import_core4 = require("@pactor-app/core");
1937
- var import_react15 = require("react");
2103
+ var import_react17 = require("react");
1938
2104
 
1939
2105
  // src/view/Composer.tsx
1940
- var import_components7 = require("@pactor-app/ui/components");
1941
- var import_react11 = require("react");
2106
+ var import_components8 = require("@pactor-app/ui/components");
2107
+ var import_react13 = require("react");
1942
2108
 
1943
2109
  // src/view/AnchoredPopover.tsx
1944
- var import_react7 = require("react");
1945
- var import_jsx_runtime6 = require("react/jsx-runtime");
2110
+ var import_react9 = require("react");
2111
+ var import_jsx_runtime7 = require("react/jsx-runtime");
1946
2112
  function AnchoredPopover({
1947
2113
  anchorRect,
1948
2114
  onClose,
@@ -1951,9 +2117,9 @@ function AnchoredPopover({
1951
2117
  role = "dialog",
1952
2118
  sideOffset = 8
1953
2119
  }) {
1954
- const ref = (0, import_react7.useRef)(null);
1955
- const [position, setPosition] = (0, import_react7.useState)(null);
1956
- (0, import_react7.useLayoutEffect)(() => {
2120
+ const ref = (0, import_react9.useRef)(null);
2121
+ const [position, setPosition] = (0, import_react9.useState)(null);
2122
+ (0, import_react9.useLayoutEffect)(() => {
1957
2123
  const element = ref.current;
1958
2124
  if (!element) return;
1959
2125
  const height = element.offsetHeight;
@@ -1971,7 +2137,7 @@ function AnchoredPopover({
1971
2137
  }
1972
2138
  );
1973
2139
  }, [anchorRect, sideOffset]);
1974
- (0, import_react7.useEffect)(() => {
2140
+ (0, import_react9.useEffect)(() => {
1975
2141
  const onKeyDown = (event) => {
1976
2142
  if (event.key !== "Escape") return;
1977
2143
  const element = ref.current;
@@ -1999,7 +2165,7 @@ function AnchoredPopover({
1999
2165
  position?.below ? "pactor-chat-popover--below" : "",
2000
2166
  className ?? ""
2001
2167
  ].filter(Boolean).join(" ");
2002
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2168
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2003
2169
  "div",
2004
2170
  {
2005
2171
  ref,
@@ -2018,8 +2184,8 @@ function AnchoredPopover({
2018
2184
  }
2019
2185
 
2020
2186
  // src/view/ModelChip.tsx
2021
- var import_components5 = require("@pactor-app/ui/components");
2022
- var import_react8 = require("react");
2187
+ var import_components6 = require("@pactor-app/ui/components");
2188
+ var import_react10 = require("react");
2023
2189
 
2024
2190
  // src/view/chrome/model-select.tsx
2025
2191
  function buildModelSelectFragment(props) {
@@ -2045,17 +2211,17 @@ function buildModelSelectFragment(props) {
2045
2211
  }
2046
2212
 
2047
2213
  // src/view/ModelChip.tsx
2048
- var import_jsx_runtime7 = require("react/jsx-runtime");
2214
+ var import_jsx_runtime8 = require("react/jsx-runtime");
2049
2215
  function ModelChip({
2050
2216
  models,
2051
2217
  model,
2052
2218
  onModelChange
2053
2219
  }) {
2054
- const chipRef = (0, import_react8.useRef)(null);
2055
- const [anchor, setAnchor] = (0, import_react8.useState)(null);
2220
+ const chipRef = (0, import_react10.useRef)(null);
2221
+ const [anchor, setAnchor] = (0, import_react10.useState)(null);
2056
2222
  const currentOption = models.find((option) => option.value === model) ?? models[0];
2057
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
2058
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2223
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
2224
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
2059
2225
  "button",
2060
2226
  {
2061
2227
  ref: chipRef,
@@ -2065,18 +2231,18 @@ function ModelChip({
2065
2231
  "aria-label": "\u9009\u62E9\u6A21\u578B",
2066
2232
  onClick: () => setAnchor(chipRef.current.getBoundingClientRect()),
2067
2233
  children: [
2068
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "pactor-chat-model-chip__label", children: currentOption.label }),
2069
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_components5.Icon, { name: "chevrons-up-down", size: 12 })
2234
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "pactor-chat-model-chip__label", children: currentOption.label }),
2235
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_components6.Icon, { name: "chevrons-up-down", size: 12 })
2070
2236
  ]
2071
2237
  }
2072
2238
  ),
2073
- anchor && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2239
+ anchor && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2074
2240
  AnchoredPopover,
2075
2241
  {
2076
2242
  anchorRect: anchor,
2077
2243
  onClose: () => setAnchor(null),
2078
2244
  role: "listbox",
2079
- children: models.map((option) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2245
+ children: models.map((option) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
2080
2246
  "button",
2081
2247
  {
2082
2248
  type: "button",
@@ -2088,8 +2254,8 @@ function ModelChip({
2088
2254
  setAnchor(null);
2089
2255
  },
2090
2256
  children: [
2091
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "pactor-chat-popover__item-label", children: option.label }),
2092
- option.value === currentOption.value && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_components5.Icon, { name: "check", size: 13, className: "pactor-chat-popover__item-check" })
2257
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "pactor-chat-popover__item-label", children: option.label }),
2258
+ option.value === currentOption.value && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_components6.Icon, { name: "check", size: 13, className: "pactor-chat-popover__item-check" })
2093
2259
  ]
2094
2260
  },
2095
2261
  option.value
@@ -2103,31 +2269,31 @@ function ModelSelect({
2103
2269
  model,
2104
2270
  onModelChange
2105
2271
  }) {
2106
- const changeRef = (0, import_react8.useRef)(onModelChange);
2272
+ const changeRef = (0, import_react10.useRef)(onModelChange);
2107
2273
  changeRef.current = onModelChange;
2108
- (0, import_react8.useEffect)(() => {
2274
+ (0, import_react10.useEffect)(() => {
2109
2275
  setChatChromeHandlers({
2110
2276
  modelChange: (value) => changeRef.current?.(value)
2111
2277
  });
2112
2278
  }, []);
2113
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2279
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2114
2280
  ChromeSlot,
2115
2281
  {
2116
2282
  fragment: buildModelSelectFragment({ models, model }),
2117
- fallback: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ModelChip, { models, model, onModelChange })
2283
+ fallback: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ModelChip, { models, model, onModelChange })
2118
2284
  }
2119
2285
  );
2120
2286
  }
2121
2287
 
2122
2288
  // src/view/chrome/composer.tsx
2123
- var import_components6 = require("@pactor-app/ui/components");
2124
- var import_react9 = require("react");
2125
- var import_jsx_runtime8 = require("react/jsx-runtime");
2126
- var ComposerBridgeContext = (0, import_react9.createContext)(
2289
+ var import_components7 = require("@pactor-app/ui/components");
2290
+ var import_react11 = require("react");
2291
+ var import_jsx_runtime9 = require("react/jsx-runtime");
2292
+ var ComposerBridgeContext = (0, import_react11.createContext)(
2127
2293
  null
2128
2294
  );
2129
2295
  function useComposerBridge() {
2130
- const bridge = (0, import_react9.useContext)(ComposerBridgeContext);
2296
+ const bridge = (0, import_react11.useContext)(ComposerBridgeContext);
2131
2297
  if (!bridge) {
2132
2298
  throw new Error(
2133
2299
  "[@pactor-app/chat] ChatComposer* \u5185\u90E8\u7EC4\u4EF6\u4EC5\u53EF\u5728 Composer chrome \u7247\u6BB5\u5185\u6E32\u67D3"
@@ -2152,21 +2318,21 @@ function ComposerAttachments({
2152
2318
  if (attachments.length === 0) {
2153
2319
  return null;
2154
2320
  }
2155
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "pactor-chat-composer__attachments", children: attachments.map((attachment) => {
2321
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "pactor-chat-composer__attachments", children: attachments.map((attachment) => {
2156
2322
  const isImage = attachment.mimeType.startsWith("image/");
2157
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
2323
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
2158
2324
  "div",
2159
2325
  {
2160
2326
  className: "pactor-chat-composer__attachment",
2161
2327
  "data-attachment-id": attachment.id,
2162
2328
  onClick: () => onClick?.(attachment),
2163
2329
  children: [
2164
- isImage && attachment.url ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "pactor-chat-composer__attachment-thumb", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("img", { src: attachment.url, alt: attachment.name }) }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "pactor-chat-composer__attachment-info", children: [
2165
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_components6.Icon, { name: "file-text", size: 14 }),
2166
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "pactor-chat-composer__attachment-name", children: attachment.name }),
2167
- attachment.size !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "pactor-chat-composer__attachment-size", children: formatSize(attachment.size) })
2330
+ isImage && attachment.url ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "pactor-chat-composer__attachment-thumb", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("img", { src: attachment.url, alt: attachment.name }) }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { className: "pactor-chat-composer__attachment-info", children: [
2331
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_components7.Icon, { name: "file-text", size: 14 }),
2332
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "pactor-chat-composer__attachment-name", children: attachment.name }),
2333
+ attachment.size !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "pactor-chat-composer__attachment-size", children: formatSize(attachment.size) })
2168
2334
  ] }),
2169
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2335
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2170
2336
  "button",
2171
2337
  {
2172
2338
  type: "button",
@@ -2177,7 +2343,7 @@ function ComposerAttachments({
2177
2343
  event.stopPropagation();
2178
2344
  onRemove(attachment.id);
2179
2345
  },
2180
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_components6.Icon, { name: "x", size: 12 })
2346
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_components7.Icon, { name: "x", size: 12 })
2181
2347
  }
2182
2348
  )
2183
2349
  ]
@@ -2193,14 +2359,14 @@ function ComposerContextChips({
2193
2359
  if (chips.length === 0) {
2194
2360
  return null;
2195
2361
  }
2196
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "pactor-chat-composer__contexts", children: chips.map((chip) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
2362
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "pactor-chat-composer__contexts", children: chips.map((chip) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
2197
2363
  "span",
2198
2364
  {
2199
2365
  className: "pactor-chat-context-chip",
2200
2366
  "data-context-id": chip.id,
2201
2367
  children: [
2202
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "pactor-chat-context-chip__label", children: chip.label }),
2203
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2368
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "pactor-chat-context-chip__label", children: chip.label }),
2369
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2204
2370
  "button",
2205
2371
  {
2206
2372
  type: "button",
@@ -2208,7 +2374,7 @@ function ComposerContextChips({
2208
2374
  title: `\u79FB\u9664\u4E0A\u4E0B\u6587 ${chip.label}`,
2209
2375
  "aria-label": `\u79FB\u9664\u4E0A\u4E0B\u6587 ${chip.label}`,
2210
2376
  onClick: () => onRemove(chip),
2211
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_components6.Icon, { name: "x", size: 12 })
2377
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_components7.Icon, { name: "x", size: 12 })
2212
2378
  }
2213
2379
  )
2214
2380
  ]
@@ -2218,8 +2384,8 @@ function ComposerContextChips({
2218
2384
  }
2219
2385
  function ChatComposerHeader() {
2220
2386
  const bridge = useComposerBridge();
2221
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
2222
- bridge.attachments !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2387
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
2388
+ bridge.attachments !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2223
2389
  ComposerAttachments,
2224
2390
  {
2225
2391
  attachments: bridge.attachments,
@@ -2227,7 +2393,7 @@ function ChatComposerHeader() {
2227
2393
  onClick: bridge.attachmentClick
2228
2394
  }
2229
2395
  ),
2230
- bridge.contextChips !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2396
+ bridge.contextChips !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2231
2397
  ComposerContextChips,
2232
2398
  {
2233
2399
  chips: bridge.contextChips,
@@ -2238,9 +2404,9 @@ function ChatComposerHeader() {
2238
2404
  }
2239
2405
  function ChatComposerToolbarStart() {
2240
2406
  const bridge = useComposerBridge();
2241
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
2407
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
2242
2408
  bridge.toolbarStart,
2243
- bridge.showPlus && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2409
+ bridge.showPlus && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2244
2410
  "button",
2245
2411
  {
2246
2412
  type: "button",
@@ -2248,10 +2414,10 @@ function ChatComposerToolbarStart() {
2248
2414
  title: "\u66F4\u591A\u529F\u80FD",
2249
2415
  "aria-label": "\u66F4\u591A\u529F\u80FD",
2250
2416
  onClick: (event) => bridge.plusClick(event.currentTarget.getBoundingClientRect()),
2251
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_components6.Icon, { name: "plus", size: 14 })
2417
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_components7.Icon, { name: "plus", size: 14 })
2252
2418
  }
2253
2419
  ),
2254
- bridge.showAttach && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2420
+ bridge.showAttach && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2255
2421
  "button",
2256
2422
  {
2257
2423
  type: "button",
@@ -2259,15 +2425,15 @@ function ChatComposerToolbarStart() {
2259
2425
  title: "\u6DFB\u52A0\u9644\u4EF6",
2260
2426
  "aria-label": "\u6DFB\u52A0\u9644\u4EF6",
2261
2427
  onClick: bridge.openFilePicker,
2262
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_components6.Icon, { name: "paperclip", size: 14 })
2428
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_components7.Icon, { name: "paperclip", size: 14 })
2263
2429
  }
2264
2430
  )
2265
2431
  ] });
2266
2432
  }
2267
2433
  function ChatComposerToolbarEnd() {
2268
2434
  const bridge = useComposerBridge();
2269
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
2270
- bridge.modelChipEnabled && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2435
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
2436
+ bridge.modelChipEnabled && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2271
2437
  ModelSelect,
2272
2438
  {
2273
2439
  models: bridge.models,
@@ -2276,7 +2442,7 @@ function ChatComposerToolbarEnd() {
2276
2442
  }
2277
2443
  ),
2278
2444
  bridge.toolbarEnd,
2279
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2445
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2280
2446
  "button",
2281
2447
  {
2282
2448
  type: "button",
@@ -2285,14 +2451,14 @@ function ChatComposerToolbarEnd() {
2285
2451
  "aria-label": bridge.streaming ? "\u505C\u6B62\u751F\u6210" : "\u53D1\u9001",
2286
2452
  disabled: bridge.streaming ? false : bridge.disabled || !bridge.text.trim(),
2287
2453
  onClick: bridge.streaming ? bridge.stop : bridge.send,
2288
- children: bridge.streaming ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_components6.Icon, { name: "square", size: 14, className: "pactor-chat-icon-fill" }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_components6.Icon, { name: "arrow-up", size: 16 })
2454
+ children: bridge.streaming ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_components7.Icon, { name: "square", size: 14, className: "pactor-chat-icon-fill" }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_components7.Icon, { name: "arrow-up", size: 16 })
2289
2455
  }
2290
2456
  )
2291
2457
  ] });
2292
2458
  }
2293
2459
  function ChatComposerFooter() {
2294
2460
  const bridge = useComposerBridge();
2295
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_jsx_runtime8.Fragment, { children: bridge.composerFooter });
2461
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_jsx_runtime9.Fragment, { children: bridge.composerFooter });
2296
2462
  }
2297
2463
  var COMPOSER_INTERNAL_COMPONENTS = {
2298
2464
  ChatComposerHeader,
@@ -2333,8 +2499,8 @@ function buildComposerFragment(props) {
2333
2499
  }
2334
2500
 
2335
2501
  // src/view/context-sources.tsx
2336
- var import_react10 = require("react");
2337
- var import_jsx_runtime9 = require("react/jsx-runtime");
2502
+ var import_react12 = require("react");
2503
+ var import_jsx_runtime10 = require("react/jsx-runtime");
2338
2504
  function sourceCacheKey(source) {
2339
2505
  return `${source.service ?? ""}:${JSON.stringify(source.params ?? {})}`;
2340
2506
  }
@@ -2369,8 +2535,8 @@ function ContextSourceList({
2369
2535
  cache,
2370
2536
  onSelect
2371
2537
  }) {
2372
- const [resolutions, setResolutions] = (0, import_react10.useState)([]);
2373
- (0, import_react10.useEffect)(() => {
2538
+ const [resolutions, setResolutions] = (0, import_react12.useState)([]);
2539
+ (0, import_react12.useEffect)(() => {
2374
2540
  let cancelled = false;
2375
2541
  const initial = sources.map(
2376
2542
  (source) => source.items ? { status: "ready", items: source.items } : { status: "loading" }
@@ -2415,12 +2581,12 @@ function ContextSourceList({
2415
2581
  totalMatched += items.length;
2416
2582
  return { source, resolution, items };
2417
2583
  });
2418
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "pactor-chat-source-list", children: [
2419
- groups.map(({ source, resolution, items }) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "pactor-chat-source-list__group", children: [
2420
- sources.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "pactor-chat-source-list__group-label", children: source.label }),
2421
- resolution.status === "loading" && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "pactor-chat-source-list__hint", children: "\u52A0\u8F7D\u4E2D\u2026" }),
2422
- resolution.status === "error" && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "pactor-chat-source-list__error", role: "alert", children: resolution.message }),
2423
- items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2584
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "pactor-chat-source-list", children: [
2585
+ groups.map(({ source, resolution, items }) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "pactor-chat-source-list__group", children: [
2586
+ sources.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "pactor-chat-source-list__group-label", children: source.label }),
2587
+ resolution.status === "loading" && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "pactor-chat-source-list__hint", children: "\u52A0\u8F7D\u4E2D\u2026" }),
2588
+ resolution.status === "error" && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "pactor-chat-source-list__error", role: "alert", children: resolution.message }),
2589
+ items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2424
2590
  "button",
2425
2591
  {
2426
2592
  type: "button",
@@ -2431,12 +2597,12 @@ function ContextSourceList({
2431
2597
  item.id
2432
2598
  ))
2433
2599
  ] }, `${source.trigger}:${source.label}`)),
2434
- totalMatched === 0 && groups.every(({ resolution }) => resolution.status === "ready") && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "pactor-chat-source-list__hint", children: "\u65E0\u5339\u914D\u9879" })
2600
+ totalMatched === 0 && groups.every(({ resolution }) => resolution.status === "ready") && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "pactor-chat-source-list__hint", children: "\u65E0\u5339\u914D\u9879" })
2435
2601
  ] });
2436
2602
  }
2437
2603
 
2438
2604
  // src/view/Composer.tsx
2439
- var import_jsx_runtime10 = require("react/jsx-runtime");
2605
+ var import_jsx_runtime11 = require("react/jsx-runtime");
2440
2606
  var MAX_INPUT_HEIGHT = 200;
2441
2607
  function detectMention(text, caret) {
2442
2608
  const beforeCaret = text.slice(0, caret);
@@ -2470,26 +2636,26 @@ function Composer({
2470
2636
  composerFooter,
2471
2637
  hideToolbar = false
2472
2638
  }) {
2473
- const [text, setText] = (0, import_react11.useState)("");
2474
- const [dragOver, setDragOver] = (0, import_react11.useState)(false);
2475
- const inputRef = (0, import_react11.useRef)(null);
2476
- const fileInputRef = (0, import_react11.useRef)(null);
2477
- const plusButtonRef = (0, import_react11.useRef)(null);
2478
- const composingRef = (0, import_react11.useRef)(false);
2639
+ const [text, setText] = (0, import_react13.useState)("");
2640
+ const [dragOver, setDragOver] = (0, import_react13.useState)(false);
2641
+ const inputRef = (0, import_react13.useRef)(null);
2642
+ const fileInputRef = (0, import_react13.useRef)(null);
2643
+ const plusButtonRef = (0, import_react13.useRef)(null);
2644
+ const composingRef = (0, import_react13.useRef)(false);
2479
2645
  const modelChipEnabled = models !== void 0 && models.length > 0;
2480
- const mentionSources = (0, import_react11.useMemo)(
2646
+ const mentionSources = (0, import_react13.useMemo)(
2481
2647
  () => contextSources?.filter((source) => source.trigger === "@") ?? [],
2482
2648
  [contextSources]
2483
2649
  );
2484
- const plusSources = (0, import_react11.useMemo)(
2650
+ const plusSources = (0, import_react13.useMemo)(
2485
2651
  () => contextSources?.filter((source) => source.trigger === "+") ?? [],
2486
2652
  [contextSources]
2487
2653
  );
2488
2654
  const builtinMentionEnabled = onMentionTrigger === void 0 && mentionSources.length > 0;
2489
2655
  const builtinPlusEnabled = onPlusMenu === void 0 && plusSources.length > 0;
2490
- const [mentionState, setMentionState] = (0, import_react11.useState)(null);
2491
- const [plusAnchor, setPlusAnchor] = (0, import_react11.useState)(null);
2492
- const sourceCacheRef = (0, import_react11.useRef)(null);
2656
+ const [mentionState, setMentionState] = (0, import_react13.useState)(null);
2657
+ const [plusAnchor, setPlusAnchor] = (0, import_react13.useState)(null);
2658
+ const sourceCacheRef = (0, import_react13.useRef)(null);
2493
2659
  if (sourceCacheRef.current === null) {
2494
2660
  sourceCacheRef.current = /* @__PURE__ */ new Map();
2495
2661
  }
@@ -2508,7 +2674,7 @@ function Composer({
2508
2674
  setMentionState(null);
2509
2675
  setPlusAnchor(null);
2510
2676
  };
2511
- (0, import_react11.useLayoutEffect)(() => {
2677
+ (0, import_react13.useLayoutEffect)(() => {
2512
2678
  const input = inputRef.current;
2513
2679
  if (input) {
2514
2680
  input.style.height = "auto";
@@ -2523,9 +2689,9 @@ function Composer({
2523
2689
  onSend?.(value);
2524
2690
  setText("");
2525
2691
  };
2526
- const sendRef = (0, import_react11.useRef)(send);
2692
+ const sendRef = (0, import_react13.useRef)(send);
2527
2693
  sendRef.current = send;
2528
- (0, import_react11.useLayoutEffect)(() => {
2694
+ (0, import_react13.useLayoutEffect)(() => {
2529
2695
  setChatChromeHandlers({ composerSubmit: () => sendRef.current() });
2530
2696
  }, []);
2531
2697
  const syncText = (value, caret, rect) => {
@@ -2583,7 +2749,7 @@ function Composer({
2583
2749
  }
2584
2750
  };
2585
2751
  const showToolbar = !hideToolbar && (toolbarStart !== void 0 || toolbarEnd !== void 0 || onPlusMenu !== void 0 || builtinPlusEnabled || onAttachFiles !== void 0 || modelChipEnabled);
2586
- const fileInputNode = onAttachFiles ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2752
+ const fileInputNode = onAttachFiles ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2587
2753
  "input",
2588
2754
  {
2589
2755
  ref: fileInputRef,
@@ -2599,14 +2765,14 @@ function Composer({
2599
2765
  }
2600
2766
  }
2601
2767
  ) : null;
2602
- const popoverNodes = /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
2603
- builtinMentionEnabled && mentionState && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2768
+ const popoverNodes = /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
2769
+ builtinMentionEnabled && mentionState && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2604
2770
  AnchoredPopover,
2605
2771
  {
2606
2772
  anchorRect: mentionState.anchorRect,
2607
2773
  onClose: () => setMentionState(null),
2608
2774
  role: "listbox",
2609
- children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2775
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2610
2776
  ContextSourceList,
2611
2777
  {
2612
2778
  sources: mentionSources,
@@ -2618,13 +2784,13 @@ function Composer({
2618
2784
  )
2619
2785
  }
2620
2786
  ),
2621
- builtinPlusEnabled && plusAnchor && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2787
+ builtinPlusEnabled && plusAnchor && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2622
2788
  AnchoredPopover,
2623
2789
  {
2624
2790
  anchorRect: plusAnchor,
2625
2791
  onClose: () => setPlusAnchor(null),
2626
2792
  role: "listbox",
2627
- children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2793
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2628
2794
  ContextSourceList,
2629
2795
  {
2630
2796
  sources: plusSources,
@@ -2637,13 +2803,13 @@ function Composer({
2637
2803
  }
2638
2804
  )
2639
2805
  ] });
2640
- const fallback = /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2806
+ const fallback = /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
2641
2807
  "div",
2642
2808
  {
2643
2809
  className: `pactor-chat-composer${dragOver ? " pactor-chat-composer--dragover" : ""}`,
2644
2810
  ...dragHandlers,
2645
2811
  children: [
2646
- attachments !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2812
+ attachments !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2647
2813
  ComposerAttachments,
2648
2814
  {
2649
2815
  attachments,
@@ -2651,7 +2817,7 @@ function Composer({
2651
2817
  onClick: onAttachmentClick
2652
2818
  }
2653
2819
  ),
2654
- contextChips !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2820
+ contextChips !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2655
2821
  ComposerContextChips,
2656
2822
  {
2657
2823
  chips: contextChips,
@@ -2662,8 +2828,8 @@ function Composer({
2662
2828
  )
2663
2829
  }
2664
2830
  ),
2665
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "pactor-chat-composer__row", children: [
2666
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2831
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "pactor-chat-composer__row", children: [
2832
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2667
2833
  "textarea",
2668
2834
  {
2669
2835
  ref: inputRef,
@@ -2695,7 +2861,7 @@ function Composer({
2695
2861
  }
2696
2862
  }
2697
2863
  ),
2698
- hideToolbar ? null : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2864
+ hideToolbar ? null : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2699
2865
  "button",
2700
2866
  {
2701
2867
  type: "button",
@@ -2704,14 +2870,14 @@ function Composer({
2704
2870
  "aria-label": streaming ? "\u505C\u6B62\u751F\u6210" : "\u53D1\u9001",
2705
2871
  disabled: streaming ? false : disabled || !text.trim(),
2706
2872
  onClick: streaming ? onStop : send,
2707
- children: streaming ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_components7.Icon, { name: "square", size: 14, className: "pactor-chat-icon-fill" }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_components7.Icon, { name: "arrow-up", size: 16 })
2873
+ children: streaming ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_components8.Icon, { name: "square", size: 14, className: "pactor-chat-icon-fill" }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_components8.Icon, { name: "arrow-up", size: 16 })
2708
2874
  }
2709
2875
  )
2710
2876
  ] }),
2711
- showToolbar && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "pactor-chat-composer__toolbar", children: [
2877
+ showToolbar && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "pactor-chat-composer__toolbar", children: [
2712
2878
  toolbarStart,
2713
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "pactor-chat-composer__toolbar-spacer" }),
2714
- (onPlusMenu || builtinPlusEnabled) && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2879
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "pactor-chat-composer__toolbar-spacer" }),
2880
+ (onPlusMenu || builtinPlusEnabled) && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2715
2881
  "button",
2716
2882
  {
2717
2883
  ref: plusButtonRef,
@@ -2727,10 +2893,10 @@ function Composer({
2727
2893
  setPlusAnchor(rect);
2728
2894
  }
2729
2895
  },
2730
- children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_components7.Icon, { name: "plus", size: 14 })
2896
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_components8.Icon, { name: "plus", size: 14 })
2731
2897
  }
2732
2898
  ),
2733
- onAttachFiles && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2899
+ onAttachFiles && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2734
2900
  "button",
2735
2901
  {
2736
2902
  type: "button",
@@ -2738,10 +2904,10 @@ function Composer({
2738
2904
  title: "\u6DFB\u52A0\u9644\u4EF6",
2739
2905
  "aria-label": "\u6DFB\u52A0\u9644\u4EF6",
2740
2906
  onClick: () => fileInputRef.current?.click(),
2741
- children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_components7.Icon, { name: "paperclip", size: 14 })
2907
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_components8.Icon, { name: "paperclip", size: 14 })
2742
2908
  }
2743
2909
  ),
2744
- modelChipEnabled && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2910
+ modelChipEnabled && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2745
2911
  ModelSelect,
2746
2912
  {
2747
2913
  models,
@@ -2751,7 +2917,7 @@ function Composer({
2751
2917
  ),
2752
2918
  toolbarEnd
2753
2919
  ] }),
2754
- composerFooter !== void 0 && composerFooter !== null ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "pactor-chat-composer__footer", children: composerFooter }) : null,
2920
+ composerFooter !== void 0 && composerFooter !== null ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "pactor-chat-composer__footer", children: composerFooter }) : null,
2755
2921
  fileInputNode,
2756
2922
  popoverNodes
2757
2923
  ]
@@ -2790,7 +2956,7 @@ function Composer({
2790
2956
  ),
2791
2957
  modelChange: onModelChange
2792
2958
  };
2793
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2959
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2794
2960
  ChromeSlot,
2795
2961
  {
2796
2962
  fragment: buildComposerFragment({
@@ -2801,7 +2967,7 @@ function Composer({
2801
2967
  }),
2802
2968
  components: COMPOSER_INTERNAL_COMPONENTS,
2803
2969
  fallback,
2804
- wrap: (children) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ComposerBridgeContext.Provider, { value: bridge, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2970
+ wrap: (children) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ComposerBridgeContext.Provider, { value: bridge, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
2805
2971
  "div",
2806
2972
  {
2807
2973
  className: `pactor-chat-composer pactor-chat-composer--dsl${dragOver ? " pactor-chat-composer--dragover" : ""}`,
@@ -2889,7 +3055,7 @@ function buildEmptyStateFragment(props) {
2889
3055
  }
2890
3056
 
2891
3057
  // src/view/EmptyState.tsx
2892
- var import_jsx_runtime11 = require("react/jsx-runtime");
3058
+ var import_jsx_runtime12 = require("react/jsx-runtime");
2893
3059
  var DEFAULT_CHAT_GREETING = "\u4F60\u597D\uFF0C\u6709\u4EC0\u4E48\u53EF\u4EE5\u5E2E\u4F60\uFF1F";
2894
3060
  function suggestionLabel2(suggestion) {
2895
3061
  return typeof suggestion === "string" ? suggestion : suggestion.label;
@@ -2903,10 +3069,10 @@ function EmptyStateFallback({
2903
3069
  onSuggestionClick,
2904
3070
  greeting
2905
3071
  }) {
2906
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
2907
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "pactor-chat-empty__greeting", children: greeting }),
2908
- subtitle && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "pactor-chat-empty__subtitle", children: subtitle }),
2909
- suggestions && suggestions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "pactor-chat-empty__suggestions", children: suggestions.map((suggestion) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3072
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
3073
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "pactor-chat-empty__greeting", children: greeting }),
3074
+ subtitle && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "pactor-chat-empty__subtitle", children: subtitle }),
3075
+ suggestions && suggestions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "pactor-chat-empty__suggestions", children: suggestions.map((suggestion) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2910
3076
  "button",
2911
3077
  {
2912
3078
  type: "button",
@@ -2924,11 +3090,11 @@ function EmptyState({
2924
3090
  suggestions,
2925
3091
  onSuggestionClick
2926
3092
  }) {
2927
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "pactor-chat-empty", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3093
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "pactor-chat-empty", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2928
3094
  ChromeSlot,
2929
3095
  {
2930
3096
  fragment: buildEmptyStateFragment({ greeting, subtitle, suggestions }),
2931
- fallback: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3097
+ fallback: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2932
3098
  EmptyStateFallback,
2933
3099
  {
2934
3100
  greeting,
@@ -2942,16 +3108,16 @@ function EmptyState({
2942
3108
  }
2943
3109
 
2944
3110
  // src/view/MessageBubble.tsx
2945
- var import_react14 = require("react");
3111
+ var import_react16 = require("react");
2946
3112
 
2947
3113
  // src/view/ActivityTrace.tsx
2948
- var import_components8 = require("@pactor-app/ui/components");
3114
+ var import_components9 = require("@pactor-app/ui/components");
2949
3115
  var import_markdown3 = require("@pactor-app/markdown");
2950
- var import_react12 = require("react");
2951
- var import_jsx_runtime12 = require("react/jsx-runtime");
3116
+ var import_react14 = require("react");
3117
+ var import_jsx_runtime13 = require("react/jsx-runtime");
2952
3118
  function usePinnedCollapse(autoOpen) {
2953
- const [state, setState] = (0, import_react12.useState)("auto");
2954
- const autoCollapsedRef = (0, import_react12.useRef)(false);
3119
+ const [state, setState] = (0, import_react14.useState)("auto");
3120
+ const autoCollapsedRef = (0, import_react14.useRef)(false);
2955
3121
  if (state === "auto" && !autoOpen) {
2956
3122
  autoCollapsedRef.current = true;
2957
3123
  }
@@ -2980,8 +3146,8 @@ function statusText(message, mode, toolCount) {
2980
3146
  }
2981
3147
  function useElapsedSeconds(startedAt, active) {
2982
3148
  const compute = () => Math.max(0, Math.floor((Date.now() - startedAt) / 1e3));
2983
- const [elapsed, setElapsed] = (0, import_react12.useState)(compute);
2984
- (0, import_react12.useEffect)(() => {
3149
+ const [elapsed, setElapsed] = (0, import_react14.useState)(compute);
3150
+ (0, import_react14.useEffect)(() => {
2985
3151
  if (!active) {
2986
3152
  setElapsed(compute());
2987
3153
  return;
@@ -2995,15 +3161,15 @@ function useElapsedSeconds(startedAt, active) {
2995
3161
  }
2996
3162
  function TraceStatusIcon({ status }) {
2997
3163
  if (status === "running") {
2998
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_components8.Icon, { name: "loading", size: 13, className: "pactor-chat-spin" });
3164
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_components9.Icon, { name: "loading", size: 13, className: "pactor-chat-spin" });
2999
3165
  }
3000
3166
  if (status === "success") {
3001
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_components8.Icon, { name: "check-circle", size: 13 });
3167
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_components9.Icon, { name: "check-circle", size: 13 });
3002
3168
  }
3003
3169
  if (status === "failed") {
3004
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_components8.Icon, { name: "x-circle", size: 13 });
3170
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_components9.Icon, { name: "x-circle", size: 13 });
3005
3171
  }
3006
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_components8.Icon, { name: "clock", size: 13 });
3172
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_components9.Icon, { name: "clock", size: 13 });
3007
3173
  }
3008
3174
  function summarizeArgs(args) {
3009
3175
  if (args === void 0) {
@@ -3032,16 +3198,16 @@ function formatDetail(value) {
3032
3198
  }
3033
3199
  }
3034
3200
  function TraceRow({ entry }) {
3035
- const [open, setOpen] = (0, import_react12.useState)(false);
3201
+ const [open, setOpen] = (0, import_react14.useState)(false);
3036
3202
  const summary = summarizeArgs(entry.args);
3037
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
3203
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
3038
3204
  "div",
3039
3205
  {
3040
3206
  className: "pactor-chat-trace__entry",
3041
3207
  "data-status": entry.status,
3042
3208
  "data-open": open,
3043
3209
  children: [
3044
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
3210
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
3045
3211
  "button",
3046
3212
  {
3047
3213
  type: "button",
@@ -3049,16 +3215,16 @@ function TraceRow({ entry }) {
3049
3215
  "aria-expanded": open,
3050
3216
  onClick: () => setOpen((value) => !value),
3051
3217
  children: [
3052
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "pactor-chat-trace__chevron", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_components8.Icon, { name: "chevron-right", size: 12 }) }),
3053
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "pactor-chat-trace__entry-icon", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TraceStatusIcon, { status: entry.status }) }),
3054
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "pactor-chat-trace__entry-title", children: entry.title ?? entry.name }),
3055
- summary && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "pactor-chat-trace__entry-args", children: summary })
3218
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "pactor-chat-trace__chevron", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_components9.Icon, { name: "chevron-right", size: 12 }) }),
3219
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "pactor-chat-trace__entry-icon", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(TraceStatusIcon, { status: entry.status }) }),
3220
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "pactor-chat-trace__entry-title", children: entry.title ?? entry.name }),
3221
+ summary && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "pactor-chat-trace__entry-args", children: summary })
3056
3222
  ]
3057
3223
  }
3058
3224
  ),
3059
- open && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "pactor-chat-trace__entry-body", children: [
3060
- entry.args !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("pre", { className: "pactor-chat-trace__entry-detail", children: formatDetail(entry.args) }),
3061
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("pre", { className: "pactor-chat-trace__entry-detail", children: entry.status === "failed" ? entry.error ?? "\u6267\u884C\u5931\u8D25" : formatDetail(entry.result) })
3225
+ open && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "pactor-chat-trace__entry-body", children: [
3226
+ entry.args !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("pre", { className: "pactor-chat-trace__entry-detail", children: formatDetail(entry.args) }),
3227
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("pre", { className: "pactor-chat-trace__entry-detail", children: entry.status === "failed" ? entry.error ?? "\u6267\u884C\u5931\u8D25" : formatDetail(entry.result) })
3062
3228
  ] })
3063
3229
  ]
3064
3230
  }
@@ -3071,14 +3237,14 @@ function ThinkingCard({
3071
3237
  const partStreaming = part.status === "streaming";
3072
3238
  const shown = useThrottledValue(part.content, 120, partStreaming);
3073
3239
  const { open, toggle } = usePinnedCollapse(partStreaming && !answerPhase);
3074
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
3240
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
3075
3241
  "div",
3076
3242
  {
3077
3243
  className: "pactor-chat-thinking",
3078
3244
  "data-open": open,
3079
3245
  "data-streaming": partStreaming,
3080
3246
  children: [
3081
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
3247
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
3082
3248
  "button",
3083
3249
  {
3084
3250
  type: "button",
@@ -3086,13 +3252,13 @@ function ThinkingCard({
3086
3252
  "aria-expanded": open,
3087
3253
  onClick: toggle,
3088
3254
  children: [
3089
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "pactor-chat-trace__chevron", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_components8.Icon, { name: "chevron-right", size: 12 }) }),
3090
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "pactor-chat-thinking__icon", children: partStreaming ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_components8.Icon, { name: "loading", size: 13, className: "pactor-chat-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_components8.Icon, { name: "brain", size: 13 }) }),
3091
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: "\u601D\u8003\u8FC7\u7A0B" })
3255
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "pactor-chat-trace__chevron", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_components9.Icon, { name: "chevron-right", size: 12 }) }),
3256
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "pactor-chat-thinking__icon", children: partStreaming ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_components9.Icon, { name: "loading", size: 13, className: "pactor-chat-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_components9.Icon, { name: "brain", size: 13 }) }),
3257
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: "\u601D\u8003\u8FC7\u7A0B" })
3092
3258
  ]
3093
3259
  }
3094
3260
  ),
3095
- open && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "pactor-chat-thinking__body", children: partStreaming ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "pactor-chat-thinking__text", children: shown }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_markdown3.MarkdownRenderer, { content: part.content }) })
3261
+ open && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "pactor-chat-thinking__body", children: partStreaming ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "pactor-chat-thinking__text", children: shown }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_markdown3.MarkdownRenderer, { content: part.content }) })
3096
3262
  ]
3097
3263
  }
3098
3264
  );
@@ -3107,7 +3273,7 @@ function ActivityTrace({ message }) {
3107
3273
  const answerPhase = mode === "responding" || !streaming;
3108
3274
  const { open, toggle } = usePinnedCollapse(!answerPhase);
3109
3275
  const collapsible = entries.length > 0 || thinkingParts.length > 0;
3110
- const mountTimeRef = (0, import_react12.useRef)(0);
3276
+ const mountTimeRef = (0, import_react14.useRef)(0);
3111
3277
  if (mountTimeRef.current === 0) {
3112
3278
  mountTimeRef.current = Date.now();
3113
3279
  }
@@ -3115,23 +3281,23 @@ function ActivityTrace({ message }) {
3115
3281
  message.createdAt ?? mountTimeRef.current,
3116
3282
  streaming
3117
3283
  );
3118
- const header = /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
3119
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "pactor-chat-trace__status-icon", children: streaming ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_components8.Icon, { name: "loading", size: 13, className: "pactor-chat-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_components8.Icon, { name: "check-circle", size: 13 }) }),
3120
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3284
+ const header = /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
3285
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "pactor-chat-trace__status-icon", children: streaming ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_components9.Icon, { name: "loading", size: 13, className: "pactor-chat-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_components9.Icon, { name: "check-circle", size: 13 }) }),
3286
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3121
3287
  "span",
3122
3288
  {
3123
3289
  className: `pactor-chat-trace__status-text${streaming ? " pactor-chat-trace__status-text--breathing" : ""}`,
3124
3290
  children: statusText(message, mode, entries.length)
3125
3291
  }
3126
3292
  ),
3127
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "pactor-chat-trace__elapsed", children: [
3293
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { className: "pactor-chat-trace__elapsed", children: [
3128
3294
  elapsed,
3129
3295
  "s"
3130
3296
  ] }),
3131
- collapsible && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "pactor-chat-trace__chevron", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_components8.Icon, { name: "chevron-right", size: 12 }) })
3297
+ collapsible && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "pactor-chat-trace__chevron", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_components9.Icon, { name: "chevron-right", size: 12 }) })
3132
3298
  ] });
3133
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "pactor-chat-trace", "data-open": open, children: [
3134
- collapsible ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3299
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "pactor-chat-trace", "data-open": open, children: [
3300
+ collapsible ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3135
3301
  "button",
3136
3302
  {
3137
3303
  type: "button",
@@ -3140,10 +3306,10 @@ function ActivityTrace({ message }) {
3140
3306
  onClick: toggle,
3141
3307
  children: header
3142
3308
  }
3143
- ) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "pactor-chat-trace__header", children: header }),
3144
- open && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
3145
- entries.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "pactor-chat-trace__entries", children: entries.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TraceRow, { entry }, entry.callIndex)) }),
3146
- thinkingParts.map((part, index) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3309
+ ) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "pactor-chat-trace__header", children: header }),
3310
+ open && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
3311
+ entries.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "pactor-chat-trace__entries", children: entries.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(TraceRow, { entry }, entry.callIndex)) }),
3312
+ thinkingParts.map((part, index) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3147
3313
  ThinkingCard,
3148
3314
  {
3149
3315
  part,
@@ -3156,8 +3322,8 @@ function ActivityTrace({ message }) {
3156
3322
  }
3157
3323
 
3158
3324
  // src/view/MessageActions.tsx
3159
- var import_components9 = require("@pactor-app/ui/components");
3160
- var import_react13 = require("react");
3325
+ var import_components10 = require("@pactor-app/ui/components");
3326
+ var import_react15 = require("react");
3161
3327
 
3162
3328
  // src/view/chrome/message-actions.tsx
3163
3329
  function buildMessageActionsFragment(args) {
@@ -3210,7 +3376,7 @@ function buildMessageActionsFragment(args) {
3210
3376
  }
3211
3377
 
3212
3378
  // src/view/MessageActions.tsx
3213
- var import_jsx_runtime13 = require("react/jsx-runtime");
3379
+ var import_jsx_runtime14 = require("react/jsx-runtime");
3214
3380
  var BUILTIN_ACTION_DEFAULTS = {
3215
3381
  copy: {
3216
3382
  label: "\u590D\u5236",
@@ -3283,13 +3449,13 @@ function MessageActions({
3283
3449
  callService,
3284
3450
  onMessageAction
3285
3451
  }) {
3286
- const [copied, setCopied] = (0, import_react13.useState)(false);
3287
- const dispatchRef = (0, import_react13.useRef)(
3452
+ const [copied, setCopied] = (0, import_react15.useState)(false);
3453
+ const dispatchRef = (0, import_react15.useRef)(
3288
3454
  () => {
3289
3455
  }
3290
3456
  );
3291
- const visibleActionsRef = (0, import_react13.useRef)([]);
3292
- (0, import_react13.useEffect)(() => {
3457
+ const visibleActionsRef = (0, import_react15.useRef)([]);
3458
+ (0, import_react15.useEffect)(() => {
3293
3459
  setMessageActionDispatcher(message.id, (actionId) => {
3294
3460
  const action = visibleActionsRef.current.find((a) => a.id === actionId);
3295
3461
  if (action) {
@@ -3363,7 +3529,7 @@ function MessageActions({
3363
3529
  const copiedFeedback = action.builtin === "copy" && copied;
3364
3530
  const label = copiedFeedback ? "\u5DF2\u590D\u5236" : action.label;
3365
3531
  const iconName = copiedFeedback ? "check" : action.icon;
3366
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3532
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3367
3533
  "button",
3368
3534
  {
3369
3535
  type: "button",
@@ -3372,16 +3538,16 @@ function MessageActions({
3372
3538
  "aria-label": label,
3373
3539
  "data-message-action": action.id,
3374
3540
  onClick: () => dispatch(action),
3375
- children: iconName !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_components9.Icon, { name: iconName, size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_components9.Icon, { name: "help-circle", size: 14 })
3541
+ children: iconName !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_components10.Icon, { name: iconName, size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_components10.Icon, { name: "help-circle", size: 14 })
3376
3542
  },
3377
3543
  action.id
3378
3544
  );
3379
3545
  });
3380
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3546
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3381
3547
  "div",
3382
3548
  {
3383
3549
  className: `pactor-chat-message__actions${forceVisible ? " pactor-chat-message__actions--visible" : ""}`,
3384
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3550
+ children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3385
3551
  ChromeSlot,
3386
3552
  {
3387
3553
  fragment: buildMessageActionsFragment({
@@ -3397,13 +3563,38 @@ function MessageActions({
3397
3563
  }
3398
3564
 
3399
3565
  // src/view/MessageBubble.tsx
3400
- var import_jsx_runtime14 = require("react/jsx-runtime");
3566
+ var import_jsx_runtime15 = require("react/jsx-runtime");
3567
+ function groupArtifactParts(parts) {
3568
+ const segments = [];
3569
+ for (const part of parts) {
3570
+ if (part.type === "artifact" && part.artifact) {
3571
+ const last = segments[segments.length - 1];
3572
+ if (Array.isArray(last)) {
3573
+ last.push(part.artifact);
3574
+ } else {
3575
+ segments.push([part.artifact]);
3576
+ }
3577
+ } else {
3578
+ segments.push(part);
3579
+ }
3580
+ }
3581
+ return segments;
3582
+ }
3583
+ function formatMessageTime(ts, now = Date.now()) {
3584
+ const date = new Date(ts);
3585
+ const hh = String(date.getHours()).padStart(2, "0");
3586
+ const mm = String(date.getMinutes()).padStart(2, "0");
3587
+ if (new Date(now).toDateString() === date.toDateString()) {
3588
+ return `${hh}:${mm}`;
3589
+ }
3590
+ return `${date.getMonth() + 1}\u6708${date.getDate()}\u65E5 ${hh}:${mm}`;
3591
+ }
3401
3592
  function MessageEditForm({
3402
3593
  initialText,
3403
3594
  onConfirm,
3404
3595
  onCancel
3405
3596
  }) {
3406
- const [text, setText] = (0, import_react14.useState)(initialText);
3597
+ const [text, setText] = (0, import_react16.useState)(initialText);
3407
3598
  const confirm = () => {
3408
3599
  const value = text.trim();
3409
3600
  if (!value) {
@@ -3411,8 +3602,8 @@ function MessageEditForm({
3411
3602
  }
3412
3603
  onConfirm(value);
3413
3604
  };
3414
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "pactor-chat-message__edit", children: [
3415
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3605
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "pactor-chat-message__edit", children: [
3606
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3416
3607
  "textarea",
3417
3608
  {
3418
3609
  className: "pactor-chat-message__edit-input",
@@ -3430,8 +3621,8 @@ function MessageEditForm({
3430
3621
  }
3431
3622
  }
3432
3623
  ),
3433
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "pactor-chat-message__edit-actions", children: [
3434
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3624
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "pactor-chat-message__edit-actions", children: [
3625
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3435
3626
  "button",
3436
3627
  {
3437
3628
  type: "button",
@@ -3441,7 +3632,7 @@ function MessageEditForm({
3441
3632
  children: "\u53D1\u9001"
3442
3633
  }
3443
3634
  ),
3444
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3635
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3445
3636
  "button",
3446
3637
  {
3447
3638
  type: "button",
@@ -3464,10 +3655,9 @@ function MessageBubble({
3464
3655
  onEditResend,
3465
3656
  messageActions,
3466
3657
  callService,
3467
- onMessageAction,
3468
- onOpenArtifact
3658
+ onMessageAction
3469
3659
  }) {
3470
- const [editing, setEditing] = (0, import_react14.useState)(false);
3660
+ const [editing, setEditing] = (0, import_react16.useState)(false);
3471
3661
  const bubbleScope = {
3472
3662
  conversation: scope?.conversation ?? {},
3473
3663
  message: { id: message.id },
@@ -3475,21 +3665,22 @@ function MessageBubble({
3475
3665
  };
3476
3666
  const streaming = message.status === "streaming";
3477
3667
  const live = message.status === "pending" || message.status === "streaming";
3478
- const wasLiveRef = (0, import_react14.useRef)(live);
3668
+ const wasLiveRef = (0, import_react16.useRef)(live);
3479
3669
  if (live) {
3480
3670
  wasLiveRef.current = true;
3481
3671
  }
3482
3672
  const showTrace = message.role === "assistant" && (wasLiveRef.current || message.parts.some(
3483
3673
  (part) => part.type === "thinking" || part.type === "tool-call" || part.type === "tool-result"
3484
3674
  ));
3485
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
3675
+ const showTime = message.role === "assistant" && !live && message.createdAt !== void 0;
3676
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
3486
3677
  "div",
3487
3678
  {
3488
3679
  className: `pactor-chat-message pactor-chat-message--${message.role}`,
3489
3680
  "data-message-id": message.id,
3490
3681
  "data-message-status": message.status,
3491
3682
  children: [
3492
- editing ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3683
+ editing ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3493
3684
  MessageEditForm,
3494
3685
  {
3495
3686
  initialText: collectMessageText(message),
@@ -3499,21 +3690,53 @@ function MessageBubble({
3499
3690
  },
3500
3691
  onCancel: () => setEditing(false)
3501
3692
  }
3502
- ) : /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "pactor-chat-message__body", children: [
3503
- showTrace && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ActivityTrace, { message }),
3504
- message.parts.length === 0 && message.status === "pending" && message.role !== "assistant" ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "pactor-chat-message__pending", children: "\u2026" }) : message.parts.map((part, index) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3505
- PartRenderer,
3506
- {
3507
- part,
3508
- runtime,
3509
- scope: bubbleScope,
3510
- streaming,
3511
- onOpenArtifact
3512
- },
3513
- part.id ?? index
3514
- ))
3693
+ ) : /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "pactor-chat-message__body", children: [
3694
+ showTrace && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ActivityTrace, { message }),
3695
+ message.parts.length === 0 && message.status === "pending" && message.role !== "assistant" ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "pactor-chat-message__pending", children: "\u2026" }) : groupArtifactParts(message.parts).map(
3696
+ (segment, index) => Array.isArray(segment) ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3697
+ ChromeSlot,
3698
+ {
3699
+ fragment: buildArtifactCardGroupFragment(segment),
3700
+ components: ARTIFACT_CARD_INTERNAL_COMPONENTS,
3701
+ fallback: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ChatArtifactCardGroup, { artifacts: segment })
3702
+ },
3703
+ `artifacts:${segment[0].id}`
3704
+ ) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3705
+ PartRenderer,
3706
+ {
3707
+ part: segment,
3708
+ runtime,
3709
+ scope: bubbleScope,
3710
+ streaming
3711
+ },
3712
+ segment.id ?? index
3713
+ )
3714
+ )
3515
3715
  ] }),
3516
- !editing && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3716
+ !editing && (showTime ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "pactor-chat-message__footer", children: [
3717
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3718
+ MessageActions,
3719
+ {
3720
+ message,
3721
+ actions: messageActions,
3722
+ showRegenerate,
3723
+ onRegenerate,
3724
+ onRetry,
3725
+ onEdit: onEditResend ? () => setEditing(true) : void 0,
3726
+ forceVisible: message.status === "error",
3727
+ callService,
3728
+ onMessageAction
3729
+ }
3730
+ ),
3731
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3732
+ "span",
3733
+ {
3734
+ className: "pactor-chat-message__time",
3735
+ title: new Date(message.createdAt).toLocaleString(),
3736
+ children: formatMessageTime(message.createdAt)
3737
+ }
3738
+ )
3739
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3517
3740
  MessageActions,
3518
3741
  {
3519
3742
  message,
@@ -3526,14 +3749,14 @@ function MessageBubble({
3526
3749
  callService,
3527
3750
  onMessageAction
3528
3751
  }
3529
- )
3752
+ ))
3530
3753
  ]
3531
3754
  }
3532
3755
  );
3533
3756
  }
3534
3757
 
3535
3758
  // src/view/ChatView.tsx
3536
- var import_jsx_runtime15 = require("react/jsx-runtime");
3759
+ var import_jsx_runtime16 = require("react/jsx-runtime");
3537
3760
  function lastContentLength(messages) {
3538
3761
  const last = messages[messages.length - 1];
3539
3762
  if (!last) {
@@ -3561,6 +3784,7 @@ function ChatView({
3561
3784
  className,
3562
3785
  onArtifact,
3563
3786
  onOpenArtifact,
3787
+ onOpenArtifactList,
3564
3788
  attachments,
3565
3789
  onAttachmentsChange,
3566
3790
  onAttachFiles,
@@ -3582,14 +3806,14 @@ function ChatView({
3582
3806
  onMessageAction,
3583
3807
  composerBottom
3584
3808
  }) {
3585
- const messages = (0, import_react15.useSyncExternalStore)(
3809
+ const messages = (0, import_react17.useSyncExternalStore)(
3586
3810
  (listener) => store.subscribe(listener),
3587
3811
  () => store.getMessages()
3588
3812
  );
3589
3813
  const isStreaming = messages.some(
3590
3814
  (message) => message.status === "pending" || message.status === "streaming"
3591
3815
  );
3592
- const runtime = (0, import_react15.useMemo)(() => {
3816
+ const runtime = (0, import_react17.useMemo)(() => {
3593
3817
  if (!safeRegistry) {
3594
3818
  return void 0;
3595
3819
  }
@@ -3606,12 +3830,12 @@ function ChatView({
3606
3830
  user
3607
3831
  });
3608
3832
  }, [safeRegistry, capabilities, permission, confirm, user]);
3609
- const scope = (0, import_react15.useMemo)(
3833
+ const scope = (0, import_react17.useMemo)(
3610
3834
  () => ({ conversation: { id: conversationId }, params }),
3611
3835
  [conversationId, params]
3612
3836
  );
3613
- const notifiedArtifactsRef = (0, import_react15.useRef)(/* @__PURE__ */ new Set());
3614
- (0, import_react15.useEffect)(() => {
3837
+ const notifiedArtifactsRef = (0, import_react17.useRef)(/* @__PURE__ */ new Set());
3838
+ (0, import_react17.useEffect)(() => {
3615
3839
  if (!onArtifact) {
3616
3840
  return;
3617
3841
  }
@@ -3630,7 +3854,7 @@ function ChatView({
3630
3854
  });
3631
3855
  }
3632
3856
  }, [messages, onArtifact]);
3633
- const abortRef = (0, import_react15.useRef)(null);
3857
+ const abortRef = (0, import_react17.useRef)(null);
3634
3858
  const { containerRef, isFollowing, scrollToBottom } = useChatAutoScroll({
3635
3859
  messageCount: messages.length,
3636
3860
  lastContentLength: lastContentLength(messages),
@@ -3641,7 +3865,7 @@ function ChatView({
3641
3865
  model,
3642
3866
  onModelChange
3643
3867
  });
3644
- const [contextChips, setContextChips] = (0, import_react15.useState)([]);
3868
+ const [contextChips, setContextChips] = (0, import_react17.useState)([]);
3645
3869
  const handleContextChipsChange = (chips) => {
3646
3870
  setContextChips(chips);
3647
3871
  onContextsChange?.(chips);
@@ -3673,14 +3897,17 @@ function ChatView({
3673
3897
  abortRef.current?.abort();
3674
3898
  abortRef.current = null;
3675
3899
  };
3676
- const handleSendRef = (0, import_react15.useRef)(handleSend);
3900
+ const handleSendRef = (0, import_react17.useRef)(handleSend);
3677
3901
  handleSendRef.current = handleSend;
3678
- const onOpenArtifactRef = (0, import_react15.useRef)(onOpenArtifact);
3902
+ const onOpenArtifactRef = (0, import_react17.useRef)(onOpenArtifact);
3679
3903
  onOpenArtifactRef.current = onOpenArtifact;
3680
- (0, import_react15.useEffect)(() => {
3904
+ const onOpenArtifactListRef = (0, import_react17.useRef)(onOpenArtifactList);
3905
+ onOpenArtifactListRef.current = onOpenArtifactList;
3906
+ (0, import_react17.useEffect)(() => {
3681
3907
  setChatChromeHandlers({
3682
3908
  sendSuggestion: (text) => handleSendRef.current(text),
3683
- openArtifact: (artifact) => onOpenArtifactRef.current?.(artifact)
3909
+ openArtifact: (artifact) => onOpenArtifactRef.current?.(artifact),
3910
+ openArtifactList: () => onOpenArtifactListRef.current?.()
3684
3911
  });
3685
3912
  }, []);
3686
3913
  const handleRegenerate = () => {
@@ -3700,7 +3927,7 @@ function ChatView({
3700
3927
  const lastMessage = messages[messages.length - 1];
3701
3928
  const regenerableMessageId = lastMessage?.role === "assistant" && lastMessage.status === "completed" ? lastMessage.id : void 0;
3702
3929
  const isEmpty = messages.length === 0;
3703
- const composerNode = /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3930
+ const composerNode = /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3704
3931
  Composer,
3705
3932
  {
3706
3933
  onSend: handleSend,
@@ -3725,18 +3952,18 @@ function ChatView({
3725
3952
  callService
3726
3953
  }
3727
3954
  );
3728
- const composerDock = /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "pactor-chat-view__composer-dock", children: [
3955
+ const composerDock = /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "pactor-chat-view__composer-dock", children: [
3729
3956
  composerNode,
3730
- composerBottom !== void 0 && composerBottom !== null ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "pactor-chat-view__composer-bottom", children: composerBottom }) : null
3957
+ composerBottom !== void 0 && composerBottom !== null ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "pactor-chat-view__composer-bottom", children: composerBottom }) : null
3731
3958
  ] });
3732
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
3959
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
3733
3960
  "div",
3734
3961
  {
3735
3962
  className: `pactor-chat-view${isEmpty ? " pactor-chat-view--empty" : ""}${className ? ` ${className}` : ""}`,
3736
3963
  children: [
3737
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "pactor-chat-messages", ref: containerRef, children: [
3738
- isEmpty ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "pactor-chat-view__empty-stack", children: [
3739
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3964
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "pactor-chat-messages", ref: containerRef, children: [
3965
+ isEmpty ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "pactor-chat-view__empty-stack", children: [
3966
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3740
3967
  EmptyState,
3741
3968
  {
3742
3969
  greeting,
@@ -3746,7 +3973,7 @@ function ChatView({
3746
3973
  }
3747
3974
  ),
3748
3975
  composerDock
3749
- ] }) : messages.map((message) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3976
+ ] }) : messages.map((message) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3750
3977
  MessageBubble,
3751
3978
  {
3752
3979
  message,
@@ -3758,19 +3985,18 @@ function ChatView({
3758
3985
  onEditResend: (text) => handleEditResend(message.id, text),
3759
3986
  messageActions,
3760
3987
  callService,
3761
- onMessageAction,
3762
- onOpenArtifact
3988
+ onMessageAction
3763
3989
  },
3764
3990
  message.id
3765
3991
  )),
3766
- !isFollowing && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
3992
+ !isFollowing && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
3767
3993
  "button",
3768
3994
  {
3769
3995
  type: "button",
3770
3996
  className: "pactor-chat-scroll-bottom",
3771
3997
  onClick: scrollToBottom,
3772
3998
  children: [
3773
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_components10.Icon, { name: "arrow-down", size: 13 }),
3999
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_components11.Icon, { name: "arrow-down", size: 13 }),
3774
4000
  "\u56DE\u5230\u5E95\u90E8"
3775
4001
  ]
3776
4002
  }
@@ -3783,8 +4009,8 @@ function ChatView({
3783
4009
  }
3784
4010
 
3785
4011
  // src/view/WorkspaceHeader.tsx
3786
- var import_components11 = require("@pactor-app/ui/components");
3787
- var import_react16 = require("react");
4012
+ var import_components12 = require("@pactor-app/ui/components");
4013
+ var import_react18 = require("react");
3788
4014
 
3789
4015
  // src/export-markdown.ts
3790
4016
  var ROLE_LABELS = {
@@ -3861,7 +4087,7 @@ function buildHeaderActionsFragment(props) {
3861
4087
  }
3862
4088
 
3863
4089
  // src/view/WorkspaceHeader.tsx
3864
- var import_jsx_runtime16 = require("react/jsx-runtime");
4090
+ var import_jsx_runtime17 = require("react/jsx-runtime");
3865
4091
  function readCurrentTheme() {
3866
4092
  if (typeof document === "undefined") {
3867
4093
  return "light";
@@ -3881,10 +4107,10 @@ function WorkspaceHeader({
3881
4107
  onTitleChange
3882
4108
  }) {
3883
4109
  const hasActions = headerActions !== void 0 && headerActions.length > 0;
3884
- const [overrideTitle, setOverrideTitle] = (0, import_react16.useState)(null);
3885
- const [editing, setEditing] = (0, import_react16.useState)(false);
3886
- const [draft, setDraft] = (0, import_react16.useState)("");
3887
- const prevTitleRef = (0, import_react16.useRef)(title);
4110
+ const [overrideTitle, setOverrideTitle] = (0, import_react18.useState)(null);
4111
+ const [editing, setEditing] = (0, import_react18.useState)(false);
4112
+ const [draft, setDraft] = (0, import_react18.useState)("");
4113
+ const prevTitleRef = (0, import_react18.useRef)(title);
3888
4114
  if (prevTitleRef.current !== title) {
3889
4115
  prevTitleRef.current = title;
3890
4116
  if (overrideTitle !== null) {
@@ -3892,7 +4118,7 @@ function WorkspaceHeader({
3892
4118
  }
3893
4119
  }
3894
4120
  const displayTitle = overrideTitle ?? title;
3895
- const [theme, setTheme] = (0, import_react16.useState)(readCurrentTheme);
4121
+ const [theme, setTheme] = (0, import_react18.useState)(readCurrentTheme);
3896
4122
  const commitTitle = () => {
3897
4123
  setEditing(false);
3898
4124
  const next = draft.trim();
@@ -3919,9 +4145,9 @@ function WorkspaceHeader({
3919
4145
  store.clear();
3920
4146
  onClear?.();
3921
4147
  };
3922
- const handlersRef = (0, import_react16.useRef)({ handleExport, handleTheme, handleClear });
4148
+ const handlersRef = (0, import_react18.useRef)({ handleExport, handleTheme, handleClear });
3923
4149
  handlersRef.current = { handleExport, handleTheme, handleClear };
3924
- (0, import_react16.useEffect)(() => {
4150
+ (0, import_react18.useEffect)(() => {
3925
4151
  setChatChromeHandlers({
3926
4152
  headerAction: (name) => {
3927
4153
  const handlers2 = handlersRef.current;
@@ -3936,7 +4162,7 @@ function WorkspaceHeader({
3936
4162
  });
3937
4163
  }, []);
3938
4164
  const actionButtons = {
3939
- export: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4165
+ export: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3940
4166
  "button",
3941
4167
  {
3942
4168
  type: "button",
@@ -3944,11 +4170,11 @@ function WorkspaceHeader({
3944
4170
  title: "\u5BFC\u51FA Markdown",
3945
4171
  "aria-label": "\u5BFC\u51FA Markdown",
3946
4172
  onClick: handleExport,
3947
- children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_components11.Icon, { name: "download", size: 15 })
4173
+ children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_components12.Icon, { name: "download", size: 15 })
3948
4174
  },
3949
4175
  "export"
3950
4176
  ),
3951
- theme: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4177
+ theme: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3952
4178
  "button",
3953
4179
  {
3954
4180
  type: "button",
@@ -3956,11 +4182,11 @@ function WorkspaceHeader({
3956
4182
  title: theme === "dark" ? "\u5207\u6362\u4E3A\u6D45\u8272" : "\u5207\u6362\u4E3A\u6DF1\u8272",
3957
4183
  "aria-label": "\u5207\u6362\u660E\u6697\u4E3B\u9898",
3958
4184
  onClick: handleTheme,
3959
- children: theme === "dark" ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_components11.Icon, { name: "sun", size: 15 }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_components11.Icon, { name: "moon", size: 15 })
4185
+ children: theme === "dark" ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_components12.Icon, { name: "sun", size: 15 }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_components12.Icon, { name: "moon", size: 15 })
3960
4186
  },
3961
4187
  "theme"
3962
4188
  ),
3963
- clear: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4189
+ clear: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3964
4190
  "button",
3965
4191
  {
3966
4192
  type: "button",
@@ -3968,12 +4194,12 @@ function WorkspaceHeader({
3968
4194
  title: "\u6E05\u7A7A\u4F1A\u8BDD",
3969
4195
  "aria-label": "\u6E05\u7A7A\u4F1A\u8BDD",
3970
4196
  onClick: handleClear,
3971
- children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_components11.Icon, { name: "trash", size: 15 })
4197
+ children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_components12.Icon, { name: "trash", size: 15 })
3972
4198
  },
3973
4199
  "clear"
3974
4200
  )
3975
4201
  };
3976
- const titleNode = editableTitle ? editing ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4202
+ const titleNode = editableTitle ? editing ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3977
4203
  "input",
3978
4204
  {
3979
4205
  className: "pactor-chat-workspace__title-input",
@@ -3990,7 +4216,7 @@ function WorkspaceHeader({
3990
4216
  }
3991
4217
  }
3992
4218
  }
3993
- ) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4219
+ ) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3994
4220
  "button",
3995
4221
  {
3996
4222
  type: "button",
@@ -4002,17 +4228,17 @@ function WorkspaceHeader({
4002
4228
  },
4003
4229
  children: displayTitle
4004
4230
  }
4005
- ) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "pactor-chat-workspace__title", children: title });
4006
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("header", { className: "pactor-chat-workspace__header", children: [
4231
+ ) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "pactor-chat-workspace__title", children: title });
4232
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("header", { className: "pactor-chat-workspace__header", children: [
4007
4233
  headerStart !== void 0 ? (
4008
4234
  // header 位模型 chip(决策 D2):与 title 组成左端组,chip 在前
4009
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "pactor-chat-workspace__header-left", children: [
4235
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "pactor-chat-workspace__header-left", children: [
4010
4236
  headerStart,
4011
4237
  titleNode
4012
4238
  ] })
4013
4239
  ) : titleNode,
4014
- hasActions ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "pactor-chat-workspace__header-right", children: [
4015
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "pactor-chat-workspace__header-actions", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4240
+ hasActions ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "pactor-chat-workspace__header-right", children: [
4241
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "pactor-chat-workspace__header-actions", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
4016
4242
  ChromeSlot,
4017
4243
  {
4018
4244
  fragment: buildHeaderActionsFragment({
@@ -4022,18 +4248,18 @@ function WorkspaceHeader({
4022
4248
  fallback: headerActions.map((action) => actionButtons[action])
4023
4249
  }
4024
4250
  ) }),
4025
- headerExtra !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "pactor-chat-workspace__header-extra", children: headerExtra }) : null
4026
- ] }) : headerExtra !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "pactor-chat-workspace__header-extra", children: headerExtra }) : null
4251
+ headerExtra !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "pactor-chat-workspace__header-extra", children: headerExtra }) : null
4252
+ ] }) : headerExtra !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "pactor-chat-workspace__header-extra", children: headerExtra }) : null
4027
4253
  ] });
4028
4254
  }
4029
4255
 
4030
4256
  // src/chat-composition.tsx
4031
- var import_jsx_runtime17 = require("react/jsx-runtime");
4257
+ var import_jsx_runtime18 = require("react/jsx-runtime");
4032
4258
  function DslNodeSlotInner({ node }) {
4033
4259
  const { renderChildren } = (0, import_runtime5.useRenderer)();
4034
4260
  return renderChildren([node]);
4035
4261
  }
4036
- var DslSlotGuard = class extends import_react17.Component {
4262
+ var DslSlotGuard = class extends import_react19.Component {
4037
4263
  constructor() {
4038
4264
  super(...arguments);
4039
4265
  this.state = { failed: false };
@@ -4051,17 +4277,17 @@ var DslSlotGuard = class extends import_react17.Component {
4051
4277
  }
4052
4278
  };
4053
4279
  function DslNodeSlot({ node }) {
4054
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DslSlotGuard, { children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DslNodeSlotInner, { node }) });
4280
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(DslSlotGuard, { children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(DslNodeSlotInner, { node }) });
4055
4281
  }
4056
4282
  function isDslNodeValue(value) {
4057
- return typeof value === "object" && value !== null && !Array.isArray(value) && !(0, import_react17.isValidElement)(value) && typeof value.type === "string";
4283
+ return typeof value === "object" && value !== null && !Array.isArray(value) && !(0, import_react19.isValidElement)(value) && typeof value.type === "string";
4058
4284
  }
4059
4285
  function resolveSlot(slot) {
4060
4286
  if (slot === void 0 || slot === null) {
4061
4287
  return void 0;
4062
4288
  }
4063
4289
  if (isDslNodeValue(slot)) {
4064
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DslNodeSlot, { node: slot });
4290
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(DslNodeSlot, { node: slot });
4065
4291
  }
4066
4292
  return slot;
4067
4293
  }
@@ -4105,33 +4331,34 @@ function ChatComposition({
4105
4331
  onPanelClose,
4106
4332
  inspector,
4107
4333
  onArtifact,
4108
- onOpenArtifact
4334
+ onOpenArtifact,
4335
+ onOpenArtifactList
4109
4336
  }) {
4110
- const storeRef = (0, import_react17.useRef)(null);
4337
+ const storeRef = (0, import_react19.useRef)(null);
4111
4338
  if (storeRef.current === null) {
4112
4339
  storeRef.current = services.store ?? services.storeFactory?.() ?? new ConversationStore();
4113
4340
  }
4114
4341
  const store = storeRef.current;
4115
- const artifactStoreRef = (0, import_react17.useRef)(null);
4342
+ const artifactStoreRef = (0, import_react19.useRef)(null);
4116
4343
  if (artifactStoreRef.current === null) {
4117
4344
  artifactStoreRef.current = services.artifactStore ?? new ArtifactStore();
4118
4345
  }
4119
4346
  const artifactStore = artifactStoreRef.current;
4120
4347
  const panelControlled = panelOpen !== void 0 || artifact !== void 0;
4121
- const storeArtifact = (0, import_react17.useSyncExternalStore)(
4348
+ const storeArtifact = (0, import_react19.useSyncExternalStore)(
4122
4349
  (listener) => artifactStore.subscribe(listener),
4123
4350
  () => artifactStore.get()
4124
4351
  );
4125
- const storeArtifacts = (0, import_react17.useSyncExternalStore)(
4352
+ const storeArtifacts = (0, import_react19.useSyncExternalStore)(
4126
4353
  (listener) => artifactStore.subscribe(listener),
4127
4354
  () => artifactStore.list()
4128
4355
  );
4129
- const messages = (0, import_react17.useSyncExternalStore)(
4356
+ const messages = (0, import_react19.useSyncExternalStore)(
4130
4357
  (listener) => store.subscribe(listener),
4131
4358
  () => store.getMessages()
4132
4359
  );
4133
- const streamArtifacts = (0, import_react17.useMemo)(() => collectArtifacts(messages), [messages]);
4134
- const mergedArtifacts = (0, import_react17.useMemo)(
4360
+ const streamArtifacts = (0, import_react19.useMemo)(() => collectArtifacts(messages), [messages]);
4361
+ const mergedArtifacts = (0, import_react19.useMemo)(
4135
4362
  () => mergeArtifacts(streamArtifacts, storeArtifacts),
4136
4363
  [streamArtifacts, storeArtifacts]
4137
4364
  );
@@ -4156,7 +4383,18 @@ function ChatComposition({
4156
4383
  artifactStore.open(next);
4157
4384
  }
4158
4385
  };
4159
- const [attachments, setAttachments] = (0, import_react17.useState)([]);
4386
+ const [listViewRequest, setListViewRequest] = (0, import_react19.useState)(null);
4387
+ const handleOpenArtifactList = () => {
4388
+ onOpenArtifactList?.();
4389
+ setListViewRequest((value) => (value ?? 0) + 1);
4390
+ if (!panelControlled && artifactStore.get() === null) {
4391
+ const first = mergedArtifacts[0];
4392
+ if (first !== void 0) {
4393
+ artifactStore.open(first);
4394
+ }
4395
+ }
4396
+ };
4397
+ const [attachments, setAttachments] = (0, import_react19.useState)([]);
4160
4398
  const handleAttachFiles = services.onAttachFiles ? (files) => {
4161
4399
  void Promise.resolve(services.onAttachFiles(files)).then(
4162
4400
  (created) => {
@@ -4176,7 +4414,7 @@ function ChatComposition({
4176
4414
  model,
4177
4415
  onModelChange
4178
4416
  });
4179
- const headerModelChip = modelPlacement === "header" && modelsEnabled ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
4417
+ const headerModelChip = modelPlacement === "header" && modelsEnabled ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4180
4418
  ModelSelect,
4181
4419
  {
4182
4420
  models,
@@ -4184,137 +4422,144 @@ function ChatComposition({
4184
4422
  onModelChange: handleModelChange
4185
4423
  }
4186
4424
  ) : void 0;
4187
- const mergedToolbarEnd = services.toolbarEnd !== void 0 || toolbarEnd !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
4425
+ const mergedToolbarEnd = services.toolbarEnd !== void 0 || toolbarEnd !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
4188
4426
  services.toolbarEnd,
4189
4427
  toolbarEnd
4190
4428
  ] }) : void 0;
4191
- const mergedToolbarStart = services.toolbarStart !== void 0 || toolbarStart !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
4429
+ const mergedToolbarStart = services.toolbarStart !== void 0 || toolbarStart !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
4192
4430
  services.toolbarStart,
4193
4431
  toolbarStart
4194
4432
  ] }) : void 0;
4195
- const mergedComposerFooter = services.composerFooter !== void 0 || composerFooter !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
4433
+ const mergedComposerFooter = services.composerFooter !== void 0 || composerFooter !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
4196
4434
  services.composerFooter,
4197
4435
  composerFooter
4198
4436
  ] }) : void 0;
4199
- const mergedComposerBottom = services.composerBottom !== void 0 || composerBottom !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
4437
+ const mergedComposerBottom = services.composerBottom !== void 0 || composerBottom !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
4200
4438
  services.composerBottom,
4201
4439
  composerBottom
4202
4440
  ] }) : void 0;
4203
4441
  const hasHeaderContent = header !== void 0 && header !== null ? true : title !== void 0 || headerExtra !== void 0 && headerExtra !== null || headerActions !== void 0 && headerActions.length > 0 || headerModelChip !== void 0;
4204
4442
  const renderHeader = showHeader !== false && hasHeaderContent;
4205
- const workspace = /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
4443
+ const workspaceHeader = renderHeader ? header ?? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4444
+ WorkspaceHeader,
4445
+ {
4446
+ title,
4447
+ headerExtra,
4448
+ headerActions,
4449
+ editableTitle,
4450
+ headerStart: headerModelChip,
4451
+ store,
4452
+ onExport,
4453
+ onThemeChange,
4454
+ onClear,
4455
+ onTitleChange
4456
+ }
4457
+ ) : null;
4458
+ const workspace = /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4206
4459
  "div",
4207
4460
  {
4208
4461
  className: `pactor-chat-workspace${className ? ` ${className}` : ""}`,
4209
- children: [
4210
- renderHeader ? header ?? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
4211
- WorkspaceHeader,
4462
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4463
+ ChatView,
4464
+ {
4465
+ store,
4466
+ transport: services.transport,
4467
+ onSend: handleSend,
4468
+ safeRegistry: services.safeRegistry,
4469
+ capabilities: services.capabilities,
4470
+ permission: services.permission,
4471
+ confirm: services.confirm,
4472
+ conversationId,
4473
+ user: services.user,
4474
+ params,
4475
+ greeting,
4476
+ subtitle,
4477
+ suggestions,
4478
+ attachments,
4479
+ onAttachmentsChange: setAttachments,
4480
+ onAttachFiles: handleAttachFiles,
4481
+ onAttachmentClick: services.onAttachmentClick,
4482
+ toolbarStart: mergedToolbarStart,
4483
+ toolbarEnd: mergedToolbarEnd,
4484
+ composerFooter: mergedComposerFooter,
4485
+ composerBottom: mergedComposerBottom,
4486
+ hideToolbar,
4487
+ onMentionTrigger: services.onMentionTrigger,
4488
+ onPlusMenu: services.onPlusMenu,
4489
+ onArtifact,
4490
+ onOpenArtifact: handleOpenArtifact,
4491
+ onOpenArtifactList: handleOpenArtifactList,
4492
+ models,
4493
+ model: currentModel,
4494
+ onModelChange: handleModelChange,
4495
+ modelPlacement,
4496
+ contexts,
4497
+ onContextsChange,
4498
+ callService: services.callService,
4499
+ messageActions,
4500
+ onMessageAction
4501
+ }
4502
+ )
4503
+ }
4504
+ );
4505
+ const main = sidebar ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(AppShell, { sidebar, children: workspace }) : workspace;
4506
+ const panelFeatureUsed = artifact !== void 0 || panelOpen !== void 0 || inspector !== void 0 || onPanelClose !== void 0 || onArtifact !== void 0 || onOpenArtifact !== void 0 || onOpenArtifactList !== void 0 || services.artifactStore !== void 0;
4507
+ if (!panelFeatureUsed && !effectivePanelOpen) {
4508
+ return workspaceHeader ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "pactor-chat-with-header", children: [
4509
+ workspaceHeader,
4510
+ main
4511
+ ] }) : main;
4512
+ }
4513
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "pactor-chat-inspector-host", children: [
4514
+ workspaceHeader,
4515
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "pactor-chat-inspector-host__row", children: [
4516
+ main,
4517
+ effectivePanelOpen ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
4518
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4519
+ "div",
4212
4520
  {
4213
- title,
4214
- headerExtra,
4215
- headerActions,
4216
- editableTitle,
4217
- headerStart: headerModelChip,
4218
- store,
4219
- onExport,
4220
- onThemeChange,
4221
- onClear,
4222
- onTitleChange
4521
+ className: "pactor-chat-inspector__scrim",
4522
+ "aria-hidden": true,
4523
+ onClick: handlePanelClose
4223
4524
  }
4224
- ) : null,
4225
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
4226
- ChatView,
4525
+ ),
4526
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4527
+ ArtifactPanel,
4227
4528
  {
4228
- store,
4229
- transport: services.transport,
4230
- onSend: handleSend,
4529
+ artifact: effectiveArtifact,
4530
+ artifacts: effectiveArtifacts,
4531
+ activeArtifactId: effectiveArtifact?.id,
4532
+ onSelectArtifact: handleSelectArtifact,
4533
+ inspector,
4534
+ onClose: handlePanelClose,
4231
4535
  safeRegistry: services.safeRegistry,
4232
- capabilities: services.capabilities,
4233
- permission: services.permission,
4234
- confirm: services.confirm,
4235
- conversationId,
4236
4536
  user: services.user,
4237
- params,
4238
- greeting,
4239
- subtitle,
4240
- suggestions,
4241
- attachments,
4242
- onAttachmentsChange: setAttachments,
4243
- onAttachFiles: handleAttachFiles,
4244
- onAttachmentClick: services.onAttachmentClick,
4245
- toolbarStart: mergedToolbarStart,
4246
- toolbarEnd: mergedToolbarEnd,
4247
- composerFooter: mergedComposerFooter,
4248
- composerBottom: mergedComposerBottom,
4249
- hideToolbar,
4250
- onMentionTrigger: services.onMentionTrigger,
4251
- onPlusMenu: services.onPlusMenu,
4252
- onArtifact,
4253
- onOpenArtifact: handleOpenArtifact,
4254
- models,
4255
- model: currentModel,
4256
- onModelChange: handleModelChange,
4257
- modelPlacement,
4258
- contexts,
4259
- onContextsChange,
4260
- callService: services.callService,
4261
- messageActions,
4262
- onMessageAction
4537
+ artifactViewers: services.artifactViewers,
4538
+ viewRequest: listViewRequest,
4539
+ onViewRequestConsumed: () => setListViewRequest(null)
4263
4540
  }
4264
4541
  )
4265
- ]
4266
- }
4267
- );
4268
- const main = sidebar ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(AppShell, { sidebar, children: workspace }) : workspace;
4269
- const panelFeatureUsed = artifact !== void 0 || panelOpen !== void 0 || inspector !== void 0 || onPanelClose !== void 0 || onArtifact !== void 0 || onOpenArtifact !== void 0 || services.artifactStore !== void 0;
4270
- if (!panelFeatureUsed && !effectivePanelOpen) {
4271
- return main;
4272
- }
4273
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "pactor-chat-inspector-host", children: [
4274
- main,
4275
- effectivePanelOpen ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
4276
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
4277
- "div",
4278
- {
4279
- className: "pactor-chat-inspector__scrim",
4280
- "aria-hidden": true,
4281
- onClick: handlePanelClose
4282
- }
4283
- ),
4284
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
4285
- ArtifactPanel,
4286
- {
4287
- artifact: effectiveArtifact,
4288
- artifacts: effectiveArtifacts,
4289
- activeArtifactId: effectiveArtifact?.id,
4290
- onSelectArtifact: handleSelectArtifact,
4291
- inspector,
4292
- onClose: handlePanelClose,
4293
- safeRegistry: services.safeRegistry,
4294
- user: services.user,
4295
- artifactViewers: services.artifactViewers
4296
- }
4297
- )
4298
- ] }) : null
4542
+ ] }) : null
4543
+ ] })
4299
4544
  ] });
4300
4545
  }
4301
4546
 
4302
4547
  // src/chat-services.tsx
4303
- var import_react18 = require("react");
4304
- var import_jsx_runtime18 = require("react/jsx-runtime");
4305
- var ChatServicesContext = (0, import_react18.createContext)(null);
4548
+ var import_react20 = require("react");
4549
+ var import_jsx_runtime19 = require("react/jsx-runtime");
4550
+ var ChatServicesContext = (0, import_react20.createContext)(null);
4306
4551
  function ChatServicesProvider({
4307
4552
  value,
4308
4553
  children
4309
4554
  }) {
4310
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ChatServicesContext.Provider, { value, children });
4555
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ChatServicesContext.Provider, { value, children });
4311
4556
  }
4312
4557
  function useChatServices() {
4313
- return (0, import_react18.useContext)(ChatServicesContext);
4558
+ return (0, import_react20.useContext)(ChatServicesContext);
4314
4559
  }
4315
4560
 
4316
4561
  // src/chat-workspace.tsx
4317
- var import_jsx_runtime19 = require("react/jsx-runtime");
4562
+ var import_jsx_runtime20 = require("react/jsx-runtime");
4318
4563
  function createChatWorkspace(services) {
4319
4564
  function ChatWorkspace({
4320
4565
  title,
@@ -4335,6 +4580,7 @@ function createChatWorkspace(services) {
4335
4580
  inspector,
4336
4581
  onArtifact,
4337
4582
  onOpenArtifact,
4583
+ onOpenArtifactList,
4338
4584
  onSelectArtifact,
4339
4585
  headerActions,
4340
4586
  editableTitle,
@@ -4352,7 +4598,7 @@ function createChatWorkspace(services) {
4352
4598
  onMessageAction,
4353
4599
  className
4354
4600
  }) {
4355
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ChatServicesProvider, { value: services, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
4601
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ChatServicesProvider, { value: services, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4356
4602
  ChatComposition,
4357
4603
  {
4358
4604
  services,
@@ -4364,18 +4610,19 @@ function createChatWorkspace(services) {
4364
4610
  params,
4365
4611
  className,
4366
4612
  headerExtra: services.headerExtra,
4367
- sidebar: sidebar ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(DslNodeSlot, { node: sidebar }) : void 0,
4368
- toolbarStart: toolbarStart ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(DslNodeSlot, { node: toolbarStart }) : void 0,
4369
- toolbarEnd: toolbarEnd ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(DslNodeSlot, { node: toolbarEnd }) : void 0,
4370
- composerFooter: composerFooter ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(DslNodeSlot, { node: composerFooter }) : void 0,
4371
- composerBottom: composerBottom ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(DslNodeSlot, { node: composerBottom }) : void 0,
4613
+ sidebar: sidebar ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DslNodeSlot, { node: sidebar }) : void 0,
4614
+ toolbarStart: toolbarStart ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DslNodeSlot, { node: toolbarStart }) : void 0,
4615
+ toolbarEnd: toolbarEnd ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DslNodeSlot, { node: toolbarEnd }) : void 0,
4616
+ composerFooter: composerFooter ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DslNodeSlot, { node: composerFooter }) : void 0,
4617
+ composerBottom: composerBottom ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DslNodeSlot, { node: composerBottom }) : void 0,
4372
4618
  hideToolbar,
4373
4619
  artifact,
4374
4620
  panelOpen,
4375
4621
  onPanelClose,
4376
- inspector: inspector ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(DslNodeSlot, { node: inspector }) : void 0,
4622
+ inspector: inspector ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DslNodeSlot, { node: inspector }) : void 0,
4377
4623
  onArtifact,
4378
4624
  onOpenArtifact,
4625
+ onOpenArtifactList,
4379
4626
  onSelectArtifact,
4380
4627
  headerActions,
4381
4628
  editableTitle,
@@ -4398,8 +4645,8 @@ function createChatWorkspace(services) {
4398
4645
  }
4399
4646
 
4400
4647
  // src/view/Chat.tsx
4401
- var import_components12 = require("@pactor-app/ui/components");
4402
- var import_react19 = require("react");
4648
+ var import_components13 = require("@pactor-app/ui/components");
4649
+ var import_react21 = require("react");
4403
4650
 
4404
4651
  // src/view/chrome/menu.tsx
4405
4652
  function buildSidebarMenuFragment(props) {
@@ -4428,7 +4675,7 @@ function buildSidebarMenuFragment(props) {
4428
4675
  }
4429
4676
 
4430
4677
  // src/view/ChatShell.tsx
4431
- var import_jsx_runtime20 = require("react/jsx-runtime");
4678
+ var import_jsx_runtime21 = require("react/jsx-runtime");
4432
4679
  function ChatShell({
4433
4680
  menu,
4434
4681
  activeMenuKey,
@@ -4440,7 +4687,7 @@ function ChatShell({
4440
4687
  className,
4441
4688
  onMenuSelect
4442
4689
  }) {
4443
- const sidebarContent = resolveSlot(sidebar) ?? (menu && menu.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4690
+ const sidebarContent = resolveSlot(sidebar) ?? (menu && menu.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4444
4691
  ChatSidebarMenu,
4445
4692
  {
4446
4693
  menu,
@@ -4448,7 +4695,7 @@ function ChatShell({
4448
4695
  onMenuSelect
4449
4696
  }
4450
4697
  ) : null);
4451
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4698
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4452
4699
  AppShell,
4453
4700
  {
4454
4701
  sidebar: sidebarContent,
@@ -4465,7 +4712,7 @@ function ChatShellDslAdapter({
4465
4712
  onMenuSelect,
4466
4713
  ...rest
4467
4714
  }) {
4468
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4715
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4469
4716
  ChatShell,
4470
4717
  {
4471
4718
  ...rest,
@@ -4480,20 +4727,20 @@ function registerChatShellComponent(registry) {
4480
4727
  }
4481
4728
 
4482
4729
  // src/view/Chat.tsx
4483
- var import_jsx_runtime21 = require("react/jsx-runtime");
4730
+ var import_jsx_runtime22 = require("react/jsx-runtime");
4484
4731
  function ChatSidebarMenu({
4485
4732
  menu,
4486
4733
  activeMenuKey,
4487
4734
  onMenuSelect
4488
4735
  }) {
4489
4736
  const drawer = useSidebarDrawer();
4490
- const menuRef = (0, import_react19.useRef)(menu);
4737
+ const menuRef = (0, import_react21.useRef)(menu);
4491
4738
  menuRef.current = menu;
4492
- const selectRef = (0, import_react19.useRef)(onMenuSelect);
4739
+ const selectRef = (0, import_react21.useRef)(onMenuSelect);
4493
4740
  selectRef.current = onMenuSelect;
4494
- const drawerRef = (0, import_react19.useRef)(drawer);
4741
+ const drawerRef = (0, import_react21.useRef)(drawer);
4495
4742
  drawerRef.current = drawer;
4496
- (0, import_react19.useEffect)(() => {
4743
+ (0, import_react21.useEffect)(() => {
4497
4744
  setChatChromeHandlers({
4498
4745
  menuSelect: (key) => {
4499
4746
  const item = menuRef.current.find((entry) => entry.key === key);
@@ -4507,12 +4754,12 @@ function ChatSidebarMenu({
4507
4754
  }, []);
4508
4755
  const fallback = (() => {
4509
4756
  let lastGroup;
4510
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("nav", { className: "pactor-chat-menu", "aria-label": "\u4F1A\u8BDD\u5BFC\u822A", children: menu.map((item) => {
4757
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("nav", { className: "pactor-chat-menu", "aria-label": "\u4F1A\u8BDD\u5BFC\u822A", children: menu.map((item) => {
4511
4758
  const groupLabel = item.group !== void 0 && item.group !== lastGroup ? item.group : void 0;
4512
4759
  lastGroup = item.group;
4513
4760
  const active = item.key === activeMenuKey;
4514
4761
  const collapsed = drawer?.collapsed === true;
4515
- const button = /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
4762
+ const button = /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
4516
4763
  "button",
4517
4764
  {
4518
4765
  type: "button",
@@ -4527,20 +4774,20 @@ function ChatSidebarMenu({
4527
4774
  drawer?.close();
4528
4775
  },
4529
4776
  children: [
4530
- item.icon !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "pactor-chat-menu__icon", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_components12.Icon, { name: item.icon, size: 15, strokeWidth: 1.7 }) }) : null,
4531
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "pactor-chat-menu__label", children: item.label }),
4532
- item.dot === true ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "pactor-chat-menu__dot", "aria-hidden": true }) : null,
4533
- item.badge !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "pactor-chat-menu__badge", children: item.badge }) : null
4777
+ item.icon !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "pactor-chat-menu__icon", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_components13.Icon, { name: item.icon, size: 15, strokeWidth: 1.7 }) }) : null,
4778
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "pactor-chat-menu__label", children: item.label }),
4779
+ item.dot === true ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "pactor-chat-menu__dot", "aria-hidden": true }) : null,
4780
+ item.badge !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "pactor-chat-menu__badge", children: item.badge }) : null
4534
4781
  ]
4535
4782
  }
4536
4783
  );
4537
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_react19.Fragment, { children: [
4538
- groupLabel !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "pactor-chat-menu__group", children: groupLabel }) : null,
4539
- collapsed ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_components12.RailTooltip, { label: item.label, children: button }) : button
4784
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_react21.Fragment, { children: [
4785
+ groupLabel !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "pactor-chat-menu__group", children: groupLabel }) : null,
4786
+ collapsed ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_components13.RailTooltip, { label: item.label, children: button }) : button
4540
4787
  ] }, item.key);
4541
4788
  }) });
4542
4789
  })();
4543
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4790
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4544
4791
  ChromeSlot,
4545
4792
  {
4546
4793
  fragment: buildSidebarMenuFragment({ menu, activeMenuKey }),
@@ -4586,13 +4833,14 @@ function Chat({
4586
4833
  inspector,
4587
4834
  onArtifact,
4588
4835
  onOpenArtifact,
4836
+ onOpenArtifactList,
4589
4837
  onSelectArtifact,
4590
4838
  className,
4591
4839
  onSend,
4592
4840
  onMenuSelect
4593
4841
  }) {
4594
4842
  const services = useChatServices();
4595
- (0, import_react19.useEffect)(() => {
4843
+ (0, import_react21.useEffect)(() => {
4596
4844
  if (!services) {
4597
4845
  console.warn(
4598
4846
  "[@pactor-app/chat] Chat \u672A\u68C0\u6D4B\u5230 ChatServicesProvider\uFF1A\u8BF7\u5728\u5E94\u7528\u6839\u90E8\u4EE5 <ChatServicesProvider> \u6CE8\u5165 transport \u7B49\u670D\u52A1"
@@ -4600,10 +4848,10 @@ function Chat({
4600
4848
  }
4601
4849
  }, [services]);
4602
4850
  if (!services) {
4603
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "pactor-chat-notice", role: "note", children: "\u672A\u914D\u7F6E\u804A\u5929\u670D\u52A1\uFF1A\u8BF7\u5728 Chat \u5916\u5C42\u4F7F\u7528 ChatServicesProvider \u6CE8\u5165 transport \u7B49\u670D\u52A1\u540E\u91CD\u8BD5\u3002" });
4851
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "pactor-chat-notice", role: "note", children: "\u672A\u914D\u7F6E\u804A\u5929\u670D\u52A1\uFF1A\u8BF7\u5728 Chat \u5916\u5C42\u4F7F\u7528 ChatServicesProvider \u6CE8\u5165 transport \u7B49\u670D\u52A1\u540E\u91CD\u8BD5\u3002" });
4604
4852
  }
4605
4853
  const sidebarSlot = resolveSlot(sidebar);
4606
- const sidebarContent = sidebarSlot ?? (menu && menu.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4854
+ const sidebarContent = sidebarSlot ?? (menu && menu.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4607
4855
  ChatSidebarMenu,
4608
4856
  {
4609
4857
  menu,
@@ -4611,7 +4859,7 @@ function Chat({
4611
4859
  onMenuSelect
4612
4860
  }
4613
4861
  ) : void 0);
4614
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4862
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4615
4863
  ChatComposition,
4616
4864
  {
4617
4865
  services,
@@ -4652,6 +4900,7 @@ function Chat({
4652
4900
  inspector: resolveSlot(inspector),
4653
4901
  onArtifact,
4654
4902
  onOpenArtifact,
4903
+ onOpenArtifactList,
4655
4904
  onSelectArtifact
4656
4905
  }
4657
4906
  );
@@ -4663,6 +4912,7 @@ function ChatDslAdapter({
4663
4912
  onPanelClose,
4664
4913
  onArtifact,
4665
4914
  onOpenArtifact,
4915
+ onOpenArtifactList,
4666
4916
  onSelectArtifact,
4667
4917
  onModelChange,
4668
4918
  onContextsChange,
@@ -4673,7 +4923,7 @@ function ChatDslAdapter({
4673
4923
  onTitleChange,
4674
4924
  ...rest
4675
4925
  }) {
4676
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4926
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4677
4927
  Chat,
4678
4928
  {
4679
4929
  ...rest,
@@ -4682,6 +4932,7 @@ function ChatDslAdapter({
4682
4932
  onPanelClose: onPanelClose ? () => onPanelClose({}) : void 0,
4683
4933
  onArtifact: onArtifact ? (artifact) => onArtifact({ artifact }) : void 0,
4684
4934
  onOpenArtifact: onOpenArtifact ? (artifact) => onOpenArtifact({ artifact }) : void 0,
4935
+ onOpenArtifactList: onOpenArtifactList ? () => onOpenArtifactList({}) : void 0,
4685
4936
  onSelectArtifact: onSelectArtifact ? (artifact) => onSelectArtifact({ artifact }) : void 0,
4686
4937
  onModelChange: onModelChange ? (model) => onModelChange({ model }) : void 0,
4687
4938
  onContextsChange: onContextsChange ? (contexts) => onContextsChange({ contexts }) : void 0,
@@ -4700,17 +4951,17 @@ function registerChatComponent(registry) {
4700
4951
  registerChatShellComponent(registry);
4701
4952
  }
4702
4953
  function createChatComponentRegistry() {
4703
- const registry = (0, import_components12.createComponentRegistry)();
4954
+ const registry = (0, import_components13.createComponentRegistry)();
4704
4955
  registerChatComponent(registry);
4705
4956
  return registry;
4706
4957
  }
4707
4958
 
4708
4959
  // src/view/ChatLayout.tsx
4709
- var import_jsx_runtime22 = require("react/jsx-runtime");
4960
+ var import_jsx_runtime23 = require("react/jsx-runtime");
4710
4961
  function ChatLayout({ title, children }) {
4711
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "pactor-chat-layout", children: [
4712
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("header", { className: "pactor-chat-layout__header", children: title ?? "Chat" }),
4713
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("main", { className: "pactor-chat-layout__main", children })
4962
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "pactor-chat-layout", children: [
4963
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("header", { className: "pactor-chat-layout__header", children: title ?? "Chat" }),
4964
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("main", { className: "pactor-chat-layout__main", children })
4714
4965
  ] });
4715
4966
  }
4716
4967
  var CHAT_LAYOUT_TYPE = "chat";
@@ -4731,6 +4982,7 @@ function registerChatLayout(layoutRegistry) {
4731
4982
  CHAT_LAYOUT_TYPE,
4732
4983
  CHAT_SHELL_COMPONENT_TYPE,
4733
4984
  Chat,
4985
+ ChatArtifactCard,
4734
4986
  ChatDenied,
4735
4987
  ChatLayout,
4736
4988
  ChatServicesProvider,
@@ -4745,6 +4997,7 @@ function registerChatLayout(layoutRegistry) {
4745
4997
  MessageBubble,
4746
4998
  PartRenderer,
4747
4999
  applyChatEvent,
5000
+ artifactCardMeta,
4748
5001
  buildArtifactBlob,
4749
5002
  buildArtifactTree,
4750
5003
  buildChatScope,
@@ -4758,6 +5011,8 @@ function registerChatLayout(layoutRegistry) {
4758
5011
  createSafeRegistry,
4759
5012
  detectStreamingMode,
4760
5013
  downloadArtifact,
5014
+ formatArtifactSize,
5015
+ formatMessageTime,
4761
5016
  guardChatDsl,
4762
5017
  isImageArtifact,
4763
5018
  mergeArtifacts,
@@ -4768,6 +5023,8 @@ function registerChatLayout(layoutRegistry) {
4768
5023
  registerChatShellComponent,
4769
5024
  resolveArtifactFileType,
4770
5025
  resolveArtifactFilename,
5026
+ resolveArtifactIcon,
5027
+ resolveArtifactIconName,
4771
5028
  runChatTurn,
4772
5029
  runRegenerateTurn,
4773
5030
  saveBlob,