@pactor-app/chat 1.16.0 → 1.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -141,6 +141,97 @@ function isImageArtifact(artifact) {
141
141
  const ext = resolveArtifactFileType(artifact);
142
142
  return ext !== null && ARTIFACT_IMAGE_EXTENSIONS.includes(ext);
143
143
  }
144
+ var ARTIFACT_ICON_BY_EXTENSION = {
145
+ // 表格数据(绿)
146
+ csv: { name: "table", tone: "green" },
147
+ tsv: { name: "table", tone: "green" },
148
+ xls: { name: "table", tone: "green" },
149
+ xlsx: { name: "table", tone: "green" },
150
+ // 数据 / 数据库(琥珀)
151
+ json: { name: "database", tone: "amber" },
152
+ sql: { name: "database", tone: "amber" },
153
+ // 脚本(蓝,终端图标)
154
+ sh: { name: "terminal", tone: "blue" },
155
+ bash: { name: "terminal", tone: "blue" },
156
+ zsh: { name: "terminal", tone: "blue" },
157
+ // 代码 / 配置(蓝)
158
+ js: { name: "code", tone: "blue" },
159
+ mjs: { name: "code", tone: "blue" },
160
+ cjs: { name: "code", tone: "blue" },
161
+ jsx: { name: "code", tone: "blue" },
162
+ ts: { name: "code", tone: "blue" },
163
+ mts: { name: "code", tone: "blue" },
164
+ cts: { name: "code", tone: "blue" },
165
+ tsx: { name: "code", tone: "blue" },
166
+ py: { name: "code", tone: "blue" },
167
+ rb: { name: "code", tone: "blue" },
168
+ go: { name: "code", tone: "blue" },
169
+ rs: { name: "code", tone: "blue" },
170
+ java: { name: "code", tone: "blue" },
171
+ kt: { name: "code", tone: "blue" },
172
+ c: { name: "code", tone: "blue" },
173
+ h: { name: "code", tone: "blue" },
174
+ cc: { name: "code", tone: "blue" },
175
+ cpp: { name: "code", tone: "blue" },
176
+ cs: { name: "code", tone: "blue" },
177
+ swift: { name: "code", tone: "blue" },
178
+ php: { name: "code", tone: "blue" },
179
+ css: { name: "code", tone: "blue" },
180
+ scss: { name: "code", tone: "blue" },
181
+ less: { name: "code", tone: "blue" },
182
+ html: { name: "code", tone: "blue" },
183
+ vue: { name: "code", tone: "blue" },
184
+ svelte: { name: "code", tone: "blue" },
185
+ yaml: { name: "code", tone: "blue" },
186
+ yml: { name: "code", tone: "blue" },
187
+ toml: { name: "code", tone: "blue" },
188
+ xml: { name: "code", tone: "blue" },
189
+ // 文档 / 文本(石板灰)
190
+ md: { name: "file-text", tone: "slate" },
191
+ markdown: { name: "file-text", tone: "slate" },
192
+ mdx: { name: "file-text", tone: "slate" },
193
+ txt: { name: "file-text", tone: "slate" },
194
+ text: { name: "file-text", tone: "slate" },
195
+ log: { name: "file-text", tone: "slate" },
196
+ rst: { name: "file-text", tone: "slate" },
197
+ pdf: { name: "file-text", tone: "slate" },
198
+ doc: { name: "file-text", tone: "slate" },
199
+ docx: { name: "file-text", tone: "slate" }
200
+ };
201
+ function resolveArtifactIcon(artifact) {
202
+ const ext = resolveArtifactFileType(artifact);
203
+ if (ext !== null) {
204
+ if (ARTIFACT_IMAGE_EXTENSIONS.includes(ext)) {
205
+ return { name: "image", tone: "violet" };
206
+ }
207
+ const spec = ARTIFACT_ICON_BY_EXTENSION[ext];
208
+ if (spec !== void 0) {
209
+ return spec;
210
+ }
211
+ }
212
+ if (artifact.kind === "code") {
213
+ return { name: "code", tone: "blue" };
214
+ }
215
+ if (artifact.kind === "dsl") {
216
+ return { name: "layout-grid", tone: "slate" };
217
+ }
218
+ return ext === null ? { name: "file-text", tone: "slate" } : { name: "file", tone: "slate" };
219
+ }
220
+ function resolveArtifactIconName(artifact) {
221
+ return resolveArtifactIcon(artifact).name;
222
+ }
223
+ function formatArtifactSize(size) {
224
+ if (typeof size !== "number" || !Number.isFinite(size) || size < 0) {
225
+ return null;
226
+ }
227
+ if (size < 1024) {
228
+ return `${size} B`;
229
+ }
230
+ if (size < 1024 * 1024) {
231
+ return `${(size / 1024).toFixed(1)} KB`;
232
+ }
233
+ return `${(size / 1024 / 1024).toFixed(1)} MB`;
234
+ }
144
235
  function collectArtifacts(messages) {
145
236
  const order = [];
146
237
  const byId = /* @__PURE__ */ new Map();
@@ -974,7 +1065,7 @@ import {
974
1065
  isValidElement,
975
1066
  useMemo as useMemo4,
976
1067
  useRef as useRef13,
977
- useState as useState15,
1068
+ useState as useState16,
978
1069
  useSyncExternalStore as useSyncExternalStore2
979
1070
  } from "react";
980
1071
 
@@ -1033,7 +1124,7 @@ function AppShell({
1033
1124
  }
1034
1125
 
1035
1126
  // src/view/ArtifactPanel.tsx
1036
- import { Icon as Icon3 } from "@pactor-app/ui/components";
1127
+ import { Icon as Icon4 } from "@pactor-app/ui/components";
1037
1128
  import { Registry as Registry2 } from "@pactor-app/core";
1038
1129
  import { MarkdownRenderer as MarkdownRenderer2 } from "@pactor-app/markdown";
1039
1130
  import { DslRenderer as DslRenderer2, useRenderer as useRenderer3 } from "@pactor-app/runtime";
@@ -1042,11 +1133,11 @@ import {
1042
1133
  useEffect as useEffect3,
1043
1134
  useMemo,
1044
1135
  useRef as useRef4,
1045
- useState as useState5
1136
+ useState as useState6
1046
1137
  } from "react";
1047
1138
 
1048
1139
  // src/view/PartRenderer.tsx
1049
- import { Icon } from "@pactor-app/ui/components";
1140
+ import { Icon as Icon2 } from "@pactor-app/ui/components";
1050
1141
  import { MarkdownRenderer } from "@pactor-app/markdown";
1051
1142
  import { DslRenderer, useRenderer as useRenderer2 } from "@pactor-app/runtime";
1052
1143
 
@@ -1088,60 +1179,8 @@ function useThrottledValue(value, intervalMs, enabled) {
1088
1179
  }
1089
1180
 
1090
1181
  // src/view/chrome/artifact-card.tsx
1091
- function buildArtifactCardFragment(artifact) {
1092
- return {
1093
- requires: ["Card", "Flex", "Text", "Badge", "Button"],
1094
- node: {
1095
- type: "Card",
1096
- props: { className: "pactor-chat-artifact-card" },
1097
- children: [
1098
- {
1099
- type: "Flex",
1100
- props: { justify: "space-between", align: "center", gap: "small" },
1101
- children: [
1102
- {
1103
- type: "Text",
1104
- props: {
1105
- text: artifact.title,
1106
- strong: true,
1107
- className: "pactor-chat-artifact-card__title"
1108
- }
1109
- },
1110
- {
1111
- type: "Badge",
1112
- props: {
1113
- text: artifact.kind,
1114
- variant: "secondary",
1115
- className: "pactor-chat-artifact-card__kind"
1116
- }
1117
- },
1118
- {
1119
- type: "Button",
1120
- props: {
1121
- text: "\u5728\u9762\u677F\u4E2D\u6253\u5F00",
1122
- variant: "default",
1123
- size: "small",
1124
- className: "pactor-chat-artifact-card__open"
1125
- },
1126
- events: {
1127
- onClick: [
1128
- {
1129
- action: "chat.openArtifact",
1130
- params: { artifact }
1131
- }
1132
- ]
1133
- }
1134
- }
1135
- ]
1136
- }
1137
- ]
1138
- }
1139
- };
1140
- }
1141
-
1142
- // src/view/chrome/ChromeSlot.tsx
1143
- import { useRenderer } from "@pactor-app/runtime";
1144
- import { Component } from "react";
1182
+ import { Icon } from "@pactor-app/ui/components";
1183
+ import { useState as useState5 } from "react";
1145
1184
 
1146
1185
  // src/view/chrome/actions.ts
1147
1186
  var handlers = {};
@@ -1221,6 +1260,12 @@ function ensureChatChromeActions(actions) {
1221
1260
  function invokeChatPanelClose() {
1222
1261
  handlers.panelClose?.();
1223
1262
  }
1263
+ function invokeChatOpenArtifact(artifact) {
1264
+ handlers.openArtifact?.(artifact);
1265
+ }
1266
+ function invokeChatOpenArtifactList() {
1267
+ handlers.openArtifactList?.();
1268
+ }
1224
1269
  function invokeChatPanelToggleList() {
1225
1270
  handlers.panelToggleList?.();
1226
1271
  }
@@ -1228,8 +1273,112 @@ function invokeChatPanelDownload() {
1228
1273
  handlers.panelDownload?.();
1229
1274
  }
1230
1275
 
1276
+ // src/view/chrome/artifact-card.tsx
1277
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
1278
+ function artifactCardMeta(artifact) {
1279
+ const ext = resolveArtifactFileType(artifact);
1280
+ const typeLabel = (ext ?? artifact.kind).toUpperCase();
1281
+ const sizeLabel = formatArtifactSize(artifact.meta?.["size"]);
1282
+ return [sizeLabel, typeLabel].filter(Boolean).join(" \xB7 ");
1283
+ }
1284
+ function ChatArtifactCard({
1285
+ artifact
1286
+ }) {
1287
+ const icon = resolveArtifactIcon(artifact);
1288
+ const meta = artifactCardMeta(artifact);
1289
+ return /* @__PURE__ */ jsxs(
1290
+ "button",
1291
+ {
1292
+ type: "button",
1293
+ className: `pactor-chat-artifact-card pactor-chat-artifact-card--${icon.tone}`,
1294
+ "data-artifact-kind": artifact.kind,
1295
+ "aria-label": `\u5728\u9762\u677F\u4E2D\u6253\u5F00\uFF1A${artifact.title}`,
1296
+ title: `\u5728\u9762\u677F\u4E2D\u6253\u5F00\uFF1A${artifact.title}`,
1297
+ onClick: () => invokeChatOpenArtifact(artifact),
1298
+ children: [
1299
+ /* @__PURE__ */ jsx2("span", { className: "pactor-chat-artifact-card__icon", children: /* @__PURE__ */ jsx2(Icon, { name: icon.name, size: 20 }) }),
1300
+ /* @__PURE__ */ jsxs("span", { className: "pactor-chat-artifact-card__text", children: [
1301
+ /* @__PURE__ */ jsx2("span", { className: "pactor-chat-artifact-card__title", children: artifact.title }),
1302
+ meta ? /* @__PURE__ */ jsx2("span", { className: "pactor-chat-artifact-card__meta", children: meta }) : null
1303
+ ] }),
1304
+ /* @__PURE__ */ jsx2("span", { className: "pactor-chat-artifact-card__arrow", children: /* @__PURE__ */ jsx2(Icon, { name: "arrow-up-right", size: 14 }) })
1305
+ ]
1306
+ }
1307
+ );
1308
+ }
1309
+ var ARTIFACT_CARD_INTERNAL_COMPONENTS = {
1310
+ ChatArtifactCard,
1311
+ ChatArtifactCardGroup
1312
+ };
1313
+ var ARTIFACT_CARD_GROUP_LIMIT = 4;
1314
+ function ChatArtifactCardGroup({
1315
+ artifacts
1316
+ }) {
1317
+ const [expanded, setExpanded] = useState5(false);
1318
+ const overflow = artifacts.length > ARTIFACT_CARD_GROUP_LIMIT;
1319
+ const visible = overflow && !expanded ? artifacts.slice(0, ARTIFACT_CARD_GROUP_LIMIT) : artifacts;
1320
+ return /* @__PURE__ */ jsxs("div", { className: "pactor-chat-artifact-group", children: [
1321
+ visible.map((artifact) => /* @__PURE__ */ jsx2(ChatArtifactCard, { artifact }, artifact.id)),
1322
+ overflow ? /* @__PURE__ */ jsxs("div", { className: "pactor-chat-artifact-group__footer", children: [
1323
+ /* @__PURE__ */ jsxs(
1324
+ "button",
1325
+ {
1326
+ type: "button",
1327
+ className: "pactor-chat-artifact-group__toggle",
1328
+ "aria-expanded": expanded,
1329
+ onClick: () => setExpanded((value) => !value),
1330
+ children: [
1331
+ /* @__PURE__ */ jsx2(
1332
+ Icon,
1333
+ {
1334
+ name: expanded ? "chevron-up" : "chevron-down",
1335
+ size: 12
1336
+ }
1337
+ ),
1338
+ expanded ? "\u6536\u8D77" : "\u5C55\u5F00"
1339
+ ]
1340
+ }
1341
+ ),
1342
+ /* @__PURE__ */ jsxs(
1343
+ "button",
1344
+ {
1345
+ type: "button",
1346
+ className: "pactor-chat-artifact-group__all",
1347
+ onClick: () => invokeChatOpenArtifactList(),
1348
+ children: [
1349
+ "\u67E5\u770B\u6240\u6709\u4EA7\u7269(",
1350
+ artifacts.length,
1351
+ ")",
1352
+ /* @__PURE__ */ jsx2(Icon, { name: "chevron-right", size: 12 })
1353
+ ]
1354
+ }
1355
+ )
1356
+ ] }) : null
1357
+ ] });
1358
+ }
1359
+ function buildArtifactCardFragment(artifact) {
1360
+ return {
1361
+ requires: ["ChatArtifactCard"],
1362
+ node: {
1363
+ type: "ChatArtifactCard",
1364
+ props: { artifact }
1365
+ }
1366
+ };
1367
+ }
1368
+ function buildArtifactCardGroupFragment(artifacts) {
1369
+ return {
1370
+ requires: ["ChatArtifactCardGroup"],
1371
+ node: {
1372
+ type: "ChatArtifactCardGroup",
1373
+ props: { artifacts }
1374
+ }
1375
+ };
1376
+ }
1377
+
1231
1378
  // src/view/chrome/ChromeSlot.tsx
1232
- import { Fragment, jsx as jsx2 } from "react/jsx-runtime";
1379
+ import { useRenderer } from "@pactor-app/runtime";
1380
+ import { Component } from "react";
1381
+ import { Fragment, jsx as jsx3 } from "react/jsx-runtime";
1233
1382
  var warnedMissing = /* @__PURE__ */ new Set();
1234
1383
  function warnMissingOnce(key, detail) {
1235
1384
  if (!warnedMissing.has(key)) {
@@ -1247,7 +1396,7 @@ function ChromeSlotInner({
1247
1396
  try {
1248
1397
  renderer = useRenderer();
1249
1398
  } catch {
1250
- return /* @__PURE__ */ jsx2(Fragment, { children: fallback });
1399
+ return /* @__PURE__ */ jsx3(Fragment, { children: fallback });
1251
1400
  }
1252
1401
  ensureChatChromeActions(renderer.context.actions);
1253
1402
  if (components) {
@@ -1258,7 +1407,7 @@ function ChromeSlotInner({
1258
1407
  `conflict:${name}`,
1259
1408
  `[@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`
1260
1409
  );
1261
- return /* @__PURE__ */ jsx2(Fragment, { children: fallback });
1410
+ return /* @__PURE__ */ jsx3(Fragment, { children: fallback });
1262
1411
  }
1263
1412
  if (existing === void 0) {
1264
1413
  renderer.context.components.register(
@@ -1276,10 +1425,10 @@ function ChromeSlotInner({
1276
1425
  `${fragment.node.type}:${missing.join(",")}`,
1277
1426
  `[@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`
1278
1427
  );
1279
- return /* @__PURE__ */ jsx2(Fragment, { children: fallback });
1428
+ return /* @__PURE__ */ jsx3(Fragment, { children: fallback });
1280
1429
  }
1281
- const rendered = /* @__PURE__ */ jsx2("div", { className: "pactor-chat-chrome", children: renderer.renderChildren([fragment.node]) });
1282
- return wrap ? /* @__PURE__ */ jsx2(Fragment, { children: wrap(rendered) }) : rendered;
1430
+ const rendered = /* @__PURE__ */ jsx3("div", { className: "pactor-chat-chrome", children: renderer.renderChildren([fragment.node]) });
1431
+ return wrap ? /* @__PURE__ */ jsx3(Fragment, { children: wrap(rendered) }) : rendered;
1283
1432
  }
1284
1433
  var ChromeSlotGuard = class extends Component {
1285
1434
  constructor() {
@@ -1294,7 +1443,7 @@ var ChromeSlotGuard = class extends Component {
1294
1443
  }
1295
1444
  };
1296
1445
  function ChromeSlot(props) {
1297
- return /* @__PURE__ */ jsx2(ChromeSlotGuard, { fallback: props.fallback, children: /* @__PURE__ */ jsx2(ChromeSlotInner, { ...props }) });
1446
+ return /* @__PURE__ */ jsx3(ChromeSlotGuard, { fallback: props.fallback, children: /* @__PURE__ */ jsx3(ChromeSlotInner, { ...props }) });
1298
1447
  }
1299
1448
 
1300
1449
  // src/view/chrome/feedback.tsx
@@ -1318,9 +1467,9 @@ function buildStatusFragment(text) {
1318
1467
  }
1319
1468
 
1320
1469
  // src/view/PartRenderer.tsx
1321
- import { Fragment as Fragment2, jsx as jsx3, jsxs } from "react/jsx-runtime";
1470
+ import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
1322
1471
  function ChatDenied({ deniedType }) {
1323
- return /* @__PURE__ */ jsxs("div", { className: "pactor-chat-denied", "data-pactor-chat-denied": deniedType, children: [
1472
+ return /* @__PURE__ */ jsxs2("div", { className: "pactor-chat-denied", "data-pactor-chat-denied": deniedType, children: [
1324
1473
  "\u8BE5\u7EC4\u4EF6\u4E0D\u5141\u8BB8\u5728 Chat \u4E2D\u4F7F\u7528",
1325
1474
  deniedType ? `\uFF1A${deniedType}` : ""
1326
1475
  ] });
@@ -1331,89 +1480,68 @@ function ChatDslNode({
1331
1480
  }) {
1332
1481
  const renderer = useRenderer2();
1333
1482
  const extraScope = scope ? buildChatScope(scope) : void 0;
1334
- return /* @__PURE__ */ jsx3(Fragment2, { children: renderer.renderChildren([node], extraScope) });
1483
+ return /* @__PURE__ */ jsx4(Fragment2, { children: renderer.renderChildren([node], extraScope) });
1335
1484
  }
1336
1485
  function SmoothText({ content, streaming }) {
1337
1486
  const shown = useSmoothStreamText(content, streaming);
1338
- return /* @__PURE__ */ jsx3("div", { className: "pactor-chat-text", children: shown });
1487
+ return /* @__PURE__ */ jsx4("div", { className: "pactor-chat-text", children: shown });
1339
1488
  }
1340
1489
  function SmoothMarkdown({ content, streaming }) {
1341
1490
  const shown = useSmoothStreamText(content, streaming);
1342
1491
  const throttled = useThrottledValue(shown, 100, streaming);
1343
- return /* @__PURE__ */ jsx3(MarkdownRenderer, { content: throttled });
1492
+ return /* @__PURE__ */ jsx4(MarkdownRenderer, { content: throttled });
1344
1493
  }
1345
- function PartRenderer({ part, runtime, scope, streaming = false, onOpenArtifact }) {
1494
+ function PartRenderer({ part, runtime, scope, streaming = false }) {
1346
1495
  switch (part.type) {
1347
1496
  case "text":
1348
- return /* @__PURE__ */ jsx3(SmoothText, { content: part.content, streaming });
1497
+ return /* @__PURE__ */ jsx4(SmoothText, { content: part.content, streaming });
1349
1498
  case "markdown":
1350
- return /* @__PURE__ */ jsx3(SmoothMarkdown, { content: part.content, streaming });
1499
+ return /* @__PURE__ */ jsx4(SmoothMarkdown, { content: part.content, streaming });
1351
1500
  case "thinking":
1352
1501
  case "tool-call":
1353
1502
  case "tool-result":
1354
1503
  return null;
1355
1504
  case "dsl": {
1356
1505
  if (!part.schema || !runtime) {
1357
- return /* @__PURE__ */ jsx3(
1506
+ return /* @__PURE__ */ jsx4(
1358
1507
  ChromeSlot,
1359
1508
  {
1360
1509
  fragment: buildStatusFragment(
1361
1510
  part.schema ? "DSL \u6E32\u67D3\u4E0D\u53EF\u7528\uFF08\u672A\u6CE8\u5165 Safe Registry\uFF09" : "\u5185\u5BB9\u751F\u6210\u4E2D\u2026"
1362
1511
  ),
1363
- fallback: /* @__PURE__ */ jsx3("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" })
1512
+ fallback: /* @__PURE__ */ jsx4("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" })
1364
1513
  }
1365
1514
  );
1366
1515
  }
1367
1516
  const guarded = guardChatDsl(part.schema, runtime.context.components);
1368
- return /* @__PURE__ */ jsx3("div", { className: "pactor-chat-dsl", children: /* @__PURE__ */ jsx3(DslRenderer, { context: runtime.context, engine: runtime.engine, children: /* @__PURE__ */ jsx3(ChatDslNode, { node: guarded, scope }) }) });
1517
+ return /* @__PURE__ */ jsx4("div", { className: "pactor-chat-dsl", children: /* @__PURE__ */ jsx4(DslRenderer, { context: runtime.context, engine: runtime.engine, children: /* @__PURE__ */ jsx4(ChatDslNode, { node: guarded, scope }) }) });
1369
1518
  }
1370
1519
  case "error":
1371
- return /* @__PURE__ */ jsx3(
1520
+ return /* @__PURE__ */ jsx4(
1372
1521
  ChromeSlot,
1373
1522
  {
1374
1523
  fragment: buildErrorFragment(part.message),
1375
- fallback: /* @__PURE__ */ jsxs("div", { className: "pactor-chat-error", role: "alert", children: [
1376
- /* @__PURE__ */ jsx3(Icon, { name: "error", size: 14 }),
1377
- /* @__PURE__ */ jsx3("span", { children: part.message })
1524
+ fallback: /* @__PURE__ */ jsxs2("div", { className: "pactor-chat-error", role: "alert", children: [
1525
+ /* @__PURE__ */ jsx4(Icon2, { name: "error", size: 14 }),
1526
+ /* @__PURE__ */ jsx4("span", { children: part.message })
1378
1527
  ] })
1379
1528
  }
1380
1529
  );
1381
1530
  case "status":
1382
- return /* @__PURE__ */ jsx3(
1531
+ return /* @__PURE__ */ jsx4(
1383
1532
  ChromeSlot,
1384
1533
  {
1385
1534
  fragment: buildStatusFragment(part.text),
1386
- fallback: /* @__PURE__ */ jsx3("div", { className: "pactor-chat-status", children: part.text })
1535
+ fallback: /* @__PURE__ */ jsx4("div", { className: "pactor-chat-status", children: part.text })
1387
1536
  }
1388
1537
  );
1389
1538
  case "artifact":
1390
- return /* @__PURE__ */ jsx3(
1539
+ return /* @__PURE__ */ jsx4(
1391
1540
  ChromeSlot,
1392
1541
  {
1393
1542
  fragment: buildArtifactCardFragment(part.artifact),
1394
- fallback: /* @__PURE__ */ jsxs(
1395
- "div",
1396
- {
1397
- className: "pactor-chat-artifact-card",
1398
- "data-artifact-kind": part.artifact.kind,
1399
- children: [
1400
- /* @__PURE__ */ jsx3("span", { className: "pactor-chat-artifact-card__title", children: part.artifact.title }),
1401
- /* @__PURE__ */ jsx3("span", { className: "pactor-chat-artifact-card__kind", children: part.artifact.kind }),
1402
- /* @__PURE__ */ jsxs(
1403
- "button",
1404
- {
1405
- type: "button",
1406
- className: "pactor-chat-artifact-card__open",
1407
- onClick: () => onOpenArtifact?.(part.artifact),
1408
- children: [
1409
- /* @__PURE__ */ jsx3(Icon, { name: "panel-right-open", size: 13, strokeWidth: 1.7 }),
1410
- "\u5728\u9762\u677F\u4E2D\u6253\u5F00"
1411
- ]
1412
- }
1413
- )
1414
- ]
1415
- }
1416
- )
1543
+ components: ARTIFACT_CARD_INTERNAL_COMPONENTS,
1544
+ fallback: /* @__PURE__ */ jsx4(ChatArtifactCard, { artifact: part.artifact })
1417
1545
  }
1418
1546
  );
1419
1547
  default:
@@ -1422,10 +1550,17 @@ function PartRenderer({ part, runtime, scope, streaming = false, onOpenArtifact
1422
1550
  }
1423
1551
 
1424
1552
  // src/view/chrome/panel-header.tsx
1425
- import { Icon as Icon2 } from "@pactor-app/ui/components";
1426
- import { jsx as jsx4 } from "react/jsx-runtime";
1553
+ import { DropdownMenu, Icon as Icon3 } from "@pactor-app/ui/components";
1554
+ import { createContext, useContext } from "react";
1555
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
1556
+ var ChatPanelContext = createContext(
1557
+ null
1558
+ );
1559
+ function artifactIconName(artifact) {
1560
+ return artifact ? resolveArtifactIconName(artifact) : "file";
1561
+ }
1427
1562
  function ChatPanelCloseButton() {
1428
- return /* @__PURE__ */ jsx4(
1563
+ return /* @__PURE__ */ jsx5(
1429
1564
  "button",
1430
1565
  {
1431
1566
  type: "button",
@@ -1433,17 +1568,16 @@ function ChatPanelCloseButton() {
1433
1568
  title: "\u5173\u95ED\u9762\u677F",
1434
1569
  "aria-label": "\u5173\u95ED\u9762\u677F",
1435
1570
  onClick: () => invokeChatPanelClose(),
1436
- children: /* @__PURE__ */ jsx4(Icon2, { name: "x", size: 16 })
1571
+ children: /* @__PURE__ */ jsx5(Icon3, { name: "x", size: 16 })
1437
1572
  }
1438
1573
  );
1439
1574
  }
1440
- var PANEL_HEADER_INTERNAL_COMPONENTS = {
1441
- ChatPanelCloseButton,
1442
- ChatPanelDownloadButton,
1443
- ChatPanelListButton
1444
- };
1445
1575
  function ChatPanelListButton() {
1446
- return /* @__PURE__ */ jsx4(
1576
+ const ctx = useContext(ChatPanelContext);
1577
+ if (ctx?.view === "list") {
1578
+ return null;
1579
+ }
1580
+ return /* @__PURE__ */ jsx5(
1447
1581
  "button",
1448
1582
  {
1449
1583
  type: "button",
@@ -1451,12 +1585,12 @@ function ChatPanelListButton() {
1451
1585
  title: "\u4EA7\u7269\u76EE\u5F55",
1452
1586
  "aria-label": "\u4EA7\u7269\u76EE\u5F55",
1453
1587
  onClick: () => invokeChatPanelToggleList(),
1454
- children: /* @__PURE__ */ jsx4(Icon2, { name: "arrow-left", size: 16 })
1588
+ children: /* @__PURE__ */ jsx5(Icon3, { name: "arrow-left", size: 16 })
1455
1589
  }
1456
1590
  );
1457
1591
  }
1458
1592
  function ChatPanelDownloadButton() {
1459
- return /* @__PURE__ */ jsx4(
1593
+ return /* @__PURE__ */ jsx5(
1460
1594
  "button",
1461
1595
  {
1462
1596
  type: "button",
@@ -1464,10 +1598,58 @@ function ChatPanelDownloadButton() {
1464
1598
  title: "\u4E0B\u8F7D\u4EA7\u7269",
1465
1599
  "aria-label": "\u4E0B\u8F7D\u4EA7\u7269",
1466
1600
  onClick: () => invokeChatPanelDownload(),
1467
- children: /* @__PURE__ */ jsx4(Icon2, { name: "download", size: 16 })
1601
+ children: /* @__PURE__ */ jsx5(Icon3, { name: "download", size: 16 })
1602
+ }
1603
+ );
1604
+ }
1605
+ function ChatPanelArtifactMenu() {
1606
+ const ctx = useContext(ChatPanelContext);
1607
+ if (!ctx || ctx.artifacts.length === 0) {
1608
+ return null;
1609
+ }
1610
+ const active = ctx.artifacts.find((item) => item.id === ctx.activeId);
1611
+ const inList = ctx.view === "list";
1612
+ return /* @__PURE__ */ jsx5(
1613
+ DropdownMenu,
1614
+ {
1615
+ items: ctx.artifacts.map((item) => ({
1616
+ label: item.title,
1617
+ value: item.id,
1618
+ icon: artifactIconName(item)
1619
+ })),
1620
+ onSelect: (value) => {
1621
+ const target = ctx.artifacts.find((item) => item.id === value);
1622
+ if (target) {
1623
+ ctx.onSelectArtifact?.(target);
1624
+ }
1625
+ },
1626
+ children: /* @__PURE__ */ jsxs3(
1627
+ "span",
1628
+ {
1629
+ className: "pactor-chat-inspector__menu-trigger",
1630
+ "data-view": ctx.view,
1631
+ children: [
1632
+ /* @__PURE__ */ jsx5(
1633
+ Icon3,
1634
+ {
1635
+ name: inList ? "folder" : artifactIconName(active),
1636
+ size: 13
1637
+ }
1638
+ ),
1639
+ /* @__PURE__ */ jsx5("span", { className: "pactor-chat-inspector__title", children: inList ? "\u4EA7\u7269\u76EE\u5F55" : active?.title ?? "\u4EA7\u51FA\u7269" }),
1640
+ /* @__PURE__ */ jsx5(Icon3, { name: "chevron-down", size: 12 })
1641
+ ]
1642
+ }
1643
+ )
1468
1644
  }
1469
1645
  );
1470
1646
  }
1647
+ var PANEL_HEADER_INTERNAL_COMPONENTS = {
1648
+ ChatPanelCloseButton,
1649
+ ChatPanelDownloadButton,
1650
+ ChatPanelListButton,
1651
+ ChatPanelArtifactMenu
1652
+ };
1471
1653
  function buildPanelHeaderFragment(props) {
1472
1654
  return {
1473
1655
  requires: [
@@ -1476,7 +1658,8 @@ function buildPanelHeaderFragment(props) {
1476
1658
  "Badge",
1477
1659
  "ChatPanelCloseButton",
1478
1660
  "ChatPanelDownloadButton",
1479
- "ChatPanelListButton"
1661
+ "ChatPanelListButton",
1662
+ "ChatPanelArtifactMenu"
1480
1663
  ],
1481
1664
  node: {
1482
1665
  type: "Flex",
@@ -1492,7 +1675,7 @@ function buildPanelHeaderFragment(props) {
1492
1675
  props: { align: "center", gap: "small" },
1493
1676
  children: [
1494
1677
  ...props.showListButton ? [{ type: "ChatPanelListButton" }] : [],
1495
- {
1678
+ props.showMenu ? { type: "ChatPanelArtifactMenu" } : {
1496
1679
  type: "Text",
1497
1680
  props: {
1498
1681
  text: props.title,
@@ -1500,14 +1683,16 @@ function buildPanelHeaderFragment(props) {
1500
1683
  className: "pactor-chat-inspector__title"
1501
1684
  }
1502
1685
  },
1503
- {
1504
- type: "Badge",
1505
- props: {
1506
- text: props.kind,
1507
- variant: "secondary",
1508
- className: "pactor-chat-inspector__kind"
1686
+ ...props.view === "list" ? [] : [
1687
+ {
1688
+ type: "Badge",
1689
+ props: {
1690
+ text: props.kind,
1691
+ variant: "secondary",
1692
+ className: "pactor-chat-inspector__kind"
1693
+ }
1509
1694
  }
1510
- }
1695
+ ]
1511
1696
  ]
1512
1697
  },
1513
1698
  {
@@ -1524,7 +1709,7 @@ function buildPanelHeaderFragment(props) {
1524
1709
  }
1525
1710
 
1526
1711
  // src/view/ArtifactPanel.tsx
1527
- import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
1712
+ import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
1528
1713
  function useArtifactRuntime(safeRegistry, user) {
1529
1714
  return useMemo(() => {
1530
1715
  if (!safeRegistry) {
@@ -1550,12 +1735,12 @@ var ArtifactDslGuard = class extends Component2 {
1550
1735
  console.warn("[@pactor-app/chat] DSL \u4EA7\u51FA\u7269\u6E32\u67D3\u5931\u8D25\uFF0C\u5DF2\u964D\u7EA7\u5C55\u793A", error);
1551
1736
  }
1552
1737
  render() {
1553
- return this.state.failed ? /* @__PURE__ */ jsx5("div", { className: "pactor-chat-denied", children: "DSL \u4EA7\u51FA\u7269\u6E32\u67D3\u5931\u8D25\uFF0C\u5DF2\u964D\u7EA7\u5C55\u793A" }) : this.props.children;
1738
+ return this.state.failed ? /* @__PURE__ */ jsx6("div", { className: "pactor-chat-denied", children: "DSL \u4EA7\u51FA\u7269\u6E32\u67D3\u5931\u8D25\uFF0C\u5DF2\u964D\u7EA7\u5C55\u793A" }) : this.props.children;
1554
1739
  }
1555
1740
  };
1556
1741
  function ArtifactDslNode({ node }) {
1557
1742
  const { renderChildren } = useRenderer3();
1558
- return /* @__PURE__ */ jsx5(Fragment3, { children: renderChildren([node]) });
1743
+ return /* @__PURE__ */ jsx6(Fragment3, { children: renderChildren([node]) });
1559
1744
  }
1560
1745
  function ArtifactDslContent({
1561
1746
  content,
@@ -1563,14 +1748,13 @@ function ArtifactDslContent({
1563
1748
  }) {
1564
1749
  const node = typeof content === "object" && content !== null && !Array.isArray(content) && typeof content.type === "string" ? content : void 0;
1565
1750
  if (!node || !runtime) {
1566
- return /* @__PURE__ */ jsx5("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" });
1751
+ return /* @__PURE__ */ jsx6("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" });
1567
1752
  }
1568
1753
  const guarded = guardChatDsl(node, runtime.context.components);
1569
- return /* @__PURE__ */ jsx5(DslRenderer2, { context: runtime.context, engine: runtime.engine, children: /* @__PURE__ */ jsx5(ArtifactDslGuard, { children: /* @__PURE__ */ jsx5(ArtifactDslNode, { node: guarded }) }) });
1754
+ return /* @__PURE__ */ jsx6(DslRenderer2, { context: runtime.context, engine: runtime.engine, children: /* @__PURE__ */ jsx6(ArtifactDslGuard, { children: /* @__PURE__ */ jsx6(ArtifactDslNode, { node: guarded }) }) });
1570
1755
  }
1571
- function ArtifactKindIcon({ kind }) {
1572
- const name = kind === "code" ? "code" : kind === "dsl" ? "layout-grid" : "file-text";
1573
- return /* @__PURE__ */ jsx5(Icon3, { name, size: 13 });
1756
+ function ArtifactKindIcon({ artifact }) {
1757
+ return /* @__PURE__ */ jsx6(Icon4, { name: resolveArtifactIconName(artifact), size: 13 });
1574
1758
  }
1575
1759
  function buildArtifactTree(artifacts) {
1576
1760
  const root = { name: "", path: "", children: [] };
@@ -1612,7 +1796,7 @@ function ArtifactListView({
1612
1796
  activeId,
1613
1797
  onSelect
1614
1798
  }) {
1615
- return /* @__PURE__ */ jsx5("ul", { className: "pactor-chat-inspector__list", children: nodes.map((node) => /* @__PURE__ */ jsx5(
1799
+ return /* @__PURE__ */ jsx6("ul", { className: "pactor-chat-inspector__list", children: nodes.map((node) => /* @__PURE__ */ jsx6(
1616
1800
  ArtifactTreeRow,
1617
1801
  {
1618
1802
  node,
@@ -1627,9 +1811,9 @@ function ArtifactTreeRow({
1627
1811
  activeId,
1628
1812
  onSelect
1629
1813
  }) {
1630
- const [open, setOpen] = useState5(true);
1814
+ const [open, setOpen] = useState6(true);
1631
1815
  if (node.artifact) {
1632
- return /* @__PURE__ */ jsx5("li", { children: /* @__PURE__ */ jsxs2(
1816
+ return /* @__PURE__ */ jsx6("li", { children: /* @__PURE__ */ jsxs4(
1633
1817
  "button",
1634
1818
  {
1635
1819
  type: "button",
@@ -1637,15 +1821,15 @@ function ArtifactTreeRow({
1637
1821
  "data-active": node.artifact.id === activeId,
1638
1822
  onClick: () => onSelect?.(node.artifact),
1639
1823
  children: [
1640
- /* @__PURE__ */ jsx5(ArtifactKindIcon, { kind: node.artifact.kind }),
1641
- /* @__PURE__ */ jsx5("span", { className: "pactor-chat-inspector__list-item-title", children: node.artifact.title }),
1642
- /* @__PURE__ */ jsx5("span", { className: "pactor-chat-inspector__kind", children: node.artifact.kind })
1824
+ /* @__PURE__ */ jsx6(ArtifactKindIcon, { artifact: node.artifact }),
1825
+ /* @__PURE__ */ jsx6("span", { className: "pactor-chat-inspector__list-item-title", children: node.artifact.title }),
1826
+ /* @__PURE__ */ jsx6("span", { className: "pactor-chat-inspector__kind", children: node.artifact.kind })
1643
1827
  ]
1644
1828
  }
1645
1829
  ) });
1646
1830
  }
1647
- return /* @__PURE__ */ jsxs2("li", { children: [
1648
- /* @__PURE__ */ jsxs2(
1831
+ return /* @__PURE__ */ jsxs4("li", { children: [
1832
+ /* @__PURE__ */ jsxs4(
1649
1833
  "button",
1650
1834
  {
1651
1835
  type: "button",
@@ -1654,13 +1838,13 @@ function ArtifactTreeRow({
1654
1838
  "data-open": open,
1655
1839
  onClick: () => setOpen((value) => !value),
1656
1840
  children: [
1657
- /* @__PURE__ */ jsx5("span", { className: "pactor-chat-trace__chevron", children: /* @__PURE__ */ jsx5(Icon3, { name: "chevron-right", size: 12 }) }),
1658
- /* @__PURE__ */ jsx5(Icon3, { name: "folder", size: 13 }),
1659
- /* @__PURE__ */ jsx5("span", { children: node.name })
1841
+ /* @__PURE__ */ jsx6("span", { className: "pactor-chat-trace__chevron", children: /* @__PURE__ */ jsx6(Icon4, { name: "chevron-right", size: 12 }) }),
1842
+ /* @__PURE__ */ jsx6(Icon4, { name: "folder", size: 13 }),
1843
+ /* @__PURE__ */ jsx6("span", { children: node.name })
1660
1844
  ]
1661
1845
  }
1662
1846
  ),
1663
- open && /* @__PURE__ */ jsx5("div", { className: "pactor-chat-inspector__list-children", children: /* @__PURE__ */ jsx5(
1847
+ open && /* @__PURE__ */ jsx6("div", { className: "pactor-chat-inspector__list-children", children: /* @__PURE__ */ jsx6(
1664
1848
  ArtifactListView,
1665
1849
  {
1666
1850
  nodes: node.children,
@@ -1673,7 +1857,7 @@ function ArtifactTreeRow({
1673
1857
  function ArtifactImageContent({ artifact }) {
1674
1858
  const raw = String(artifact.content).trim();
1675
1859
  const src = raw.startsWith("<svg") || raw.startsWith("<?xml") ? `data:image/svg+xml;utf8,${encodeURIComponent(raw)}` : raw;
1676
- return /* @__PURE__ */ jsx5("div", { className: "pactor-chat-inspector__image", children: /* @__PURE__ */ jsx5("img", { src, alt: artifact.title }) });
1860
+ return /* @__PURE__ */ jsx6("div", { className: "pactor-chat-inspector__image", children: /* @__PURE__ */ jsx6("img", { src, alt: artifact.title }) });
1677
1861
  }
1678
1862
  function ArtifactContent({
1679
1863
  artifact,
@@ -1683,23 +1867,23 @@ function ArtifactContent({
1683
1867
  const ext = resolveArtifactFileType(artifact);
1684
1868
  const custom = (ext ? viewers?.[ext] : void 0) ?? viewers?.[artifact.kind];
1685
1869
  if (custom) {
1686
- return /* @__PURE__ */ jsx5(Fragment3, { children: custom(artifact) });
1870
+ return /* @__PURE__ */ jsx6(Fragment3, { children: custom(artifact) });
1687
1871
  }
1688
1872
  if (isImageArtifact(artifact)) {
1689
- return /* @__PURE__ */ jsx5(ArtifactImageContent, { artifact });
1873
+ return /* @__PURE__ */ jsx6(ArtifactImageContent, { artifact });
1690
1874
  }
1691
1875
  switch (artifact.kind) {
1692
1876
  case "markdown":
1693
- return /* @__PURE__ */ jsx5(MarkdownRenderer2, { content: String(artifact.content) });
1877
+ return /* @__PURE__ */ jsx6(MarkdownRenderer2, { content: String(artifact.content) });
1694
1878
  case "code":
1695
- return /* @__PURE__ */ jsxs2("div", { className: "pactor-chat-inspector__code", children: [
1696
- artifact.language ? /* @__PURE__ */ jsx5("span", { className: "pactor-chat-inspector__code-lang", children: artifact.language }) : null,
1697
- /* @__PURE__ */ jsx5("pre", { children: /* @__PURE__ */ jsx5("code", { children: String(artifact.content) }) })
1879
+ return /* @__PURE__ */ jsxs4("div", { className: "pactor-chat-inspector__code", children: [
1880
+ artifact.language ? /* @__PURE__ */ jsx6("span", { className: "pactor-chat-inspector__code-lang", children: artifact.language }) : null,
1881
+ /* @__PURE__ */ jsx6("pre", { children: /* @__PURE__ */ jsx6("code", { children: String(artifact.content) }) })
1698
1882
  ] });
1699
1883
  case "text":
1700
- return /* @__PURE__ */ jsx5("pre", { className: "pactor-chat-inspector__text", children: String(artifact.content) });
1884
+ return /* @__PURE__ */ jsx6("pre", { className: "pactor-chat-inspector__text", children: String(artifact.content) });
1701
1885
  case "dsl":
1702
- return /* @__PURE__ */ jsx5(ArtifactDslContent, { content: artifact.content, runtime });
1886
+ return /* @__PURE__ */ jsx6(ArtifactDslContent, { content: artifact.content, runtime });
1703
1887
  default:
1704
1888
  return null;
1705
1889
  }
@@ -1709,6 +1893,8 @@ function ArtifactPanel({
1709
1893
  artifacts,
1710
1894
  activeArtifactId,
1711
1895
  onSelectArtifact,
1896
+ viewRequest,
1897
+ onViewRequestConsumed,
1712
1898
  inspector,
1713
1899
  onClose,
1714
1900
  safeRegistry,
@@ -1717,12 +1903,19 @@ function ArtifactPanel({
1717
1903
  className
1718
1904
  }) {
1719
1905
  const runtime = useArtifactRuntime(safeRegistry, user);
1720
- const [view, setView] = useState5("content");
1906
+ const [view, setView] = useState6("content");
1721
1907
  const activeId = activeArtifactId ?? artifact?.id;
1722
1908
  useEffect3(() => {
1723
1909
  setView("content");
1724
1910
  }, [activeId]);
1911
+ useEffect3(() => {
1912
+ if (viewRequest != null) {
1913
+ setView("list");
1914
+ onViewRequestConsumed?.();
1915
+ }
1916
+ }, [viewRequest]);
1725
1917
  const showListButton = artifacts !== void 0 && artifacts.length > 0;
1918
+ const showMenu = artifacts !== void 0 && artifacts.length > 0;
1726
1919
  const toggleListRef = useRef4(() => {
1727
1920
  });
1728
1921
  toggleListRef.current = () => setView((value) => value === "list" ? "content" : "list");
@@ -1743,23 +1936,23 @@ function ArtifactPanel({
1743
1936
  });
1744
1937
  }, []);
1745
1938
  const panelRef = useRef4(null);
1746
- const [width, setWidth] = useState5(null);
1939
+ const [width, setWidth] = useState6(null);
1747
1940
  const handleResizeStart = (event) => {
1748
1941
  event.preventDefault();
1749
1942
  const panel = panelRef.current;
1750
1943
  if (!panel) {
1751
1944
  return;
1752
1945
  }
1753
- const hostRect = panel.parentElement?.getBoundingClientRect();
1754
- const hostWidth = hostRect !== void 0 && hostRect.width > 0 ? hostRect.width : window.innerWidth;
1755
- const maxWidth = hostWidth * 0.7;
1756
1946
  const startWidth = panel.getBoundingClientRect().width;
1757
1947
  const startX = event.clientX;
1758
1948
  const prevUserSelect = document.body.style.userSelect;
1759
1949
  document.body.style.userSelect = "none";
1760
1950
  const onMove = (moveEvent) => {
1951
+ const hostRect = panel.parentElement?.getBoundingClientRect();
1952
+ const hostWidth = hostRect !== void 0 && hostRect.width > 0 ? hostRect.width : window.innerWidth;
1953
+ const maxWidth = hostWidth * 2 / 3;
1761
1954
  const next = startWidth + (startX - moveEvent.clientX);
1762
- setWidth(Math.round(Math.min(Math.max(next, 320), maxWidth)));
1955
+ setWidth(Math.round(Math.min(Math.max(next, 480), maxWidth)));
1763
1956
  };
1764
1957
  const onUp = () => {
1765
1958
  document.body.style.userSelect = prevUserSelect;
@@ -1769,126 +1962,93 @@ function ArtifactPanel({
1769
1962
  document.addEventListener("pointermove", onMove);
1770
1963
  document.addEventListener("pointerup", onUp);
1771
1964
  };
1772
- return /* @__PURE__ */ jsxs2(
1773
- "aside",
1965
+ return /* @__PURE__ */ jsx6(
1966
+ ChatPanelContext.Provider,
1774
1967
  {
1775
- ref: panelRef,
1776
- className: `pactor-chat-inspector${className ? ` ${className}` : ""}`,
1777
- "data-kind": artifact?.kind,
1778
- style: width !== null ? { width: `${width}px` } : void 0,
1779
- children: [
1780
- /* @__PURE__ */ jsx5(
1781
- "div",
1782
- {
1783
- className: "pactor-chat-inspector__resize",
1784
- role: "separator",
1785
- "aria-orientation": "vertical",
1786
- "aria-label": "\u62D6\u52A8\u8C03\u6574\u9762\u677F\u5BBD\u5EA6",
1787
- onPointerDown: handleResizeStart
1788
- }
1789
- ),
1790
- /* @__PURE__ */ jsx5("div", { className: "pactor-chat-inspector__header", children: /* @__PURE__ */ jsx5(
1791
- ChromeSlot,
1792
- {
1793
- fragment: buildPanelHeaderFragment({
1794
- title: artifact?.title ?? "\u4EA7\u51FA\u7269",
1795
- kind: artifact?.kind ?? "text",
1796
- showListButton,
1797
- showDownload: artifact != null
1798
- }),
1799
- components: PANEL_HEADER_INTERNAL_COMPONENTS,
1800
- fallback: /* @__PURE__ */ jsxs2(Fragment3, { children: [
1801
- showListButton ? /* @__PURE__ */ jsx5(
1802
- "button",
1803
- {
1804
- type: "button",
1805
- className: "pactor-chat-icon-button pactor-chat-inspector__list-toggle",
1806
- title: "\u4EA7\u7269\u76EE\u5F55",
1807
- "aria-label": "\u4EA7\u7269\u76EE\u5F55",
1808
- onClick: () => toggleListRef.current(),
1809
- children: /* @__PURE__ */ jsx5(Icon3, { name: "arrow-left", size: 16, strokeWidth: 1.7 })
1810
- }
1811
- ) : null,
1812
- /* @__PURE__ */ jsx5("span", { className: "pactor-chat-inspector__title", children: artifact?.title ?? "\u4EA7\u51FA\u7269" }),
1813
- artifact ? /* @__PURE__ */ jsx5("span", { className: "pactor-chat-inspector__kind", children: artifact.kind }) : null,
1814
- artifact ? /* @__PURE__ */ jsx5(
1815
- "button",
1816
- {
1817
- type: "button",
1818
- className: "pactor-chat-icon-button pactor-chat-inspector__download",
1819
- title: "\u4E0B\u8F7D\u4EA7\u7269",
1820
- "aria-label": "\u4E0B\u8F7D\u4EA7\u7269",
1821
- onClick: () => void downloadArtifact(artifact),
1822
- children: /* @__PURE__ */ jsx5(Icon3, { name: "download", size: 16, strokeWidth: 1.7 })
1823
- }
1824
- ) : null,
1825
- /* @__PURE__ */ jsx5(
1826
- "button",
1827
- {
1828
- type: "button",
1829
- className: "pactor-chat-icon-button pactor-chat-inspector__close",
1830
- "aria-label": "\u5173\u95ED\u9762\u677F",
1831
- onClick: onClose,
1832
- children: /* @__PURE__ */ jsx5(Icon3, { name: "x", size: 16, strokeWidth: 1.7 })
1833
- }
1834
- )
1835
- ] })
1836
- }
1837
- ) }),
1838
- artifacts !== void 0 && artifacts.length > 1 ? /* @__PURE__ */ jsx5("div", { className: "pactor-chat-inspector__tabs", role: "tablist", children: artifacts.map((item) => /* @__PURE__ */ jsxs2(
1839
- "button",
1840
- {
1841
- type: "button",
1842
- role: "tab",
1843
- "aria-selected": item.id === activeId,
1844
- "data-active": item.id === activeId,
1845
- className: "pactor-chat-inspector__tab",
1846
- title: item.title,
1847
- onClick: () => onSelectArtifact?.(item),
1848
- children: [
1849
- /* @__PURE__ */ jsx5(ArtifactKindIcon, { kind: item.kind }),
1850
- /* @__PURE__ */ jsx5("span", { className: "pactor-chat-inspector__tab-title", children: item.title })
1851
- ]
1852
- },
1853
- item.id
1854
- )) }) : null,
1855
- /* @__PURE__ */ jsx5("div", { className: "pactor-chat-inspector__body", children: view === "list" && artifacts !== void 0 ? /* @__PURE__ */ jsx5(
1856
- ArtifactListView,
1857
- {
1858
- nodes: buildArtifactTree(artifacts),
1859
- activeId,
1860
- onSelect: onSelectArtifact
1861
- }
1862
- ) : inspector !== void 0 && inspector !== null ? inspector : artifact ? /* @__PURE__ */ jsx5(
1863
- ArtifactContent,
1864
- {
1865
- artifact,
1866
- runtime,
1867
- viewers: artifactViewers
1868
- }
1869
- ) : null })
1870
- ]
1968
+ value: {
1969
+ artifacts: artifacts ?? [],
1970
+ activeId,
1971
+ view,
1972
+ onSelectArtifact
1973
+ },
1974
+ children: /* @__PURE__ */ jsxs4(
1975
+ "aside",
1976
+ {
1977
+ ref: panelRef,
1978
+ className: `pactor-chat-inspector${className ? ` ${className}` : ""}`,
1979
+ "data-kind": artifact?.kind,
1980
+ style: width !== null ? { width: `${width}px` } : void 0,
1981
+ children: [
1982
+ /* @__PURE__ */ jsx6(
1983
+ "div",
1984
+ {
1985
+ className: "pactor-chat-inspector__resize",
1986
+ role: "separator",
1987
+ "aria-orientation": "vertical",
1988
+ "aria-label": "\u62D6\u52A8\u8C03\u6574\u9762\u677F\u5BBD\u5EA6",
1989
+ onPointerDown: handleResizeStart
1990
+ }
1991
+ ),
1992
+ /* @__PURE__ */ jsx6("div", { className: "pactor-chat-inspector__header", children: /* @__PURE__ */ jsx6(
1993
+ ChromeSlot,
1994
+ {
1995
+ fragment: buildPanelHeaderFragment({
1996
+ title: view === "list" ? "\u4EA7\u7269\u76EE\u5F55" : artifact?.title ?? "\u4EA7\u51FA\u7269",
1997
+ kind: artifact?.kind ?? "text",
1998
+ showListButton,
1999
+ showDownload: artifact != null,
2000
+ showMenu,
2001
+ view
2002
+ }),
2003
+ components: PANEL_HEADER_INTERNAL_COMPONENTS,
2004
+ fallback: /* @__PURE__ */ jsxs4(Fragment3, { children: [
2005
+ showListButton ? /* @__PURE__ */ jsx6(ChatPanelListButton, {}) : null,
2006
+ showMenu ? /* @__PURE__ */ jsx6(ChatPanelArtifactMenu, {}) : /* @__PURE__ */ jsx6("span", { className: "pactor-chat-inspector__title", children: view === "list" ? "\u4EA7\u7269\u76EE\u5F55" : artifact?.title ?? "\u4EA7\u51FA\u7269" }),
2007
+ view !== "list" && artifact ? /* @__PURE__ */ jsx6("span", { className: "pactor-chat-inspector__kind", children: artifact.kind }) : null,
2008
+ artifact ? /* @__PURE__ */ jsx6(ChatPanelDownloadButton, {}) : null,
2009
+ /* @__PURE__ */ jsx6(ChatPanelCloseButton, {})
2010
+ ] })
2011
+ }
2012
+ ) }),
2013
+ /* @__PURE__ */ jsx6("div", { className: "pactor-chat-inspector__body", children: view === "list" && artifacts !== void 0 ? /* @__PURE__ */ jsx6(
2014
+ ArtifactListView,
2015
+ {
2016
+ nodes: buildArtifactTree(artifacts),
2017
+ activeId,
2018
+ onSelect: onSelectArtifact
2019
+ }
2020
+ ) : inspector !== void 0 && inspector !== null ? inspector : artifact ? /* @__PURE__ */ jsx6(
2021
+ ArtifactContent,
2022
+ {
2023
+ artifact,
2024
+ runtime,
2025
+ viewers: artifactViewers
2026
+ }
2027
+ ) : null })
2028
+ ]
2029
+ }
2030
+ )
1871
2031
  }
1872
2032
  );
1873
2033
  }
1874
2034
 
1875
2035
  // src/view/ChatView.tsx
1876
- import { Icon as Icon9 } from "@pactor-app/ui/components";
2036
+ import { Icon as Icon10 } from "@pactor-app/ui/components";
1877
2037
  import { Registry as Registry3 } from "@pactor-app/core";
1878
- import { useEffect as useEffect9, useMemo as useMemo3, useRef as useRef11, useState as useState13, useSyncExternalStore } from "react";
2038
+ import { useEffect as useEffect9, useMemo as useMemo3, useRef as useRef11, useState as useState14, useSyncExternalStore } from "react";
1879
2039
 
1880
2040
  // src/view/Composer.tsx
1881
- import { Icon as Icon6 } from "@pactor-app/ui/components";
1882
- import { useLayoutEffect as useLayoutEffect3, useMemo as useMemo2, useRef as useRef7, useState as useState9 } from "react";
2041
+ import { Icon as Icon7 } from "@pactor-app/ui/components";
2042
+ import { useLayoutEffect as useLayoutEffect3, useMemo as useMemo2, useRef as useRef7, useState as useState10 } from "react";
1883
2043
 
1884
2044
  // src/view/AnchoredPopover.tsx
1885
2045
  import {
1886
2046
  useEffect as useEffect4,
1887
2047
  useLayoutEffect as useLayoutEffect2,
1888
2048
  useRef as useRef5,
1889
- useState as useState6
2049
+ useState as useState7
1890
2050
  } from "react";
1891
- import { jsx as jsx6 } from "react/jsx-runtime";
2051
+ import { jsx as jsx7 } from "react/jsx-runtime";
1892
2052
  function AnchoredPopover({
1893
2053
  anchorRect,
1894
2054
  onClose,
@@ -1898,7 +2058,7 @@ function AnchoredPopover({
1898
2058
  sideOffset = 8
1899
2059
  }) {
1900
2060
  const ref = useRef5(null);
1901
- const [position, setPosition] = useState6(null);
2061
+ const [position, setPosition] = useState7(null);
1902
2062
  useLayoutEffect2(() => {
1903
2063
  const element = ref.current;
1904
2064
  if (!element) return;
@@ -1945,7 +2105,7 @@ function AnchoredPopover({
1945
2105
  position?.below ? "pactor-chat-popover--below" : "",
1946
2106
  className ?? ""
1947
2107
  ].filter(Boolean).join(" ");
1948
- return /* @__PURE__ */ jsx6(
2108
+ return /* @__PURE__ */ jsx7(
1949
2109
  "div",
1950
2110
  {
1951
2111
  ref,
@@ -1964,8 +2124,8 @@ function AnchoredPopover({
1964
2124
  }
1965
2125
 
1966
2126
  // src/view/ModelChip.tsx
1967
- import { Icon as Icon4 } from "@pactor-app/ui/components";
1968
- import { useEffect as useEffect5, useRef as useRef6, useState as useState7 } from "react";
2127
+ import { Icon as Icon5 } from "@pactor-app/ui/components";
2128
+ import { useEffect as useEffect5, useRef as useRef6, useState as useState8 } from "react";
1969
2129
 
1970
2130
  // src/view/chrome/model-select.tsx
1971
2131
  function buildModelSelectFragment(props) {
@@ -1991,17 +2151,17 @@ function buildModelSelectFragment(props) {
1991
2151
  }
1992
2152
 
1993
2153
  // src/view/ModelChip.tsx
1994
- import { Fragment as Fragment4, jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
2154
+ import { Fragment as Fragment4, jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
1995
2155
  function ModelChip({
1996
2156
  models,
1997
2157
  model,
1998
2158
  onModelChange
1999
2159
  }) {
2000
2160
  const chipRef = useRef6(null);
2001
- const [anchor, setAnchor] = useState7(null);
2161
+ const [anchor, setAnchor] = useState8(null);
2002
2162
  const currentOption = models.find((option) => option.value === model) ?? models[0];
2003
- return /* @__PURE__ */ jsxs3(Fragment4, { children: [
2004
- /* @__PURE__ */ jsxs3(
2163
+ return /* @__PURE__ */ jsxs5(Fragment4, { children: [
2164
+ /* @__PURE__ */ jsxs5(
2005
2165
  "button",
2006
2166
  {
2007
2167
  ref: chipRef,
@@ -2011,18 +2171,18 @@ function ModelChip({
2011
2171
  "aria-label": "\u9009\u62E9\u6A21\u578B",
2012
2172
  onClick: () => setAnchor(chipRef.current.getBoundingClientRect()),
2013
2173
  children: [
2014
- /* @__PURE__ */ jsx7("span", { className: "pactor-chat-model-chip__label", children: currentOption.label }),
2015
- /* @__PURE__ */ jsx7(Icon4, { name: "chevrons-up-down", size: 12 })
2174
+ /* @__PURE__ */ jsx8("span", { className: "pactor-chat-model-chip__label", children: currentOption.label }),
2175
+ /* @__PURE__ */ jsx8(Icon5, { name: "chevrons-up-down", size: 12 })
2016
2176
  ]
2017
2177
  }
2018
2178
  ),
2019
- anchor && /* @__PURE__ */ jsx7(
2179
+ anchor && /* @__PURE__ */ jsx8(
2020
2180
  AnchoredPopover,
2021
2181
  {
2022
2182
  anchorRect: anchor,
2023
2183
  onClose: () => setAnchor(null),
2024
2184
  role: "listbox",
2025
- children: models.map((option) => /* @__PURE__ */ jsxs3(
2185
+ children: models.map((option) => /* @__PURE__ */ jsxs5(
2026
2186
  "button",
2027
2187
  {
2028
2188
  type: "button",
@@ -2034,8 +2194,8 @@ function ModelChip({
2034
2194
  setAnchor(null);
2035
2195
  },
2036
2196
  children: [
2037
- /* @__PURE__ */ jsx7("span", { className: "pactor-chat-popover__item-label", children: option.label }),
2038
- option.value === currentOption.value && /* @__PURE__ */ jsx7(Icon4, { name: "check", size: 13, className: "pactor-chat-popover__item-check" })
2197
+ /* @__PURE__ */ jsx8("span", { className: "pactor-chat-popover__item-label", children: option.label }),
2198
+ option.value === currentOption.value && /* @__PURE__ */ jsx8(Icon5, { name: "check", size: 13, className: "pactor-chat-popover__item-check" })
2039
2199
  ]
2040
2200
  },
2041
2201
  option.value
@@ -2056,24 +2216,24 @@ function ModelSelect({
2056
2216
  modelChange: (value) => changeRef.current?.(value)
2057
2217
  });
2058
2218
  }, []);
2059
- return /* @__PURE__ */ jsx7(
2219
+ return /* @__PURE__ */ jsx8(
2060
2220
  ChromeSlot,
2061
2221
  {
2062
2222
  fragment: buildModelSelectFragment({ models, model }),
2063
- fallback: /* @__PURE__ */ jsx7(ModelChip, { models, model, onModelChange })
2223
+ fallback: /* @__PURE__ */ jsx8(ModelChip, { models, model, onModelChange })
2064
2224
  }
2065
2225
  );
2066
2226
  }
2067
2227
 
2068
2228
  // src/view/chrome/composer.tsx
2069
- import { Icon as Icon5 } from "@pactor-app/ui/components";
2070
- import { createContext, useContext } from "react";
2071
- import { Fragment as Fragment5, jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
2072
- var ComposerBridgeContext = createContext(
2229
+ import { Icon as Icon6 } from "@pactor-app/ui/components";
2230
+ import { createContext as createContext2, useContext as useContext2 } from "react";
2231
+ import { Fragment as Fragment5, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
2232
+ var ComposerBridgeContext = createContext2(
2073
2233
  null
2074
2234
  );
2075
2235
  function useComposerBridge() {
2076
- const bridge = useContext(ComposerBridgeContext);
2236
+ const bridge = useContext2(ComposerBridgeContext);
2077
2237
  if (!bridge) {
2078
2238
  throw new Error(
2079
2239
  "[@pactor-app/chat] ChatComposer* \u5185\u90E8\u7EC4\u4EF6\u4EC5\u53EF\u5728 Composer chrome \u7247\u6BB5\u5185\u6E32\u67D3"
@@ -2098,21 +2258,21 @@ function ComposerAttachments({
2098
2258
  if (attachments.length === 0) {
2099
2259
  return null;
2100
2260
  }
2101
- return /* @__PURE__ */ jsx8("div", { className: "pactor-chat-composer__attachments", children: attachments.map((attachment) => {
2261
+ return /* @__PURE__ */ jsx9("div", { className: "pactor-chat-composer__attachments", children: attachments.map((attachment) => {
2102
2262
  const isImage = attachment.mimeType.startsWith("image/");
2103
- return /* @__PURE__ */ jsxs4(
2263
+ return /* @__PURE__ */ jsxs6(
2104
2264
  "div",
2105
2265
  {
2106
2266
  className: "pactor-chat-composer__attachment",
2107
2267
  "data-attachment-id": attachment.id,
2108
2268
  onClick: () => onClick?.(attachment),
2109
2269
  children: [
2110
- isImage && attachment.url ? /* @__PURE__ */ jsx8("span", { className: "pactor-chat-composer__attachment-thumb", children: /* @__PURE__ */ jsx8("img", { src: attachment.url, alt: attachment.name }) }) : /* @__PURE__ */ jsxs4("span", { className: "pactor-chat-composer__attachment-info", children: [
2111
- /* @__PURE__ */ jsx8(Icon5, { name: "file-text", size: 14 }),
2112
- /* @__PURE__ */ jsx8("span", { className: "pactor-chat-composer__attachment-name", children: attachment.name }),
2113
- attachment.size !== void 0 && /* @__PURE__ */ jsx8("span", { className: "pactor-chat-composer__attachment-size", children: formatSize(attachment.size) })
2270
+ isImage && attachment.url ? /* @__PURE__ */ jsx9("span", { className: "pactor-chat-composer__attachment-thumb", children: /* @__PURE__ */ jsx9("img", { src: attachment.url, alt: attachment.name }) }) : /* @__PURE__ */ jsxs6("span", { className: "pactor-chat-composer__attachment-info", children: [
2271
+ /* @__PURE__ */ jsx9(Icon6, { name: "file-text", size: 14 }),
2272
+ /* @__PURE__ */ jsx9("span", { className: "pactor-chat-composer__attachment-name", children: attachment.name }),
2273
+ attachment.size !== void 0 && /* @__PURE__ */ jsx9("span", { className: "pactor-chat-composer__attachment-size", children: formatSize(attachment.size) })
2114
2274
  ] }),
2115
- /* @__PURE__ */ jsx8(
2275
+ /* @__PURE__ */ jsx9(
2116
2276
  "button",
2117
2277
  {
2118
2278
  type: "button",
@@ -2123,7 +2283,7 @@ function ComposerAttachments({
2123
2283
  event.stopPropagation();
2124
2284
  onRemove(attachment.id);
2125
2285
  },
2126
- children: /* @__PURE__ */ jsx8(Icon5, { name: "x", size: 12 })
2286
+ children: /* @__PURE__ */ jsx9(Icon6, { name: "x", size: 12 })
2127
2287
  }
2128
2288
  )
2129
2289
  ]
@@ -2139,14 +2299,14 @@ function ComposerContextChips({
2139
2299
  if (chips.length === 0) {
2140
2300
  return null;
2141
2301
  }
2142
- return /* @__PURE__ */ jsx8("div", { className: "pactor-chat-composer__contexts", children: chips.map((chip) => /* @__PURE__ */ jsxs4(
2302
+ return /* @__PURE__ */ jsx9("div", { className: "pactor-chat-composer__contexts", children: chips.map((chip) => /* @__PURE__ */ jsxs6(
2143
2303
  "span",
2144
2304
  {
2145
2305
  className: "pactor-chat-context-chip",
2146
2306
  "data-context-id": chip.id,
2147
2307
  children: [
2148
- /* @__PURE__ */ jsx8("span", { className: "pactor-chat-context-chip__label", children: chip.label }),
2149
- /* @__PURE__ */ jsx8(
2308
+ /* @__PURE__ */ jsx9("span", { className: "pactor-chat-context-chip__label", children: chip.label }),
2309
+ /* @__PURE__ */ jsx9(
2150
2310
  "button",
2151
2311
  {
2152
2312
  type: "button",
@@ -2154,7 +2314,7 @@ function ComposerContextChips({
2154
2314
  title: `\u79FB\u9664\u4E0A\u4E0B\u6587 ${chip.label}`,
2155
2315
  "aria-label": `\u79FB\u9664\u4E0A\u4E0B\u6587 ${chip.label}`,
2156
2316
  onClick: () => onRemove(chip),
2157
- children: /* @__PURE__ */ jsx8(Icon5, { name: "x", size: 12 })
2317
+ children: /* @__PURE__ */ jsx9(Icon6, { name: "x", size: 12 })
2158
2318
  }
2159
2319
  )
2160
2320
  ]
@@ -2164,8 +2324,8 @@ function ComposerContextChips({
2164
2324
  }
2165
2325
  function ChatComposerHeader() {
2166
2326
  const bridge = useComposerBridge();
2167
- return /* @__PURE__ */ jsxs4(Fragment5, { children: [
2168
- bridge.attachments !== void 0 && /* @__PURE__ */ jsx8(
2327
+ return /* @__PURE__ */ jsxs6(Fragment5, { children: [
2328
+ bridge.attachments !== void 0 && /* @__PURE__ */ jsx9(
2169
2329
  ComposerAttachments,
2170
2330
  {
2171
2331
  attachments: bridge.attachments,
@@ -2173,7 +2333,7 @@ function ChatComposerHeader() {
2173
2333
  onClick: bridge.attachmentClick
2174
2334
  }
2175
2335
  ),
2176
- bridge.contextChips !== void 0 && /* @__PURE__ */ jsx8(
2336
+ bridge.contextChips !== void 0 && /* @__PURE__ */ jsx9(
2177
2337
  ComposerContextChips,
2178
2338
  {
2179
2339
  chips: bridge.contextChips,
@@ -2184,9 +2344,9 @@ function ChatComposerHeader() {
2184
2344
  }
2185
2345
  function ChatComposerToolbarStart() {
2186
2346
  const bridge = useComposerBridge();
2187
- return /* @__PURE__ */ jsxs4(Fragment5, { children: [
2347
+ return /* @__PURE__ */ jsxs6(Fragment5, { children: [
2188
2348
  bridge.toolbarStart,
2189
- bridge.showPlus && /* @__PURE__ */ jsx8(
2349
+ bridge.showPlus && /* @__PURE__ */ jsx9(
2190
2350
  "button",
2191
2351
  {
2192
2352
  type: "button",
@@ -2194,10 +2354,10 @@ function ChatComposerToolbarStart() {
2194
2354
  title: "\u66F4\u591A\u529F\u80FD",
2195
2355
  "aria-label": "\u66F4\u591A\u529F\u80FD",
2196
2356
  onClick: (event) => bridge.plusClick(event.currentTarget.getBoundingClientRect()),
2197
- children: /* @__PURE__ */ jsx8(Icon5, { name: "plus", size: 14 })
2357
+ children: /* @__PURE__ */ jsx9(Icon6, { name: "plus", size: 14 })
2198
2358
  }
2199
2359
  ),
2200
- bridge.showAttach && /* @__PURE__ */ jsx8(
2360
+ bridge.showAttach && /* @__PURE__ */ jsx9(
2201
2361
  "button",
2202
2362
  {
2203
2363
  type: "button",
@@ -2205,15 +2365,15 @@ function ChatComposerToolbarStart() {
2205
2365
  title: "\u6DFB\u52A0\u9644\u4EF6",
2206
2366
  "aria-label": "\u6DFB\u52A0\u9644\u4EF6",
2207
2367
  onClick: bridge.openFilePicker,
2208
- children: /* @__PURE__ */ jsx8(Icon5, { name: "paperclip", size: 14 })
2368
+ children: /* @__PURE__ */ jsx9(Icon6, { name: "paperclip", size: 14 })
2209
2369
  }
2210
2370
  )
2211
2371
  ] });
2212
2372
  }
2213
2373
  function ChatComposerToolbarEnd() {
2214
2374
  const bridge = useComposerBridge();
2215
- return /* @__PURE__ */ jsxs4(Fragment5, { children: [
2216
- bridge.modelChipEnabled && /* @__PURE__ */ jsx8(
2375
+ return /* @__PURE__ */ jsxs6(Fragment5, { children: [
2376
+ bridge.modelChipEnabled && /* @__PURE__ */ jsx9(
2217
2377
  ModelSelect,
2218
2378
  {
2219
2379
  models: bridge.models,
@@ -2222,7 +2382,7 @@ function ChatComposerToolbarEnd() {
2222
2382
  }
2223
2383
  ),
2224
2384
  bridge.toolbarEnd,
2225
- /* @__PURE__ */ jsx8(
2385
+ /* @__PURE__ */ jsx9(
2226
2386
  "button",
2227
2387
  {
2228
2388
  type: "button",
@@ -2231,14 +2391,14 @@ function ChatComposerToolbarEnd() {
2231
2391
  "aria-label": bridge.streaming ? "\u505C\u6B62\u751F\u6210" : "\u53D1\u9001",
2232
2392
  disabled: bridge.streaming ? false : bridge.disabled || !bridge.text.trim(),
2233
2393
  onClick: bridge.streaming ? bridge.stop : bridge.send,
2234
- children: bridge.streaming ? /* @__PURE__ */ jsx8(Icon5, { name: "square", size: 14, className: "pactor-chat-icon-fill" }) : /* @__PURE__ */ jsx8(Icon5, { name: "arrow-up", size: 16 })
2394
+ children: bridge.streaming ? /* @__PURE__ */ jsx9(Icon6, { name: "square", size: 14, className: "pactor-chat-icon-fill" }) : /* @__PURE__ */ jsx9(Icon6, { name: "arrow-up", size: 16 })
2235
2395
  }
2236
2396
  )
2237
2397
  ] });
2238
2398
  }
2239
2399
  function ChatComposerFooter() {
2240
2400
  const bridge = useComposerBridge();
2241
- return /* @__PURE__ */ jsx8(Fragment5, { children: bridge.composerFooter });
2401
+ return /* @__PURE__ */ jsx9(Fragment5, { children: bridge.composerFooter });
2242
2402
  }
2243
2403
  var COMPOSER_INTERNAL_COMPONENTS = {
2244
2404
  ChatComposerHeader,
@@ -2279,8 +2439,8 @@ function buildComposerFragment(props) {
2279
2439
  }
2280
2440
 
2281
2441
  // src/view/context-sources.tsx
2282
- import { useEffect as useEffect6, useState as useState8 } from "react";
2283
- import { jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
2442
+ import { useEffect as useEffect6, useState as useState9 } from "react";
2443
+ import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
2284
2444
  function sourceCacheKey(source) {
2285
2445
  return `${source.service ?? ""}:${JSON.stringify(source.params ?? {})}`;
2286
2446
  }
@@ -2315,7 +2475,7 @@ function ContextSourceList({
2315
2475
  cache,
2316
2476
  onSelect
2317
2477
  }) {
2318
- const [resolutions, setResolutions] = useState8([]);
2478
+ const [resolutions, setResolutions] = useState9([]);
2319
2479
  useEffect6(() => {
2320
2480
  let cancelled = false;
2321
2481
  const initial = sources.map(
@@ -2361,12 +2521,12 @@ function ContextSourceList({
2361
2521
  totalMatched += items.length;
2362
2522
  return { source, resolution, items };
2363
2523
  });
2364
- return /* @__PURE__ */ jsxs5("div", { className: "pactor-chat-source-list", children: [
2365
- groups.map(({ source, resolution, items }) => /* @__PURE__ */ jsxs5("div", { className: "pactor-chat-source-list__group", children: [
2366
- sources.length > 1 && /* @__PURE__ */ jsx9("div", { className: "pactor-chat-source-list__group-label", children: source.label }),
2367
- resolution.status === "loading" && /* @__PURE__ */ jsx9("div", { className: "pactor-chat-source-list__hint", children: "\u52A0\u8F7D\u4E2D\u2026" }),
2368
- resolution.status === "error" && /* @__PURE__ */ jsx9("div", { className: "pactor-chat-source-list__error", role: "alert", children: resolution.message }),
2369
- items.map((item) => /* @__PURE__ */ jsx9(
2524
+ return /* @__PURE__ */ jsxs7("div", { className: "pactor-chat-source-list", children: [
2525
+ groups.map(({ source, resolution, items }) => /* @__PURE__ */ jsxs7("div", { className: "pactor-chat-source-list__group", children: [
2526
+ sources.length > 1 && /* @__PURE__ */ jsx10("div", { className: "pactor-chat-source-list__group-label", children: source.label }),
2527
+ resolution.status === "loading" && /* @__PURE__ */ jsx10("div", { className: "pactor-chat-source-list__hint", children: "\u52A0\u8F7D\u4E2D\u2026" }),
2528
+ resolution.status === "error" && /* @__PURE__ */ jsx10("div", { className: "pactor-chat-source-list__error", role: "alert", children: resolution.message }),
2529
+ items.map((item) => /* @__PURE__ */ jsx10(
2370
2530
  "button",
2371
2531
  {
2372
2532
  type: "button",
@@ -2377,12 +2537,12 @@ function ContextSourceList({
2377
2537
  item.id
2378
2538
  ))
2379
2539
  ] }, `${source.trigger}:${source.label}`)),
2380
- totalMatched === 0 && groups.every(({ resolution }) => resolution.status === "ready") && /* @__PURE__ */ jsx9("div", { className: "pactor-chat-source-list__hint", children: "\u65E0\u5339\u914D\u9879" })
2540
+ totalMatched === 0 && groups.every(({ resolution }) => resolution.status === "ready") && /* @__PURE__ */ jsx10("div", { className: "pactor-chat-source-list__hint", children: "\u65E0\u5339\u914D\u9879" })
2381
2541
  ] });
2382
2542
  }
2383
2543
 
2384
2544
  // src/view/Composer.tsx
2385
- import { Fragment as Fragment6, jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
2545
+ import { Fragment as Fragment6, jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
2386
2546
  var MAX_INPUT_HEIGHT = 200;
2387
2547
  function detectMention(text, caret) {
2388
2548
  const beforeCaret = text.slice(0, caret);
@@ -2416,8 +2576,8 @@ function Composer({
2416
2576
  composerFooter,
2417
2577
  hideToolbar = false
2418
2578
  }) {
2419
- const [text, setText] = useState9("");
2420
- const [dragOver, setDragOver] = useState9(false);
2579
+ const [text, setText] = useState10("");
2580
+ const [dragOver, setDragOver] = useState10(false);
2421
2581
  const inputRef = useRef7(null);
2422
2582
  const fileInputRef = useRef7(null);
2423
2583
  const plusButtonRef = useRef7(null);
@@ -2433,8 +2593,8 @@ function Composer({
2433
2593
  );
2434
2594
  const builtinMentionEnabled = onMentionTrigger === void 0 && mentionSources.length > 0;
2435
2595
  const builtinPlusEnabled = onPlusMenu === void 0 && plusSources.length > 0;
2436
- const [mentionState, setMentionState] = useState9(null);
2437
- const [plusAnchor, setPlusAnchor] = useState9(null);
2596
+ const [mentionState, setMentionState] = useState10(null);
2597
+ const [plusAnchor, setPlusAnchor] = useState10(null);
2438
2598
  const sourceCacheRef = useRef7(null);
2439
2599
  if (sourceCacheRef.current === null) {
2440
2600
  sourceCacheRef.current = /* @__PURE__ */ new Map();
@@ -2529,7 +2689,7 @@ function Composer({
2529
2689
  }
2530
2690
  };
2531
2691
  const showToolbar = !hideToolbar && (toolbarStart !== void 0 || toolbarEnd !== void 0 || onPlusMenu !== void 0 || builtinPlusEnabled || onAttachFiles !== void 0 || modelChipEnabled);
2532
- const fileInputNode = onAttachFiles ? /* @__PURE__ */ jsx10(
2692
+ const fileInputNode = onAttachFiles ? /* @__PURE__ */ jsx11(
2533
2693
  "input",
2534
2694
  {
2535
2695
  ref: fileInputRef,
@@ -2545,14 +2705,14 @@ function Composer({
2545
2705
  }
2546
2706
  }
2547
2707
  ) : null;
2548
- const popoverNodes = /* @__PURE__ */ jsxs6(Fragment6, { children: [
2549
- builtinMentionEnabled && mentionState && /* @__PURE__ */ jsx10(
2708
+ const popoverNodes = /* @__PURE__ */ jsxs8(Fragment6, { children: [
2709
+ builtinMentionEnabled && mentionState && /* @__PURE__ */ jsx11(
2550
2710
  AnchoredPopover,
2551
2711
  {
2552
2712
  anchorRect: mentionState.anchorRect,
2553
2713
  onClose: () => setMentionState(null),
2554
2714
  role: "listbox",
2555
- children: /* @__PURE__ */ jsx10(
2715
+ children: /* @__PURE__ */ jsx11(
2556
2716
  ContextSourceList,
2557
2717
  {
2558
2718
  sources: mentionSources,
@@ -2564,13 +2724,13 @@ function Composer({
2564
2724
  )
2565
2725
  }
2566
2726
  ),
2567
- builtinPlusEnabled && plusAnchor && /* @__PURE__ */ jsx10(
2727
+ builtinPlusEnabled && plusAnchor && /* @__PURE__ */ jsx11(
2568
2728
  AnchoredPopover,
2569
2729
  {
2570
2730
  anchorRect: plusAnchor,
2571
2731
  onClose: () => setPlusAnchor(null),
2572
2732
  role: "listbox",
2573
- children: /* @__PURE__ */ jsx10(
2733
+ children: /* @__PURE__ */ jsx11(
2574
2734
  ContextSourceList,
2575
2735
  {
2576
2736
  sources: plusSources,
@@ -2583,13 +2743,13 @@ function Composer({
2583
2743
  }
2584
2744
  )
2585
2745
  ] });
2586
- const fallback = /* @__PURE__ */ jsxs6(
2746
+ const fallback = /* @__PURE__ */ jsxs8(
2587
2747
  "div",
2588
2748
  {
2589
2749
  className: `pactor-chat-composer${dragOver ? " pactor-chat-composer--dragover" : ""}`,
2590
2750
  ...dragHandlers,
2591
2751
  children: [
2592
- attachments !== void 0 && /* @__PURE__ */ jsx10(
2752
+ attachments !== void 0 && /* @__PURE__ */ jsx11(
2593
2753
  ComposerAttachments,
2594
2754
  {
2595
2755
  attachments,
@@ -2597,7 +2757,7 @@ function Composer({
2597
2757
  onClick: onAttachmentClick
2598
2758
  }
2599
2759
  ),
2600
- contextChips !== void 0 && /* @__PURE__ */ jsx10(
2760
+ contextChips !== void 0 && /* @__PURE__ */ jsx11(
2601
2761
  ComposerContextChips,
2602
2762
  {
2603
2763
  chips: contextChips,
@@ -2608,8 +2768,8 @@ function Composer({
2608
2768
  )
2609
2769
  }
2610
2770
  ),
2611
- /* @__PURE__ */ jsxs6("div", { className: "pactor-chat-composer__row", children: [
2612
- /* @__PURE__ */ jsx10(
2771
+ /* @__PURE__ */ jsxs8("div", { className: "pactor-chat-composer__row", children: [
2772
+ /* @__PURE__ */ jsx11(
2613
2773
  "textarea",
2614
2774
  {
2615
2775
  ref: inputRef,
@@ -2641,7 +2801,7 @@ function Composer({
2641
2801
  }
2642
2802
  }
2643
2803
  ),
2644
- hideToolbar ? null : /* @__PURE__ */ jsx10(
2804
+ hideToolbar ? null : /* @__PURE__ */ jsx11(
2645
2805
  "button",
2646
2806
  {
2647
2807
  type: "button",
@@ -2650,14 +2810,14 @@ function Composer({
2650
2810
  "aria-label": streaming ? "\u505C\u6B62\u751F\u6210" : "\u53D1\u9001",
2651
2811
  disabled: streaming ? false : disabled || !text.trim(),
2652
2812
  onClick: streaming ? onStop : send,
2653
- children: streaming ? /* @__PURE__ */ jsx10(Icon6, { name: "square", size: 14, className: "pactor-chat-icon-fill" }) : /* @__PURE__ */ jsx10(Icon6, { name: "arrow-up", size: 16 })
2813
+ children: streaming ? /* @__PURE__ */ jsx11(Icon7, { name: "square", size: 14, className: "pactor-chat-icon-fill" }) : /* @__PURE__ */ jsx11(Icon7, { name: "arrow-up", size: 16 })
2654
2814
  }
2655
2815
  )
2656
2816
  ] }),
2657
- showToolbar && /* @__PURE__ */ jsxs6("div", { className: "pactor-chat-composer__toolbar", children: [
2817
+ showToolbar && /* @__PURE__ */ jsxs8("div", { className: "pactor-chat-composer__toolbar", children: [
2658
2818
  toolbarStart,
2659
- /* @__PURE__ */ jsx10("span", { className: "pactor-chat-composer__toolbar-spacer" }),
2660
- (onPlusMenu || builtinPlusEnabled) && /* @__PURE__ */ jsx10(
2819
+ /* @__PURE__ */ jsx11("span", { className: "pactor-chat-composer__toolbar-spacer" }),
2820
+ (onPlusMenu || builtinPlusEnabled) && /* @__PURE__ */ jsx11(
2661
2821
  "button",
2662
2822
  {
2663
2823
  ref: plusButtonRef,
@@ -2673,10 +2833,10 @@ function Composer({
2673
2833
  setPlusAnchor(rect);
2674
2834
  }
2675
2835
  },
2676
- children: /* @__PURE__ */ jsx10(Icon6, { name: "plus", size: 14 })
2836
+ children: /* @__PURE__ */ jsx11(Icon7, { name: "plus", size: 14 })
2677
2837
  }
2678
2838
  ),
2679
- onAttachFiles && /* @__PURE__ */ jsx10(
2839
+ onAttachFiles && /* @__PURE__ */ jsx11(
2680
2840
  "button",
2681
2841
  {
2682
2842
  type: "button",
@@ -2684,10 +2844,10 @@ function Composer({
2684
2844
  title: "\u6DFB\u52A0\u9644\u4EF6",
2685
2845
  "aria-label": "\u6DFB\u52A0\u9644\u4EF6",
2686
2846
  onClick: () => fileInputRef.current?.click(),
2687
- children: /* @__PURE__ */ jsx10(Icon6, { name: "paperclip", size: 14 })
2847
+ children: /* @__PURE__ */ jsx11(Icon7, { name: "paperclip", size: 14 })
2688
2848
  }
2689
2849
  ),
2690
- modelChipEnabled && /* @__PURE__ */ jsx10(
2850
+ modelChipEnabled && /* @__PURE__ */ jsx11(
2691
2851
  ModelSelect,
2692
2852
  {
2693
2853
  models,
@@ -2697,7 +2857,7 @@ function Composer({
2697
2857
  ),
2698
2858
  toolbarEnd
2699
2859
  ] }),
2700
- composerFooter !== void 0 && composerFooter !== null ? /* @__PURE__ */ jsx10("div", { className: "pactor-chat-composer__footer", children: composerFooter }) : null,
2860
+ composerFooter !== void 0 && composerFooter !== null ? /* @__PURE__ */ jsx11("div", { className: "pactor-chat-composer__footer", children: composerFooter }) : null,
2701
2861
  fileInputNode,
2702
2862
  popoverNodes
2703
2863
  ]
@@ -2736,7 +2896,7 @@ function Composer({
2736
2896
  ),
2737
2897
  modelChange: onModelChange
2738
2898
  };
2739
- return /* @__PURE__ */ jsx10(
2899
+ return /* @__PURE__ */ jsx11(
2740
2900
  ChromeSlot,
2741
2901
  {
2742
2902
  fragment: buildComposerFragment({
@@ -2747,7 +2907,7 @@ function Composer({
2747
2907
  }),
2748
2908
  components: COMPOSER_INTERNAL_COMPONENTS,
2749
2909
  fallback,
2750
- wrap: (children) => /* @__PURE__ */ jsx10(ComposerBridgeContext.Provider, { value: bridge, children: /* @__PURE__ */ jsxs6(
2910
+ wrap: (children) => /* @__PURE__ */ jsx11(ComposerBridgeContext.Provider, { value: bridge, children: /* @__PURE__ */ jsxs8(
2751
2911
  "div",
2752
2912
  {
2753
2913
  className: `pactor-chat-composer pactor-chat-composer--dsl${dragOver ? " pactor-chat-composer--dragover" : ""}`,
@@ -2835,7 +2995,7 @@ function buildEmptyStateFragment(props) {
2835
2995
  }
2836
2996
 
2837
2997
  // src/view/EmptyState.tsx
2838
- import { Fragment as Fragment7, jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
2998
+ import { Fragment as Fragment7, jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
2839
2999
  var DEFAULT_CHAT_GREETING = "\u4F60\u597D\uFF0C\u6709\u4EC0\u4E48\u53EF\u4EE5\u5E2E\u4F60\uFF1F";
2840
3000
  function suggestionLabel2(suggestion) {
2841
3001
  return typeof suggestion === "string" ? suggestion : suggestion.label;
@@ -2849,10 +3009,10 @@ function EmptyStateFallback({
2849
3009
  onSuggestionClick,
2850
3010
  greeting
2851
3011
  }) {
2852
- return /* @__PURE__ */ jsxs7(Fragment7, { children: [
2853
- /* @__PURE__ */ jsx11("div", { className: "pactor-chat-empty__greeting", children: greeting }),
2854
- subtitle && /* @__PURE__ */ jsx11("div", { className: "pactor-chat-empty__subtitle", children: subtitle }),
2855
- suggestions && suggestions.length > 0 && /* @__PURE__ */ jsx11("div", { className: "pactor-chat-empty__suggestions", children: suggestions.map((suggestion) => /* @__PURE__ */ jsx11(
3012
+ return /* @__PURE__ */ jsxs9(Fragment7, { children: [
3013
+ /* @__PURE__ */ jsx12("div", { className: "pactor-chat-empty__greeting", children: greeting }),
3014
+ subtitle && /* @__PURE__ */ jsx12("div", { className: "pactor-chat-empty__subtitle", children: subtitle }),
3015
+ suggestions && suggestions.length > 0 && /* @__PURE__ */ jsx12("div", { className: "pactor-chat-empty__suggestions", children: suggestions.map((suggestion) => /* @__PURE__ */ jsx12(
2856
3016
  "button",
2857
3017
  {
2858
3018
  type: "button",
@@ -2870,11 +3030,11 @@ function EmptyState({
2870
3030
  suggestions,
2871
3031
  onSuggestionClick
2872
3032
  }) {
2873
- return /* @__PURE__ */ jsx11("div", { className: "pactor-chat-empty", children: /* @__PURE__ */ jsx11(
3033
+ return /* @__PURE__ */ jsx12("div", { className: "pactor-chat-empty", children: /* @__PURE__ */ jsx12(
2874
3034
  ChromeSlot,
2875
3035
  {
2876
3036
  fragment: buildEmptyStateFragment({ greeting, subtitle, suggestions }),
2877
- fallback: /* @__PURE__ */ jsx11(
3037
+ fallback: /* @__PURE__ */ jsx12(
2878
3038
  EmptyStateFallback,
2879
3039
  {
2880
3040
  greeting,
@@ -2888,15 +3048,15 @@ function EmptyState({
2888
3048
  }
2889
3049
 
2890
3050
  // src/view/MessageBubble.tsx
2891
- import { useRef as useRef10, useState as useState12 } from "react";
3051
+ import { useRef as useRef10, useState as useState13 } from "react";
2892
3052
 
2893
3053
  // src/view/ActivityTrace.tsx
2894
- import { Icon as Icon7 } from "@pactor-app/ui/components";
3054
+ import { Icon as Icon8 } from "@pactor-app/ui/components";
2895
3055
  import { MarkdownRenderer as MarkdownRenderer3 } from "@pactor-app/markdown";
2896
- import { useEffect as useEffect7, useRef as useRef8, useState as useState10 } from "react";
2897
- import { Fragment as Fragment8, jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
3056
+ import { useEffect as useEffect7, useRef as useRef8, useState as useState11 } from "react";
3057
+ import { Fragment as Fragment8, jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
2898
3058
  function usePinnedCollapse(autoOpen) {
2899
- const [state, setState] = useState10("auto");
3059
+ const [state, setState] = useState11("auto");
2900
3060
  const autoCollapsedRef = useRef8(false);
2901
3061
  if (state === "auto" && !autoOpen) {
2902
3062
  autoCollapsedRef.current = true;
@@ -2926,7 +3086,7 @@ function statusText(message, mode, toolCount) {
2926
3086
  }
2927
3087
  function useElapsedSeconds(startedAt, active) {
2928
3088
  const compute = () => Math.max(0, Math.floor((Date.now() - startedAt) / 1e3));
2929
- const [elapsed, setElapsed] = useState10(compute);
3089
+ const [elapsed, setElapsed] = useState11(compute);
2930
3090
  useEffect7(() => {
2931
3091
  if (!active) {
2932
3092
  setElapsed(compute());
@@ -2941,15 +3101,15 @@ function useElapsedSeconds(startedAt, active) {
2941
3101
  }
2942
3102
  function TraceStatusIcon({ status }) {
2943
3103
  if (status === "running") {
2944
- return /* @__PURE__ */ jsx12(Icon7, { name: "loading", size: 13, className: "pactor-chat-spin" });
3104
+ return /* @__PURE__ */ jsx13(Icon8, { name: "loading", size: 13, className: "pactor-chat-spin" });
2945
3105
  }
2946
3106
  if (status === "success") {
2947
- return /* @__PURE__ */ jsx12(Icon7, { name: "check-circle", size: 13 });
3107
+ return /* @__PURE__ */ jsx13(Icon8, { name: "check-circle", size: 13 });
2948
3108
  }
2949
3109
  if (status === "failed") {
2950
- return /* @__PURE__ */ jsx12(Icon7, { name: "x-circle", size: 13 });
3110
+ return /* @__PURE__ */ jsx13(Icon8, { name: "x-circle", size: 13 });
2951
3111
  }
2952
- return /* @__PURE__ */ jsx12(Icon7, { name: "clock", size: 13 });
3112
+ return /* @__PURE__ */ jsx13(Icon8, { name: "clock", size: 13 });
2953
3113
  }
2954
3114
  function summarizeArgs(args) {
2955
3115
  if (args === void 0) {
@@ -2978,16 +3138,16 @@ function formatDetail(value) {
2978
3138
  }
2979
3139
  }
2980
3140
  function TraceRow({ entry }) {
2981
- const [open, setOpen] = useState10(false);
3141
+ const [open, setOpen] = useState11(false);
2982
3142
  const summary = summarizeArgs(entry.args);
2983
- return /* @__PURE__ */ jsxs8(
3143
+ return /* @__PURE__ */ jsxs10(
2984
3144
  "div",
2985
3145
  {
2986
3146
  className: "pactor-chat-trace__entry",
2987
3147
  "data-status": entry.status,
2988
3148
  "data-open": open,
2989
3149
  children: [
2990
- /* @__PURE__ */ jsxs8(
3150
+ /* @__PURE__ */ jsxs10(
2991
3151
  "button",
2992
3152
  {
2993
3153
  type: "button",
@@ -2995,16 +3155,16 @@ function TraceRow({ entry }) {
2995
3155
  "aria-expanded": open,
2996
3156
  onClick: () => setOpen((value) => !value),
2997
3157
  children: [
2998
- /* @__PURE__ */ jsx12("span", { className: "pactor-chat-trace__chevron", children: /* @__PURE__ */ jsx12(Icon7, { name: "chevron-right", size: 12 }) }),
2999
- /* @__PURE__ */ jsx12("span", { className: "pactor-chat-trace__entry-icon", children: /* @__PURE__ */ jsx12(TraceStatusIcon, { status: entry.status }) }),
3000
- /* @__PURE__ */ jsx12("span", { className: "pactor-chat-trace__entry-title", children: entry.title ?? entry.name }),
3001
- summary && /* @__PURE__ */ jsx12("span", { className: "pactor-chat-trace__entry-args", children: summary })
3158
+ /* @__PURE__ */ jsx13("span", { className: "pactor-chat-trace__chevron", children: /* @__PURE__ */ jsx13(Icon8, { name: "chevron-right", size: 12 }) }),
3159
+ /* @__PURE__ */ jsx13("span", { className: "pactor-chat-trace__entry-icon", children: /* @__PURE__ */ jsx13(TraceStatusIcon, { status: entry.status }) }),
3160
+ /* @__PURE__ */ jsx13("span", { className: "pactor-chat-trace__entry-title", children: entry.title ?? entry.name }),
3161
+ summary && /* @__PURE__ */ jsx13("span", { className: "pactor-chat-trace__entry-args", children: summary })
3002
3162
  ]
3003
3163
  }
3004
3164
  ),
3005
- open && /* @__PURE__ */ jsxs8("div", { className: "pactor-chat-trace__entry-body", children: [
3006
- entry.args !== void 0 && /* @__PURE__ */ jsx12("pre", { className: "pactor-chat-trace__entry-detail", children: formatDetail(entry.args) }),
3007
- /* @__PURE__ */ jsx12("pre", { className: "pactor-chat-trace__entry-detail", children: entry.status === "failed" ? entry.error ?? "\u6267\u884C\u5931\u8D25" : formatDetail(entry.result) })
3165
+ open && /* @__PURE__ */ jsxs10("div", { className: "pactor-chat-trace__entry-body", children: [
3166
+ entry.args !== void 0 && /* @__PURE__ */ jsx13("pre", { className: "pactor-chat-trace__entry-detail", children: formatDetail(entry.args) }),
3167
+ /* @__PURE__ */ jsx13("pre", { className: "pactor-chat-trace__entry-detail", children: entry.status === "failed" ? entry.error ?? "\u6267\u884C\u5931\u8D25" : formatDetail(entry.result) })
3008
3168
  ] })
3009
3169
  ]
3010
3170
  }
@@ -3017,14 +3177,14 @@ function ThinkingCard({
3017
3177
  const partStreaming = part.status === "streaming";
3018
3178
  const shown = useThrottledValue(part.content, 120, partStreaming);
3019
3179
  const { open, toggle } = usePinnedCollapse(partStreaming && !answerPhase);
3020
- return /* @__PURE__ */ jsxs8(
3180
+ return /* @__PURE__ */ jsxs10(
3021
3181
  "div",
3022
3182
  {
3023
3183
  className: "pactor-chat-thinking",
3024
3184
  "data-open": open,
3025
3185
  "data-streaming": partStreaming,
3026
3186
  children: [
3027
- /* @__PURE__ */ jsxs8(
3187
+ /* @__PURE__ */ jsxs10(
3028
3188
  "button",
3029
3189
  {
3030
3190
  type: "button",
@@ -3032,13 +3192,13 @@ function ThinkingCard({
3032
3192
  "aria-expanded": open,
3033
3193
  onClick: toggle,
3034
3194
  children: [
3035
- /* @__PURE__ */ jsx12("span", { className: "pactor-chat-trace__chevron", children: /* @__PURE__ */ jsx12(Icon7, { name: "chevron-right", size: 12 }) }),
3036
- /* @__PURE__ */ jsx12("span", { className: "pactor-chat-thinking__icon", children: partStreaming ? /* @__PURE__ */ jsx12(Icon7, { name: "loading", size: 13, className: "pactor-chat-spin" }) : /* @__PURE__ */ jsx12(Icon7, { name: "brain", size: 13 }) }),
3037
- /* @__PURE__ */ jsx12("span", { children: "\u601D\u8003\u8FC7\u7A0B" })
3195
+ /* @__PURE__ */ jsx13("span", { className: "pactor-chat-trace__chevron", children: /* @__PURE__ */ jsx13(Icon8, { name: "chevron-right", size: 12 }) }),
3196
+ /* @__PURE__ */ jsx13("span", { className: "pactor-chat-thinking__icon", children: partStreaming ? /* @__PURE__ */ jsx13(Icon8, { name: "loading", size: 13, className: "pactor-chat-spin" }) : /* @__PURE__ */ jsx13(Icon8, { name: "brain", size: 13 }) }),
3197
+ /* @__PURE__ */ jsx13("span", { children: "\u601D\u8003\u8FC7\u7A0B" })
3038
3198
  ]
3039
3199
  }
3040
3200
  ),
3041
- open && /* @__PURE__ */ jsx12("div", { className: "pactor-chat-thinking__body", children: partStreaming ? /* @__PURE__ */ jsx12("div", { className: "pactor-chat-thinking__text", children: shown }) : /* @__PURE__ */ jsx12(MarkdownRenderer3, { content: part.content }) })
3201
+ open && /* @__PURE__ */ jsx13("div", { className: "pactor-chat-thinking__body", children: partStreaming ? /* @__PURE__ */ jsx13("div", { className: "pactor-chat-thinking__text", children: shown }) : /* @__PURE__ */ jsx13(MarkdownRenderer3, { content: part.content }) })
3042
3202
  ]
3043
3203
  }
3044
3204
  );
@@ -3061,23 +3221,23 @@ function ActivityTrace({ message }) {
3061
3221
  message.createdAt ?? mountTimeRef.current,
3062
3222
  streaming
3063
3223
  );
3064
- const header = /* @__PURE__ */ jsxs8(Fragment8, { children: [
3065
- /* @__PURE__ */ jsx12("span", { className: "pactor-chat-trace__status-icon", children: streaming ? /* @__PURE__ */ jsx12(Icon7, { name: "loading", size: 13, className: "pactor-chat-spin" }) : /* @__PURE__ */ jsx12(Icon7, { name: "check-circle", size: 13 }) }),
3066
- /* @__PURE__ */ jsx12(
3224
+ const header = /* @__PURE__ */ jsxs10(Fragment8, { children: [
3225
+ /* @__PURE__ */ jsx13("span", { className: "pactor-chat-trace__status-icon", children: streaming ? /* @__PURE__ */ jsx13(Icon8, { name: "loading", size: 13, className: "pactor-chat-spin" }) : /* @__PURE__ */ jsx13(Icon8, { name: "check-circle", size: 13 }) }),
3226
+ /* @__PURE__ */ jsx13(
3067
3227
  "span",
3068
3228
  {
3069
3229
  className: `pactor-chat-trace__status-text${streaming ? " pactor-chat-trace__status-text--breathing" : ""}`,
3070
3230
  children: statusText(message, mode, entries.length)
3071
3231
  }
3072
3232
  ),
3073
- /* @__PURE__ */ jsxs8("span", { className: "pactor-chat-trace__elapsed", children: [
3233
+ /* @__PURE__ */ jsxs10("span", { className: "pactor-chat-trace__elapsed", children: [
3074
3234
  elapsed,
3075
3235
  "s"
3076
3236
  ] }),
3077
- collapsible && /* @__PURE__ */ jsx12("span", { className: "pactor-chat-trace__chevron", children: /* @__PURE__ */ jsx12(Icon7, { name: "chevron-right", size: 12 }) })
3237
+ collapsible && /* @__PURE__ */ jsx13("span", { className: "pactor-chat-trace__chevron", children: /* @__PURE__ */ jsx13(Icon8, { name: "chevron-right", size: 12 }) })
3078
3238
  ] });
3079
- return /* @__PURE__ */ jsxs8("div", { className: "pactor-chat-trace", "data-open": open, children: [
3080
- collapsible ? /* @__PURE__ */ jsx12(
3239
+ return /* @__PURE__ */ jsxs10("div", { className: "pactor-chat-trace", "data-open": open, children: [
3240
+ collapsible ? /* @__PURE__ */ jsx13(
3081
3241
  "button",
3082
3242
  {
3083
3243
  type: "button",
@@ -3086,10 +3246,10 @@ function ActivityTrace({ message }) {
3086
3246
  onClick: toggle,
3087
3247
  children: header
3088
3248
  }
3089
- ) : /* @__PURE__ */ jsx12("div", { className: "pactor-chat-trace__header", children: header }),
3090
- open && /* @__PURE__ */ jsxs8(Fragment8, { children: [
3091
- entries.length > 0 && /* @__PURE__ */ jsx12("div", { className: "pactor-chat-trace__entries", children: entries.map((entry) => /* @__PURE__ */ jsx12(TraceRow, { entry }, entry.callIndex)) }),
3092
- thinkingParts.map((part, index) => /* @__PURE__ */ jsx12(
3249
+ ) : /* @__PURE__ */ jsx13("div", { className: "pactor-chat-trace__header", children: header }),
3250
+ open && /* @__PURE__ */ jsxs10(Fragment8, { children: [
3251
+ entries.length > 0 && /* @__PURE__ */ jsx13("div", { className: "pactor-chat-trace__entries", children: entries.map((entry) => /* @__PURE__ */ jsx13(TraceRow, { entry }, entry.callIndex)) }),
3252
+ thinkingParts.map((part, index) => /* @__PURE__ */ jsx13(
3093
3253
  ThinkingCard,
3094
3254
  {
3095
3255
  part,
@@ -3102,8 +3262,8 @@ function ActivityTrace({ message }) {
3102
3262
  }
3103
3263
 
3104
3264
  // src/view/MessageActions.tsx
3105
- import { Icon as Icon8 } from "@pactor-app/ui/components";
3106
- import { useEffect as useEffect8, useRef as useRef9, useState as useState11 } from "react";
3265
+ import { Icon as Icon9 } from "@pactor-app/ui/components";
3266
+ import { useEffect as useEffect8, useRef as useRef9, useState as useState12 } from "react";
3107
3267
 
3108
3268
  // src/view/chrome/message-actions.tsx
3109
3269
  function buildMessageActionsFragment(args) {
@@ -3156,7 +3316,7 @@ function buildMessageActionsFragment(args) {
3156
3316
  }
3157
3317
 
3158
3318
  // src/view/MessageActions.tsx
3159
- import { jsx as jsx13 } from "react/jsx-runtime";
3319
+ import { jsx as jsx14 } from "react/jsx-runtime";
3160
3320
  var BUILTIN_ACTION_DEFAULTS = {
3161
3321
  copy: {
3162
3322
  label: "\u590D\u5236",
@@ -3229,7 +3389,7 @@ function MessageActions({
3229
3389
  callService,
3230
3390
  onMessageAction
3231
3391
  }) {
3232
- const [copied, setCopied] = useState11(false);
3392
+ const [copied, setCopied] = useState12(false);
3233
3393
  const dispatchRef = useRef9(
3234
3394
  () => {
3235
3395
  }
@@ -3309,7 +3469,7 @@ function MessageActions({
3309
3469
  const copiedFeedback = action.builtin === "copy" && copied;
3310
3470
  const label = copiedFeedback ? "\u5DF2\u590D\u5236" : action.label;
3311
3471
  const iconName = copiedFeedback ? "check" : action.icon;
3312
- return /* @__PURE__ */ jsx13(
3472
+ return /* @__PURE__ */ jsx14(
3313
3473
  "button",
3314
3474
  {
3315
3475
  type: "button",
@@ -3318,16 +3478,16 @@ function MessageActions({
3318
3478
  "aria-label": label,
3319
3479
  "data-message-action": action.id,
3320
3480
  onClick: () => dispatch(action),
3321
- children: iconName !== void 0 ? /* @__PURE__ */ jsx13(Icon8, { name: iconName, size: 14 }) : /* @__PURE__ */ jsx13(Icon8, { name: "help-circle", size: 14 })
3481
+ children: iconName !== void 0 ? /* @__PURE__ */ jsx14(Icon9, { name: iconName, size: 14 }) : /* @__PURE__ */ jsx14(Icon9, { name: "help-circle", size: 14 })
3322
3482
  },
3323
3483
  action.id
3324
3484
  );
3325
3485
  });
3326
- return /* @__PURE__ */ jsx13(
3486
+ return /* @__PURE__ */ jsx14(
3327
3487
  "div",
3328
3488
  {
3329
3489
  className: `pactor-chat-message__actions${forceVisible ? " pactor-chat-message__actions--visible" : ""}`,
3330
- children: /* @__PURE__ */ jsx13(
3490
+ children: /* @__PURE__ */ jsx14(
3331
3491
  ChromeSlot,
3332
3492
  {
3333
3493
  fragment: buildMessageActionsFragment({
@@ -3343,13 +3503,38 @@ function MessageActions({
3343
3503
  }
3344
3504
 
3345
3505
  // src/view/MessageBubble.tsx
3346
- import { jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
3506
+ import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
3507
+ function groupArtifactParts(parts) {
3508
+ const segments = [];
3509
+ for (const part of parts) {
3510
+ if (part.type === "artifact" && part.artifact) {
3511
+ const last = segments[segments.length - 1];
3512
+ if (Array.isArray(last)) {
3513
+ last.push(part.artifact);
3514
+ } else {
3515
+ segments.push([part.artifact]);
3516
+ }
3517
+ } else {
3518
+ segments.push(part);
3519
+ }
3520
+ }
3521
+ return segments;
3522
+ }
3523
+ function formatMessageTime(ts, now = Date.now()) {
3524
+ const date = new Date(ts);
3525
+ const hh = String(date.getHours()).padStart(2, "0");
3526
+ const mm = String(date.getMinutes()).padStart(2, "0");
3527
+ if (new Date(now).toDateString() === date.toDateString()) {
3528
+ return `${hh}:${mm}`;
3529
+ }
3530
+ return `${date.getMonth() + 1}\u6708${date.getDate()}\u65E5 ${hh}:${mm}`;
3531
+ }
3347
3532
  function MessageEditForm({
3348
3533
  initialText,
3349
3534
  onConfirm,
3350
3535
  onCancel
3351
3536
  }) {
3352
- const [text, setText] = useState12(initialText);
3537
+ const [text, setText] = useState13(initialText);
3353
3538
  const confirm = () => {
3354
3539
  const value = text.trim();
3355
3540
  if (!value) {
@@ -3357,8 +3542,8 @@ function MessageEditForm({
3357
3542
  }
3358
3543
  onConfirm(value);
3359
3544
  };
3360
- return /* @__PURE__ */ jsxs9("div", { className: "pactor-chat-message__edit", children: [
3361
- /* @__PURE__ */ jsx14(
3545
+ return /* @__PURE__ */ jsxs11("div", { className: "pactor-chat-message__edit", children: [
3546
+ /* @__PURE__ */ jsx15(
3362
3547
  "textarea",
3363
3548
  {
3364
3549
  className: "pactor-chat-message__edit-input",
@@ -3376,8 +3561,8 @@ function MessageEditForm({
3376
3561
  }
3377
3562
  }
3378
3563
  ),
3379
- /* @__PURE__ */ jsxs9("div", { className: "pactor-chat-message__edit-actions", children: [
3380
- /* @__PURE__ */ jsx14(
3564
+ /* @__PURE__ */ jsxs11("div", { className: "pactor-chat-message__edit-actions", children: [
3565
+ /* @__PURE__ */ jsx15(
3381
3566
  "button",
3382
3567
  {
3383
3568
  type: "button",
@@ -3387,7 +3572,7 @@ function MessageEditForm({
3387
3572
  children: "\u53D1\u9001"
3388
3573
  }
3389
3574
  ),
3390
- /* @__PURE__ */ jsx14(
3575
+ /* @__PURE__ */ jsx15(
3391
3576
  "button",
3392
3577
  {
3393
3578
  type: "button",
@@ -3410,10 +3595,9 @@ function MessageBubble({
3410
3595
  onEditResend,
3411
3596
  messageActions,
3412
3597
  callService,
3413
- onMessageAction,
3414
- onOpenArtifact
3598
+ onMessageAction
3415
3599
  }) {
3416
- const [editing, setEditing] = useState12(false);
3600
+ const [editing, setEditing] = useState13(false);
3417
3601
  const bubbleScope = {
3418
3602
  conversation: scope?.conversation ?? {},
3419
3603
  message: { id: message.id },
@@ -3428,14 +3612,15 @@ function MessageBubble({
3428
3612
  const showTrace = message.role === "assistant" && (wasLiveRef.current || message.parts.some(
3429
3613
  (part) => part.type === "thinking" || part.type === "tool-call" || part.type === "tool-result"
3430
3614
  ));
3431
- return /* @__PURE__ */ jsxs9(
3615
+ const showTime = message.role === "assistant" && !live && message.createdAt !== void 0;
3616
+ return /* @__PURE__ */ jsxs11(
3432
3617
  "div",
3433
3618
  {
3434
3619
  className: `pactor-chat-message pactor-chat-message--${message.role}`,
3435
3620
  "data-message-id": message.id,
3436
3621
  "data-message-status": message.status,
3437
3622
  children: [
3438
- editing ? /* @__PURE__ */ jsx14(
3623
+ editing ? /* @__PURE__ */ jsx15(
3439
3624
  MessageEditForm,
3440
3625
  {
3441
3626
  initialText: collectMessageText(message),
@@ -3445,21 +3630,53 @@ function MessageBubble({
3445
3630
  },
3446
3631
  onCancel: () => setEditing(false)
3447
3632
  }
3448
- ) : /* @__PURE__ */ jsxs9("div", { className: "pactor-chat-message__body", children: [
3449
- showTrace && /* @__PURE__ */ jsx14(ActivityTrace, { message }),
3450
- message.parts.length === 0 && message.status === "pending" && message.role !== "assistant" ? /* @__PURE__ */ jsx14("span", { className: "pactor-chat-message__pending", children: "\u2026" }) : message.parts.map((part, index) => /* @__PURE__ */ jsx14(
3451
- PartRenderer,
3452
- {
3453
- part,
3454
- runtime,
3455
- scope: bubbleScope,
3456
- streaming,
3457
- onOpenArtifact
3458
- },
3459
- part.id ?? index
3460
- ))
3633
+ ) : /* @__PURE__ */ jsxs11("div", { className: "pactor-chat-message__body", children: [
3634
+ showTrace && /* @__PURE__ */ jsx15(ActivityTrace, { message }),
3635
+ message.parts.length === 0 && message.status === "pending" && message.role !== "assistant" ? /* @__PURE__ */ jsx15("span", { className: "pactor-chat-message__pending", children: "\u2026" }) : groupArtifactParts(message.parts).map(
3636
+ (segment, index) => Array.isArray(segment) ? /* @__PURE__ */ jsx15(
3637
+ ChromeSlot,
3638
+ {
3639
+ fragment: buildArtifactCardGroupFragment(segment),
3640
+ components: ARTIFACT_CARD_INTERNAL_COMPONENTS,
3641
+ fallback: /* @__PURE__ */ jsx15(ChatArtifactCardGroup, { artifacts: segment })
3642
+ },
3643
+ `artifacts:${segment[0].id}`
3644
+ ) : /* @__PURE__ */ jsx15(
3645
+ PartRenderer,
3646
+ {
3647
+ part: segment,
3648
+ runtime,
3649
+ scope: bubbleScope,
3650
+ streaming
3651
+ },
3652
+ segment.id ?? index
3653
+ )
3654
+ )
3461
3655
  ] }),
3462
- !editing && /* @__PURE__ */ jsx14(
3656
+ !editing && (showTime ? /* @__PURE__ */ jsxs11("div", { className: "pactor-chat-message__footer", children: [
3657
+ /* @__PURE__ */ jsx15(
3658
+ MessageActions,
3659
+ {
3660
+ message,
3661
+ actions: messageActions,
3662
+ showRegenerate,
3663
+ onRegenerate,
3664
+ onRetry,
3665
+ onEdit: onEditResend ? () => setEditing(true) : void 0,
3666
+ forceVisible: message.status === "error",
3667
+ callService,
3668
+ onMessageAction
3669
+ }
3670
+ ),
3671
+ /* @__PURE__ */ jsx15(
3672
+ "span",
3673
+ {
3674
+ className: "pactor-chat-message__time",
3675
+ title: new Date(message.createdAt).toLocaleString(),
3676
+ children: formatMessageTime(message.createdAt)
3677
+ }
3678
+ )
3679
+ ] }) : /* @__PURE__ */ jsx15(
3463
3680
  MessageActions,
3464
3681
  {
3465
3682
  message,
@@ -3472,14 +3689,14 @@ function MessageBubble({
3472
3689
  callService,
3473
3690
  onMessageAction
3474
3691
  }
3475
- )
3692
+ ))
3476
3693
  ]
3477
3694
  }
3478
3695
  );
3479
3696
  }
3480
3697
 
3481
3698
  // src/view/ChatView.tsx
3482
- import { jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
3699
+ import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
3483
3700
  function lastContentLength(messages) {
3484
3701
  const last = messages[messages.length - 1];
3485
3702
  if (!last) {
@@ -3507,6 +3724,7 @@ function ChatView({
3507
3724
  className,
3508
3725
  onArtifact,
3509
3726
  onOpenArtifact,
3727
+ onOpenArtifactList,
3510
3728
  attachments,
3511
3729
  onAttachmentsChange,
3512
3730
  onAttachFiles,
@@ -3587,7 +3805,7 @@ function ChatView({
3587
3805
  model,
3588
3806
  onModelChange
3589
3807
  });
3590
- const [contextChips, setContextChips] = useState13([]);
3808
+ const [contextChips, setContextChips] = useState14([]);
3591
3809
  const handleContextChipsChange = (chips) => {
3592
3810
  setContextChips(chips);
3593
3811
  onContextsChange?.(chips);
@@ -3623,10 +3841,13 @@ function ChatView({
3623
3841
  handleSendRef.current = handleSend;
3624
3842
  const onOpenArtifactRef = useRef11(onOpenArtifact);
3625
3843
  onOpenArtifactRef.current = onOpenArtifact;
3844
+ const onOpenArtifactListRef = useRef11(onOpenArtifactList);
3845
+ onOpenArtifactListRef.current = onOpenArtifactList;
3626
3846
  useEffect9(() => {
3627
3847
  setChatChromeHandlers({
3628
3848
  sendSuggestion: (text) => handleSendRef.current(text),
3629
- openArtifact: (artifact) => onOpenArtifactRef.current?.(artifact)
3849
+ openArtifact: (artifact) => onOpenArtifactRef.current?.(artifact),
3850
+ openArtifactList: () => onOpenArtifactListRef.current?.()
3630
3851
  });
3631
3852
  }, []);
3632
3853
  const handleRegenerate = () => {
@@ -3646,7 +3867,7 @@ function ChatView({
3646
3867
  const lastMessage = messages[messages.length - 1];
3647
3868
  const regenerableMessageId = lastMessage?.role === "assistant" && lastMessage.status === "completed" ? lastMessage.id : void 0;
3648
3869
  const isEmpty = messages.length === 0;
3649
- const composerNode = /* @__PURE__ */ jsx15(
3870
+ const composerNode = /* @__PURE__ */ jsx16(
3650
3871
  Composer,
3651
3872
  {
3652
3873
  onSend: handleSend,
@@ -3671,18 +3892,18 @@ function ChatView({
3671
3892
  callService
3672
3893
  }
3673
3894
  );
3674
- const composerDock = /* @__PURE__ */ jsxs10("div", { className: "pactor-chat-view__composer-dock", children: [
3895
+ const composerDock = /* @__PURE__ */ jsxs12("div", { className: "pactor-chat-view__composer-dock", children: [
3675
3896
  composerNode,
3676
- composerBottom !== void 0 && composerBottom !== null ? /* @__PURE__ */ jsx15("div", { className: "pactor-chat-view__composer-bottom", children: composerBottom }) : null
3897
+ composerBottom !== void 0 && composerBottom !== null ? /* @__PURE__ */ jsx16("div", { className: "pactor-chat-view__composer-bottom", children: composerBottom }) : null
3677
3898
  ] });
3678
- return /* @__PURE__ */ jsxs10(
3899
+ return /* @__PURE__ */ jsxs12(
3679
3900
  "div",
3680
3901
  {
3681
3902
  className: `pactor-chat-view${isEmpty ? " pactor-chat-view--empty" : ""}${className ? ` ${className}` : ""}`,
3682
3903
  children: [
3683
- /* @__PURE__ */ jsxs10("div", { className: "pactor-chat-messages", ref: containerRef, children: [
3684
- isEmpty ? /* @__PURE__ */ jsxs10("div", { className: "pactor-chat-view__empty-stack", children: [
3685
- /* @__PURE__ */ jsx15(
3904
+ /* @__PURE__ */ jsxs12("div", { className: "pactor-chat-messages", ref: containerRef, children: [
3905
+ isEmpty ? /* @__PURE__ */ jsxs12("div", { className: "pactor-chat-view__empty-stack", children: [
3906
+ /* @__PURE__ */ jsx16(
3686
3907
  EmptyState,
3687
3908
  {
3688
3909
  greeting,
@@ -3692,7 +3913,7 @@ function ChatView({
3692
3913
  }
3693
3914
  ),
3694
3915
  composerDock
3695
- ] }) : messages.map((message) => /* @__PURE__ */ jsx15(
3916
+ ] }) : messages.map((message) => /* @__PURE__ */ jsx16(
3696
3917
  MessageBubble,
3697
3918
  {
3698
3919
  message,
@@ -3704,19 +3925,18 @@ function ChatView({
3704
3925
  onEditResend: (text) => handleEditResend(message.id, text),
3705
3926
  messageActions,
3706
3927
  callService,
3707
- onMessageAction,
3708
- onOpenArtifact
3928
+ onMessageAction
3709
3929
  },
3710
3930
  message.id
3711
3931
  )),
3712
- !isFollowing && /* @__PURE__ */ jsxs10(
3932
+ !isFollowing && /* @__PURE__ */ jsxs12(
3713
3933
  "button",
3714
3934
  {
3715
3935
  type: "button",
3716
3936
  className: "pactor-chat-scroll-bottom",
3717
3937
  onClick: scrollToBottom,
3718
3938
  children: [
3719
- /* @__PURE__ */ jsx15(Icon9, { name: "arrow-down", size: 13 }),
3939
+ /* @__PURE__ */ jsx16(Icon10, { name: "arrow-down", size: 13 }),
3720
3940
  "\u56DE\u5230\u5E95\u90E8"
3721
3941
  ]
3722
3942
  }
@@ -3729,8 +3949,8 @@ function ChatView({
3729
3949
  }
3730
3950
 
3731
3951
  // src/view/WorkspaceHeader.tsx
3732
- import { Icon as Icon10 } from "@pactor-app/ui/components";
3733
- import { useEffect as useEffect10, useRef as useRef12, useState as useState14 } from "react";
3952
+ import { Icon as Icon11 } from "@pactor-app/ui/components";
3953
+ import { useEffect as useEffect10, useRef as useRef12, useState as useState15 } from "react";
3734
3954
 
3735
3955
  // src/export-markdown.ts
3736
3956
  var ROLE_LABELS = {
@@ -3807,7 +4027,7 @@ function buildHeaderActionsFragment(props) {
3807
4027
  }
3808
4028
 
3809
4029
  // src/view/WorkspaceHeader.tsx
3810
- import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
4030
+ import { jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
3811
4031
  function readCurrentTheme() {
3812
4032
  if (typeof document === "undefined") {
3813
4033
  return "light";
@@ -3827,9 +4047,9 @@ function WorkspaceHeader({
3827
4047
  onTitleChange
3828
4048
  }) {
3829
4049
  const hasActions = headerActions !== void 0 && headerActions.length > 0;
3830
- const [overrideTitle, setOverrideTitle] = useState14(null);
3831
- const [editing, setEditing] = useState14(false);
3832
- const [draft, setDraft] = useState14("");
4050
+ const [overrideTitle, setOverrideTitle] = useState15(null);
4051
+ const [editing, setEditing] = useState15(false);
4052
+ const [draft, setDraft] = useState15("");
3833
4053
  const prevTitleRef = useRef12(title);
3834
4054
  if (prevTitleRef.current !== title) {
3835
4055
  prevTitleRef.current = title;
@@ -3838,7 +4058,7 @@ function WorkspaceHeader({
3838
4058
  }
3839
4059
  }
3840
4060
  const displayTitle = overrideTitle ?? title;
3841
- const [theme, setTheme] = useState14(readCurrentTheme);
4061
+ const [theme, setTheme] = useState15(readCurrentTheme);
3842
4062
  const commitTitle = () => {
3843
4063
  setEditing(false);
3844
4064
  const next = draft.trim();
@@ -3882,7 +4102,7 @@ function WorkspaceHeader({
3882
4102
  });
3883
4103
  }, []);
3884
4104
  const actionButtons = {
3885
- export: /* @__PURE__ */ jsx16(
4105
+ export: /* @__PURE__ */ jsx17(
3886
4106
  "button",
3887
4107
  {
3888
4108
  type: "button",
@@ -3890,11 +4110,11 @@ function WorkspaceHeader({
3890
4110
  title: "\u5BFC\u51FA Markdown",
3891
4111
  "aria-label": "\u5BFC\u51FA Markdown",
3892
4112
  onClick: handleExport,
3893
- children: /* @__PURE__ */ jsx16(Icon10, { name: "download", size: 15 })
4113
+ children: /* @__PURE__ */ jsx17(Icon11, { name: "download", size: 15 })
3894
4114
  },
3895
4115
  "export"
3896
4116
  ),
3897
- theme: /* @__PURE__ */ jsx16(
4117
+ theme: /* @__PURE__ */ jsx17(
3898
4118
  "button",
3899
4119
  {
3900
4120
  type: "button",
@@ -3902,11 +4122,11 @@ function WorkspaceHeader({
3902
4122
  title: theme === "dark" ? "\u5207\u6362\u4E3A\u6D45\u8272" : "\u5207\u6362\u4E3A\u6DF1\u8272",
3903
4123
  "aria-label": "\u5207\u6362\u660E\u6697\u4E3B\u9898",
3904
4124
  onClick: handleTheme,
3905
- children: theme === "dark" ? /* @__PURE__ */ jsx16(Icon10, { name: "sun", size: 15 }) : /* @__PURE__ */ jsx16(Icon10, { name: "moon", size: 15 })
4125
+ children: theme === "dark" ? /* @__PURE__ */ jsx17(Icon11, { name: "sun", size: 15 }) : /* @__PURE__ */ jsx17(Icon11, { name: "moon", size: 15 })
3906
4126
  },
3907
4127
  "theme"
3908
4128
  ),
3909
- clear: /* @__PURE__ */ jsx16(
4129
+ clear: /* @__PURE__ */ jsx17(
3910
4130
  "button",
3911
4131
  {
3912
4132
  type: "button",
@@ -3914,12 +4134,12 @@ function WorkspaceHeader({
3914
4134
  title: "\u6E05\u7A7A\u4F1A\u8BDD",
3915
4135
  "aria-label": "\u6E05\u7A7A\u4F1A\u8BDD",
3916
4136
  onClick: handleClear,
3917
- children: /* @__PURE__ */ jsx16(Icon10, { name: "trash", size: 15 })
4137
+ children: /* @__PURE__ */ jsx17(Icon11, { name: "trash", size: 15 })
3918
4138
  },
3919
4139
  "clear"
3920
4140
  )
3921
4141
  };
3922
- const titleNode = editableTitle ? editing ? /* @__PURE__ */ jsx16(
4142
+ const titleNode = editableTitle ? editing ? /* @__PURE__ */ jsx17(
3923
4143
  "input",
3924
4144
  {
3925
4145
  className: "pactor-chat-workspace__title-input",
@@ -3936,7 +4156,7 @@ function WorkspaceHeader({
3936
4156
  }
3937
4157
  }
3938
4158
  }
3939
- ) : /* @__PURE__ */ jsx16(
4159
+ ) : /* @__PURE__ */ jsx17(
3940
4160
  "button",
3941
4161
  {
3942
4162
  type: "button",
@@ -3948,17 +4168,17 @@ function WorkspaceHeader({
3948
4168
  },
3949
4169
  children: displayTitle
3950
4170
  }
3951
- ) : /* @__PURE__ */ jsx16("div", { className: "pactor-chat-workspace__title", children: title });
3952
- return /* @__PURE__ */ jsxs11("header", { className: "pactor-chat-workspace__header", children: [
4171
+ ) : /* @__PURE__ */ jsx17("div", { className: "pactor-chat-workspace__title", children: title });
4172
+ return /* @__PURE__ */ jsxs13("header", { className: "pactor-chat-workspace__header", children: [
3953
4173
  headerStart !== void 0 ? (
3954
4174
  // header 位模型 chip(决策 D2):与 title 组成左端组,chip 在前
3955
- /* @__PURE__ */ jsxs11("div", { className: "pactor-chat-workspace__header-left", children: [
4175
+ /* @__PURE__ */ jsxs13("div", { className: "pactor-chat-workspace__header-left", children: [
3956
4176
  headerStart,
3957
4177
  titleNode
3958
4178
  ] })
3959
4179
  ) : titleNode,
3960
- hasActions ? /* @__PURE__ */ jsxs11("div", { className: "pactor-chat-workspace__header-right", children: [
3961
- /* @__PURE__ */ jsx16("div", { className: "pactor-chat-workspace__header-actions", children: /* @__PURE__ */ jsx16(
4180
+ hasActions ? /* @__PURE__ */ jsxs13("div", { className: "pactor-chat-workspace__header-right", children: [
4181
+ /* @__PURE__ */ jsx17("div", { className: "pactor-chat-workspace__header-actions", children: /* @__PURE__ */ jsx17(
3962
4182
  ChromeSlot,
3963
4183
  {
3964
4184
  fragment: buildHeaderActionsFragment({
@@ -3968,13 +4188,13 @@ function WorkspaceHeader({
3968
4188
  fallback: headerActions.map((action) => actionButtons[action])
3969
4189
  }
3970
4190
  ) }),
3971
- headerExtra !== void 0 ? /* @__PURE__ */ jsx16("div", { className: "pactor-chat-workspace__header-extra", children: headerExtra }) : null
3972
- ] }) : headerExtra !== void 0 ? /* @__PURE__ */ jsx16("div", { className: "pactor-chat-workspace__header-extra", children: headerExtra }) : null
4191
+ headerExtra !== void 0 ? /* @__PURE__ */ jsx17("div", { className: "pactor-chat-workspace__header-extra", children: headerExtra }) : null
4192
+ ] }) : headerExtra !== void 0 ? /* @__PURE__ */ jsx17("div", { className: "pactor-chat-workspace__header-extra", children: headerExtra }) : null
3973
4193
  ] });
3974
4194
  }
3975
4195
 
3976
4196
  // src/chat-composition.tsx
3977
- import { Fragment as Fragment9, jsx as jsx17, jsxs as jsxs12 } from "react/jsx-runtime";
4197
+ import { Fragment as Fragment9, jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
3978
4198
  function DslNodeSlotInner({ node }) {
3979
4199
  const { renderChildren } = useRenderer4();
3980
4200
  return renderChildren([node]);
@@ -3997,7 +4217,7 @@ var DslSlotGuard = class extends Component3 {
3997
4217
  }
3998
4218
  };
3999
4219
  function DslNodeSlot({ node }) {
4000
- return /* @__PURE__ */ jsx17(DslSlotGuard, { children: /* @__PURE__ */ jsx17(DslNodeSlotInner, { node }) });
4220
+ return /* @__PURE__ */ jsx18(DslSlotGuard, { children: /* @__PURE__ */ jsx18(DslNodeSlotInner, { node }) });
4001
4221
  }
4002
4222
  function isDslNodeValue(value) {
4003
4223
  return typeof value === "object" && value !== null && !Array.isArray(value) && !isValidElement(value) && typeof value.type === "string";
@@ -4007,7 +4227,7 @@ function resolveSlot(slot) {
4007
4227
  return void 0;
4008
4228
  }
4009
4229
  if (isDslNodeValue(slot)) {
4010
- return /* @__PURE__ */ jsx17(DslNodeSlot, { node: slot });
4230
+ return /* @__PURE__ */ jsx18(DslNodeSlot, { node: slot });
4011
4231
  }
4012
4232
  return slot;
4013
4233
  }
@@ -4051,7 +4271,8 @@ function ChatComposition({
4051
4271
  onPanelClose,
4052
4272
  inspector,
4053
4273
  onArtifact,
4054
- onOpenArtifact
4274
+ onOpenArtifact,
4275
+ onOpenArtifactList
4055
4276
  }) {
4056
4277
  const storeRef = useRef13(null);
4057
4278
  if (storeRef.current === null) {
@@ -4102,7 +4323,18 @@ function ChatComposition({
4102
4323
  artifactStore.open(next);
4103
4324
  }
4104
4325
  };
4105
- const [attachments, setAttachments] = useState15([]);
4326
+ const [listViewRequest, setListViewRequest] = useState16(null);
4327
+ const handleOpenArtifactList = () => {
4328
+ onOpenArtifactList?.();
4329
+ setListViewRequest((value) => (value ?? 0) + 1);
4330
+ if (!panelControlled && artifactStore.get() === null) {
4331
+ const first = mergedArtifacts[0];
4332
+ if (first !== void 0) {
4333
+ artifactStore.open(first);
4334
+ }
4335
+ }
4336
+ };
4337
+ const [attachments, setAttachments] = useState16([]);
4106
4338
  const handleAttachFiles = services.onAttachFiles ? (files) => {
4107
4339
  void Promise.resolve(services.onAttachFiles(files)).then(
4108
4340
  (created) => {
@@ -4122,7 +4354,7 @@ function ChatComposition({
4122
4354
  model,
4123
4355
  onModelChange
4124
4356
  });
4125
- const headerModelChip = modelPlacement === "header" && modelsEnabled ? /* @__PURE__ */ jsx17(
4357
+ const headerModelChip = modelPlacement === "header" && modelsEnabled ? /* @__PURE__ */ jsx18(
4126
4358
  ModelSelect,
4127
4359
  {
4128
4360
  models,
@@ -4130,96 +4362,101 @@ function ChatComposition({
4130
4362
  onModelChange: handleModelChange
4131
4363
  }
4132
4364
  ) : void 0;
4133
- const mergedToolbarEnd = services.toolbarEnd !== void 0 || toolbarEnd !== void 0 ? /* @__PURE__ */ jsxs12(Fragment9, { children: [
4365
+ const mergedToolbarEnd = services.toolbarEnd !== void 0 || toolbarEnd !== void 0 ? /* @__PURE__ */ jsxs14(Fragment9, { children: [
4134
4366
  services.toolbarEnd,
4135
4367
  toolbarEnd
4136
4368
  ] }) : void 0;
4137
- const mergedToolbarStart = services.toolbarStart !== void 0 || toolbarStart !== void 0 ? /* @__PURE__ */ jsxs12(Fragment9, { children: [
4369
+ const mergedToolbarStart = services.toolbarStart !== void 0 || toolbarStart !== void 0 ? /* @__PURE__ */ jsxs14(Fragment9, { children: [
4138
4370
  services.toolbarStart,
4139
4371
  toolbarStart
4140
4372
  ] }) : void 0;
4141
- const mergedComposerFooter = services.composerFooter !== void 0 || composerFooter !== void 0 ? /* @__PURE__ */ jsxs12(Fragment9, { children: [
4373
+ const mergedComposerFooter = services.composerFooter !== void 0 || composerFooter !== void 0 ? /* @__PURE__ */ jsxs14(Fragment9, { children: [
4142
4374
  services.composerFooter,
4143
4375
  composerFooter
4144
4376
  ] }) : void 0;
4145
- const mergedComposerBottom = services.composerBottom !== void 0 || composerBottom !== void 0 ? /* @__PURE__ */ jsxs12(Fragment9, { children: [
4377
+ const mergedComposerBottom = services.composerBottom !== void 0 || composerBottom !== void 0 ? /* @__PURE__ */ jsxs14(Fragment9, { children: [
4146
4378
  services.composerBottom,
4147
4379
  composerBottom
4148
4380
  ] }) : void 0;
4149
4381
  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;
4150
4382
  const renderHeader = showHeader !== false && hasHeaderContent;
4151
- const workspace = /* @__PURE__ */ jsxs12(
4383
+ const workspaceHeader = renderHeader ? header ?? /* @__PURE__ */ jsx18(
4384
+ WorkspaceHeader,
4385
+ {
4386
+ title,
4387
+ headerExtra,
4388
+ headerActions,
4389
+ editableTitle,
4390
+ headerStart: headerModelChip,
4391
+ store,
4392
+ onExport,
4393
+ onThemeChange,
4394
+ onClear,
4395
+ onTitleChange
4396
+ }
4397
+ ) : null;
4398
+ const workspace = /* @__PURE__ */ jsx18(
4152
4399
  "div",
4153
4400
  {
4154
4401
  className: `pactor-chat-workspace${className ? ` ${className}` : ""}`,
4155
- children: [
4156
- renderHeader ? header ?? /* @__PURE__ */ jsx17(
4157
- WorkspaceHeader,
4158
- {
4159
- title,
4160
- headerExtra,
4161
- headerActions,
4162
- editableTitle,
4163
- headerStart: headerModelChip,
4164
- store,
4165
- onExport,
4166
- onThemeChange,
4167
- onClear,
4168
- onTitleChange
4169
- }
4170
- ) : null,
4171
- /* @__PURE__ */ jsx17(
4172
- ChatView,
4173
- {
4174
- store,
4175
- transport: services.transport,
4176
- onSend: handleSend,
4177
- safeRegistry: services.safeRegistry,
4178
- capabilities: services.capabilities,
4179
- permission: services.permission,
4180
- confirm: services.confirm,
4181
- conversationId,
4182
- user: services.user,
4183
- params,
4184
- greeting,
4185
- subtitle,
4186
- suggestions,
4187
- attachments,
4188
- onAttachmentsChange: setAttachments,
4189
- onAttachFiles: handleAttachFiles,
4190
- onAttachmentClick: services.onAttachmentClick,
4191
- toolbarStart: mergedToolbarStart,
4192
- toolbarEnd: mergedToolbarEnd,
4193
- composerFooter: mergedComposerFooter,
4194
- composerBottom: mergedComposerBottom,
4195
- hideToolbar,
4196
- onMentionTrigger: services.onMentionTrigger,
4197
- onPlusMenu: services.onPlusMenu,
4198
- onArtifact,
4199
- onOpenArtifact: handleOpenArtifact,
4200
- models,
4201
- model: currentModel,
4202
- onModelChange: handleModelChange,
4203
- modelPlacement,
4204
- contexts,
4205
- onContextsChange,
4206
- callService: services.callService,
4207
- messageActions,
4208
- onMessageAction
4209
- }
4210
- )
4211
- ]
4402
+ children: /* @__PURE__ */ jsx18(
4403
+ ChatView,
4404
+ {
4405
+ store,
4406
+ transport: services.transport,
4407
+ onSend: handleSend,
4408
+ safeRegistry: services.safeRegistry,
4409
+ capabilities: services.capabilities,
4410
+ permission: services.permission,
4411
+ confirm: services.confirm,
4412
+ conversationId,
4413
+ user: services.user,
4414
+ params,
4415
+ greeting,
4416
+ subtitle,
4417
+ suggestions,
4418
+ attachments,
4419
+ onAttachmentsChange: setAttachments,
4420
+ onAttachFiles: handleAttachFiles,
4421
+ onAttachmentClick: services.onAttachmentClick,
4422
+ toolbarStart: mergedToolbarStart,
4423
+ toolbarEnd: mergedToolbarEnd,
4424
+ composerFooter: mergedComposerFooter,
4425
+ composerBottom: mergedComposerBottom,
4426
+ hideToolbar,
4427
+ onMentionTrigger: services.onMentionTrigger,
4428
+ onPlusMenu: services.onPlusMenu,
4429
+ onArtifact,
4430
+ onOpenArtifact: handleOpenArtifact,
4431
+ onOpenArtifactList: handleOpenArtifactList,
4432
+ models,
4433
+ model: currentModel,
4434
+ onModelChange: handleModelChange,
4435
+ modelPlacement,
4436
+ contexts,
4437
+ onContextsChange,
4438
+ callService: services.callService,
4439
+ messageActions,
4440
+ onMessageAction
4441
+ }
4442
+ )
4212
4443
  }
4213
4444
  );
4214
- const main = sidebar ? /* @__PURE__ */ jsx17(AppShell, { sidebar, children: workspace }) : workspace;
4215
- const panelFeatureUsed = artifact !== void 0 || panelOpen !== void 0 || inspector !== void 0 || onPanelClose !== void 0 || onArtifact !== void 0 || onOpenArtifact !== void 0 || services.artifactStore !== void 0;
4445
+ const main = sidebar ? /* @__PURE__ */ jsx18(AppShell, { sidebar, children: workspace }) : workspace;
4446
+ 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;
4216
4447
  if (!panelFeatureUsed && !effectivePanelOpen) {
4217
- return main;
4448
+ return workspaceHeader ? /* @__PURE__ */ jsxs14("div", { className: "pactor-chat-with-header", children: [
4449
+ workspaceHeader,
4450
+ main
4451
+ ] }) : main;
4218
4452
  }
4219
- return /* @__PURE__ */ jsxs12("div", { className: "pactor-chat-inspector-host", children: [
4220
- main,
4221
- effectivePanelOpen ? /* @__PURE__ */ jsxs12(Fragment9, { children: [
4222
- /* @__PURE__ */ jsx17(
4453
+ return /* @__PURE__ */ jsx18("div", { className: "pactor-chat-inspector-host", children: /* @__PURE__ */ jsxs14("div", { className: "pactor-chat-inspector-host__row", children: [
4454
+ /* @__PURE__ */ jsxs14("div", { className: "pactor-chat-inspector-host__main", children: [
4455
+ workspaceHeader,
4456
+ main
4457
+ ] }),
4458
+ effectivePanelOpen ? /* @__PURE__ */ jsxs14(Fragment9, { children: [
4459
+ /* @__PURE__ */ jsx18(
4223
4460
  "div",
4224
4461
  {
4225
4462
  className: "pactor-chat-inspector__scrim",
@@ -4227,7 +4464,7 @@ function ChatComposition({
4227
4464
  onClick: handlePanelClose
4228
4465
  }
4229
4466
  ),
4230
- /* @__PURE__ */ jsx17(
4467
+ /* @__PURE__ */ jsx18(
4231
4468
  ArtifactPanel,
4232
4469
  {
4233
4470
  artifact: effectiveArtifact,
@@ -4238,29 +4475,31 @@ function ChatComposition({
4238
4475
  onClose: handlePanelClose,
4239
4476
  safeRegistry: services.safeRegistry,
4240
4477
  user: services.user,
4241
- artifactViewers: services.artifactViewers
4478
+ artifactViewers: services.artifactViewers,
4479
+ viewRequest: listViewRequest,
4480
+ onViewRequestConsumed: () => setListViewRequest(null)
4242
4481
  }
4243
4482
  )
4244
4483
  ] }) : null
4245
- ] });
4484
+ ] }) });
4246
4485
  }
4247
4486
 
4248
4487
  // src/chat-services.tsx
4249
- import { createContext as createContext2, useContext as useContext2 } from "react";
4250
- import { jsx as jsx18 } from "react/jsx-runtime";
4251
- var ChatServicesContext = createContext2(null);
4488
+ import { createContext as createContext3, useContext as useContext3 } from "react";
4489
+ import { jsx as jsx19 } from "react/jsx-runtime";
4490
+ var ChatServicesContext = createContext3(null);
4252
4491
  function ChatServicesProvider({
4253
4492
  value,
4254
4493
  children
4255
4494
  }) {
4256
- return /* @__PURE__ */ jsx18(ChatServicesContext.Provider, { value, children });
4495
+ return /* @__PURE__ */ jsx19(ChatServicesContext.Provider, { value, children });
4257
4496
  }
4258
4497
  function useChatServices() {
4259
- return useContext2(ChatServicesContext);
4498
+ return useContext3(ChatServicesContext);
4260
4499
  }
4261
4500
 
4262
4501
  // src/chat-workspace.tsx
4263
- import { jsx as jsx19 } from "react/jsx-runtime";
4502
+ import { jsx as jsx20 } from "react/jsx-runtime";
4264
4503
  function createChatWorkspace(services) {
4265
4504
  function ChatWorkspace({
4266
4505
  title,
@@ -4281,6 +4520,7 @@ function createChatWorkspace(services) {
4281
4520
  inspector,
4282
4521
  onArtifact,
4283
4522
  onOpenArtifact,
4523
+ onOpenArtifactList,
4284
4524
  onSelectArtifact,
4285
4525
  headerActions,
4286
4526
  editableTitle,
@@ -4298,7 +4538,7 @@ function createChatWorkspace(services) {
4298
4538
  onMessageAction,
4299
4539
  className
4300
4540
  }) {
4301
- return /* @__PURE__ */ jsx19(ChatServicesProvider, { value: services, children: /* @__PURE__ */ jsx19(
4541
+ return /* @__PURE__ */ jsx20(ChatServicesProvider, { value: services, children: /* @__PURE__ */ jsx20(
4302
4542
  ChatComposition,
4303
4543
  {
4304
4544
  services,
@@ -4310,18 +4550,19 @@ function createChatWorkspace(services) {
4310
4550
  params,
4311
4551
  className,
4312
4552
  headerExtra: services.headerExtra,
4313
- sidebar: sidebar ? /* @__PURE__ */ jsx19(DslNodeSlot, { node: sidebar }) : void 0,
4314
- toolbarStart: toolbarStart ? /* @__PURE__ */ jsx19(DslNodeSlot, { node: toolbarStart }) : void 0,
4315
- toolbarEnd: toolbarEnd ? /* @__PURE__ */ jsx19(DslNodeSlot, { node: toolbarEnd }) : void 0,
4316
- composerFooter: composerFooter ? /* @__PURE__ */ jsx19(DslNodeSlot, { node: composerFooter }) : void 0,
4317
- composerBottom: composerBottom ? /* @__PURE__ */ jsx19(DslNodeSlot, { node: composerBottom }) : void 0,
4553
+ sidebar: sidebar ? /* @__PURE__ */ jsx20(DslNodeSlot, { node: sidebar }) : void 0,
4554
+ toolbarStart: toolbarStart ? /* @__PURE__ */ jsx20(DslNodeSlot, { node: toolbarStart }) : void 0,
4555
+ toolbarEnd: toolbarEnd ? /* @__PURE__ */ jsx20(DslNodeSlot, { node: toolbarEnd }) : void 0,
4556
+ composerFooter: composerFooter ? /* @__PURE__ */ jsx20(DslNodeSlot, { node: composerFooter }) : void 0,
4557
+ composerBottom: composerBottom ? /* @__PURE__ */ jsx20(DslNodeSlot, { node: composerBottom }) : void 0,
4318
4558
  hideToolbar,
4319
4559
  artifact,
4320
4560
  panelOpen,
4321
4561
  onPanelClose,
4322
- inspector: inspector ? /* @__PURE__ */ jsx19(DslNodeSlot, { node: inspector }) : void 0,
4562
+ inspector: inspector ? /* @__PURE__ */ jsx20(DslNodeSlot, { node: inspector }) : void 0,
4323
4563
  onArtifact,
4324
4564
  onOpenArtifact,
4565
+ onOpenArtifactList,
4325
4566
  onSelectArtifact,
4326
4567
  headerActions,
4327
4568
  editableTitle,
@@ -4344,7 +4585,7 @@ function createChatWorkspace(services) {
4344
4585
  }
4345
4586
 
4346
4587
  // src/view/Chat.tsx
4347
- import { createComponentRegistry, Icon as Icon11, RailTooltip } from "@pactor-app/ui/components";
4588
+ import { createComponentRegistry, Icon as Icon12, RailTooltip } from "@pactor-app/ui/components";
4348
4589
  import { Fragment as Fragment10, useEffect as useEffect11, useRef as useRef14 } from "react";
4349
4590
 
4350
4591
  // src/view/chrome/menu.tsx
@@ -4374,7 +4615,7 @@ function buildSidebarMenuFragment(props) {
4374
4615
  }
4375
4616
 
4376
4617
  // src/view/ChatShell.tsx
4377
- import { jsx as jsx20 } from "react/jsx-runtime";
4618
+ import { jsx as jsx21 } from "react/jsx-runtime";
4378
4619
  function ChatShell({
4379
4620
  menu,
4380
4621
  activeMenuKey,
@@ -4386,7 +4627,7 @@ function ChatShell({
4386
4627
  className,
4387
4628
  onMenuSelect
4388
4629
  }) {
4389
- const sidebarContent = resolveSlot(sidebar) ?? (menu && menu.length > 0 ? /* @__PURE__ */ jsx20(
4630
+ const sidebarContent = resolveSlot(sidebar) ?? (menu && menu.length > 0 ? /* @__PURE__ */ jsx21(
4390
4631
  ChatSidebarMenu,
4391
4632
  {
4392
4633
  menu,
@@ -4394,7 +4635,7 @@ function ChatShell({
4394
4635
  onMenuSelect
4395
4636
  }
4396
4637
  ) : null);
4397
- return /* @__PURE__ */ jsx20(
4638
+ return /* @__PURE__ */ jsx21(
4398
4639
  AppShell,
4399
4640
  {
4400
4641
  sidebar: sidebarContent,
@@ -4411,7 +4652,7 @@ function ChatShellDslAdapter({
4411
4652
  onMenuSelect,
4412
4653
  ...rest
4413
4654
  }) {
4414
- return /* @__PURE__ */ jsx20(
4655
+ return /* @__PURE__ */ jsx21(
4415
4656
  ChatShell,
4416
4657
  {
4417
4658
  ...rest,
@@ -4426,7 +4667,7 @@ function registerChatShellComponent(registry) {
4426
4667
  }
4427
4668
 
4428
4669
  // src/view/Chat.tsx
4429
- import { jsx as jsx21, jsxs as jsxs13 } from "react/jsx-runtime";
4670
+ import { jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
4430
4671
  function ChatSidebarMenu({
4431
4672
  menu,
4432
4673
  activeMenuKey,
@@ -4453,12 +4694,12 @@ function ChatSidebarMenu({
4453
4694
  }, []);
4454
4695
  const fallback = (() => {
4455
4696
  let lastGroup;
4456
- return /* @__PURE__ */ jsx21("nav", { className: "pactor-chat-menu", "aria-label": "\u4F1A\u8BDD\u5BFC\u822A", children: menu.map((item) => {
4697
+ return /* @__PURE__ */ jsx22("nav", { className: "pactor-chat-menu", "aria-label": "\u4F1A\u8BDD\u5BFC\u822A", children: menu.map((item) => {
4457
4698
  const groupLabel = item.group !== void 0 && item.group !== lastGroup ? item.group : void 0;
4458
4699
  lastGroup = item.group;
4459
4700
  const active = item.key === activeMenuKey;
4460
4701
  const collapsed = drawer?.collapsed === true;
4461
- const button = /* @__PURE__ */ jsxs13(
4702
+ const button = /* @__PURE__ */ jsxs15(
4462
4703
  "button",
4463
4704
  {
4464
4705
  type: "button",
@@ -4473,20 +4714,20 @@ function ChatSidebarMenu({
4473
4714
  drawer?.close();
4474
4715
  },
4475
4716
  children: [
4476
- item.icon !== void 0 ? /* @__PURE__ */ jsx21("span", { className: "pactor-chat-menu__icon", children: /* @__PURE__ */ jsx21(Icon11, { name: item.icon, size: 15, strokeWidth: 1.7 }) }) : null,
4477
- /* @__PURE__ */ jsx21("span", { className: "pactor-chat-menu__label", children: item.label }),
4478
- item.dot === true ? /* @__PURE__ */ jsx21("span", { className: "pactor-chat-menu__dot", "aria-hidden": true }) : null,
4479
- item.badge !== void 0 ? /* @__PURE__ */ jsx21("span", { className: "pactor-chat-menu__badge", children: item.badge }) : null
4717
+ item.icon !== void 0 ? /* @__PURE__ */ jsx22("span", { className: "pactor-chat-menu__icon", children: /* @__PURE__ */ jsx22(Icon12, { name: item.icon, size: 15, strokeWidth: 1.7 }) }) : null,
4718
+ /* @__PURE__ */ jsx22("span", { className: "pactor-chat-menu__label", children: item.label }),
4719
+ item.dot === true ? /* @__PURE__ */ jsx22("span", { className: "pactor-chat-menu__dot", "aria-hidden": true }) : null,
4720
+ item.badge !== void 0 ? /* @__PURE__ */ jsx22("span", { className: "pactor-chat-menu__badge", children: item.badge }) : null
4480
4721
  ]
4481
4722
  }
4482
4723
  );
4483
- return /* @__PURE__ */ jsxs13(Fragment10, { children: [
4484
- groupLabel !== void 0 ? /* @__PURE__ */ jsx21("div", { className: "pactor-chat-menu__group", children: groupLabel }) : null,
4485
- collapsed ? /* @__PURE__ */ jsx21(RailTooltip, { label: item.label, children: button }) : button
4724
+ return /* @__PURE__ */ jsxs15(Fragment10, { children: [
4725
+ groupLabel !== void 0 ? /* @__PURE__ */ jsx22("div", { className: "pactor-chat-menu__group", children: groupLabel }) : null,
4726
+ collapsed ? /* @__PURE__ */ jsx22(RailTooltip, { label: item.label, children: button }) : button
4486
4727
  ] }, item.key);
4487
4728
  }) });
4488
4729
  })();
4489
- return /* @__PURE__ */ jsx21(
4730
+ return /* @__PURE__ */ jsx22(
4490
4731
  ChromeSlot,
4491
4732
  {
4492
4733
  fragment: buildSidebarMenuFragment({ menu, activeMenuKey }),
@@ -4532,6 +4773,7 @@ function Chat({
4532
4773
  inspector,
4533
4774
  onArtifact,
4534
4775
  onOpenArtifact,
4776
+ onOpenArtifactList,
4535
4777
  onSelectArtifact,
4536
4778
  className,
4537
4779
  onSend,
@@ -4546,10 +4788,10 @@ function Chat({
4546
4788
  }
4547
4789
  }, [services]);
4548
4790
  if (!services) {
4549
- return /* @__PURE__ */ jsx21("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" });
4791
+ return /* @__PURE__ */ jsx22("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" });
4550
4792
  }
4551
4793
  const sidebarSlot = resolveSlot(sidebar);
4552
- const sidebarContent = sidebarSlot ?? (menu && menu.length > 0 ? /* @__PURE__ */ jsx21(
4794
+ const sidebarContent = sidebarSlot ?? (menu && menu.length > 0 ? /* @__PURE__ */ jsx22(
4553
4795
  ChatSidebarMenu,
4554
4796
  {
4555
4797
  menu,
@@ -4557,7 +4799,7 @@ function Chat({
4557
4799
  onMenuSelect
4558
4800
  }
4559
4801
  ) : void 0);
4560
- return /* @__PURE__ */ jsx21(
4802
+ return /* @__PURE__ */ jsx22(
4561
4803
  ChatComposition,
4562
4804
  {
4563
4805
  services,
@@ -4598,6 +4840,7 @@ function Chat({
4598
4840
  inspector: resolveSlot(inspector),
4599
4841
  onArtifact,
4600
4842
  onOpenArtifact,
4843
+ onOpenArtifactList,
4601
4844
  onSelectArtifact
4602
4845
  }
4603
4846
  );
@@ -4609,6 +4852,7 @@ function ChatDslAdapter({
4609
4852
  onPanelClose,
4610
4853
  onArtifact,
4611
4854
  onOpenArtifact,
4855
+ onOpenArtifactList,
4612
4856
  onSelectArtifact,
4613
4857
  onModelChange,
4614
4858
  onContextsChange,
@@ -4619,7 +4863,7 @@ function ChatDslAdapter({
4619
4863
  onTitleChange,
4620
4864
  ...rest
4621
4865
  }) {
4622
- return /* @__PURE__ */ jsx21(
4866
+ return /* @__PURE__ */ jsx22(
4623
4867
  Chat,
4624
4868
  {
4625
4869
  ...rest,
@@ -4628,6 +4872,7 @@ function ChatDslAdapter({
4628
4872
  onPanelClose: onPanelClose ? () => onPanelClose({}) : void 0,
4629
4873
  onArtifact: onArtifact ? (artifact) => onArtifact({ artifact }) : void 0,
4630
4874
  onOpenArtifact: onOpenArtifact ? (artifact) => onOpenArtifact({ artifact }) : void 0,
4875
+ onOpenArtifactList: onOpenArtifactList ? () => onOpenArtifactList({}) : void 0,
4631
4876
  onSelectArtifact: onSelectArtifact ? (artifact) => onSelectArtifact({ artifact }) : void 0,
4632
4877
  onModelChange: onModelChange ? (model) => onModelChange({ model }) : void 0,
4633
4878
  onContextsChange: onContextsChange ? (contexts) => onContextsChange({ contexts }) : void 0,
@@ -4652,11 +4897,11 @@ function createChatComponentRegistry() {
4652
4897
  }
4653
4898
 
4654
4899
  // src/view/ChatLayout.tsx
4655
- import { jsx as jsx22, jsxs as jsxs14 } from "react/jsx-runtime";
4900
+ import { jsx as jsx23, jsxs as jsxs16 } from "react/jsx-runtime";
4656
4901
  function ChatLayout({ title, children }) {
4657
- return /* @__PURE__ */ jsxs14("div", { className: "pactor-chat-layout", children: [
4658
- /* @__PURE__ */ jsx22("header", { className: "pactor-chat-layout__header", children: title ?? "Chat" }),
4659
- /* @__PURE__ */ jsx22("main", { className: "pactor-chat-layout__main", children })
4902
+ return /* @__PURE__ */ jsxs16("div", { className: "pactor-chat-layout", children: [
4903
+ /* @__PURE__ */ jsx23("header", { className: "pactor-chat-layout__header", children: title ?? "Chat" }),
4904
+ /* @__PURE__ */ jsx23("main", { className: "pactor-chat-layout__main", children })
4660
4905
  ] });
4661
4906
  }
4662
4907
  var CHAT_LAYOUT_TYPE = "chat";
@@ -4676,6 +4921,7 @@ export {
4676
4921
  CHAT_LAYOUT_TYPE,
4677
4922
  CHAT_SHELL_COMPONENT_TYPE,
4678
4923
  Chat,
4924
+ ChatArtifactCard,
4679
4925
  ChatDenied,
4680
4926
  ChatLayout,
4681
4927
  ChatServicesProvider,
@@ -4690,6 +4936,7 @@ export {
4690
4936
  MessageBubble,
4691
4937
  PartRenderer,
4692
4938
  applyChatEvent,
4939
+ artifactCardMeta,
4693
4940
  buildArtifactBlob,
4694
4941
  buildArtifactTree,
4695
4942
  buildChatScope,
@@ -4703,6 +4950,8 @@ export {
4703
4950
  createSafeRegistry,
4704
4951
  detectStreamingMode,
4705
4952
  downloadArtifact,
4953
+ formatArtifactSize,
4954
+ formatMessageTime,
4706
4955
  guardChatDsl,
4707
4956
  isImageArtifact,
4708
4957
  mergeArtifacts,
@@ -4713,6 +4962,8 @@ export {
4713
4962
  registerChatShellComponent,
4714
4963
  resolveArtifactFileType,
4715
4964
  resolveArtifactFilename,
4965
+ resolveArtifactIcon,
4966
+ resolveArtifactIconName,
4716
4967
  runChatTurn,
4717
4968
  runRegenerateTurn,
4718
4969
  saveBlob,