@pactor-app/ui 1.44.0 → 1.46.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -33,20 +33,16 @@ __export(index_exports, {
33
33
  Accordion: () => Accordion2,
34
34
  AdminLayout: () => AdminLayout,
35
35
  Affix: () => Affix,
36
- AgentStatus: () => AgentStatus,
37
36
  Alert: () => Alert2,
38
37
  AlertDialog: () => AlertDialog2,
39
38
  Anchor: () => Anchor,
40
- ArtifactPanel: () => ArtifactPanel,
41
39
  AspectRatio: () => AspectRatio2,
42
- Attachment: () => Attachment,
43
40
  Audio: () => Audio,
44
41
  Avatar: () => Avatar2,
45
42
  BackTop: () => BackTop,
46
43
  Badge: () => Badge2,
47
44
  BlankLayout: () => BlankLayout,
48
45
  Breadcrumb: () => Breadcrumb2,
49
- Bubble: () => Bubble2,
50
46
  Button: () => Button2,
51
47
  ButtonGroup: () => ButtonGroup2,
52
48
  CONTROL_SIZE_AREA: () => CONTROL_SIZE_AREA,
@@ -60,12 +56,9 @@ __export(index_exports, {
60
56
  Cascader: () => Cascader,
61
57
  ChatInput: () => ChatInput,
62
58
  ChatLayout: () => ChatLayout,
63
- ChatMessage: () => ChatMessage,
64
- ChatPage: () => ChatPage,
65
59
  Checkbox: () => Checkbox2,
66
60
  ChipFilter: () => ChipFilter,
67
61
  ChipNode: () => ChipNode,
68
- Citation: () => Citation,
69
62
  ClearHoverButton: () => ClearHoverButton,
70
63
  CodeBlock: () => CodeBlock,
71
64
  Col: () => Col,
@@ -73,11 +66,9 @@ __export(index_exports, {
73
66
  ColorPicker: () => ColorPicker,
74
67
  Combobox: () => Combobox2,
75
68
  Command: () => Command2,
76
- Composer: () => Composer,
77
69
  Container: () => Container,
78
70
  Content: () => Content,
79
71
  ContextMenu: () => ContextMenu2,
80
- ConversationList: () => ConversationList,
81
72
  DataTable: () => DataTable,
82
73
  DatePicker: () => DatePicker,
83
74
  Descriptions: () => Descriptions,
@@ -121,7 +112,6 @@ __export(index_exports, {
121
112
  Menu: () => Menu2,
122
113
  Menubar: () => Menubar2,
123
114
  Message: () => Message,
124
- MessageList: () => MessageList,
125
115
  NavigationMenu: () => NavigationMenu2,
126
116
  Notification: () => Notification,
127
117
  NumberInput: () => NumberInput,
@@ -133,7 +123,6 @@ __export(index_exports, {
133
123
  Popconfirm: () => Popconfirm,
134
124
  Popover: () => Popover2,
135
125
  Progress: () => Progress2,
136
- Prompt: () => Prompt,
137
126
  QRCode: () => QRCode,
138
127
  RadioGroup: () => RadioGroup2,
139
128
  RailTooltip: () => RailTooltip,
@@ -145,7 +134,6 @@ __export(index_exports, {
145
134
  ScrollArea: () => ScrollArea2,
146
135
  Segmented: () => Segmented,
147
136
  Select: () => Select2,
148
- Sender: () => Sender,
149
137
  Separator: () => Separator2,
150
138
  Sheet: () => Sheet2,
151
139
  Sidebar: () => Sidebar,
@@ -158,21 +146,16 @@ __export(index_exports, {
158
146
  Statistic: () => Statistic,
159
147
  Status: () => Status,
160
148
  Steps: () => Steps,
161
- StepsPanel: () => StepsPanel,
162
- StreamingText: () => StreamingText,
163
- Suggestion: () => Suggestion,
164
149
  Switch: () => Switch2,
165
150
  Table: () => Table3,
166
151
  Tabs: () => Tabs2,
167
152
  Tag: () => Tag2,
168
153
  Text: () => Text,
169
154
  Textarea: () => Textarea2,
170
- Thinking: () => Thinking,
171
155
  TimePicker: () => TimePicker,
172
156
  Timeline: () => Timeline,
173
157
  Toggle: () => Toggle2,
174
158
  ToggleGroup: () => ToggleGroup2,
175
- ToolCall: () => ToolCall,
176
159
  Tooltip: () => Tooltip2,
177
160
  Tour: () => Tour,
178
161
  Transfer: () => Transfer,
@@ -182,8 +165,6 @@ __export(index_exports, {
182
165
  Upload: () => Upload2,
183
166
  Video: () => Video2,
184
167
  Watermark: () => Watermark,
185
- Welcome: () => Welcome,
186
- buildArtifactTree: () => buildArtifactTree,
187
168
  builtinComponents: () => builtinComponents,
188
169
  collectDefaultOpenKeys: () => collectDefaultOpenKeys,
189
170
  createComponentRegistry: () => createComponentRegistry,
@@ -198,12 +179,13 @@ __export(index_exports, {
198
179
  registerInteractionActions: () => registerInteractionActions,
199
180
  resolveLayout: () => resolveLayout,
200
181
  useFormContext: () => useFormContext,
182
+ useOptionalRenderer: () => useOptionalRenderer,
201
183
  useSidebarDrawer: () => useSidebarDrawer
202
184
  });
203
185
  module.exports = __toCommonJS(index_exports);
204
186
 
205
187
  // src/components/register.ts
206
- var import_core3 = require("@pactor-app/core");
188
+ var import_core2 = require("@pactor-app/core");
207
189
 
208
190
  // src/components/components/Accordion/index.tsx
209
191
  var import_runtime = require("@pactor-app/runtime");
@@ -521,6 +503,8 @@ var ICONS = {
521
503
  "chart-column": import_lucide_react2.ChartColumn,
522
504
  "layout-grid": import_lucide_react2.LayoutGrid,
523
505
  "layout-template": import_lucide_react2.LayoutTemplate,
506
+ "maximize-2": import_lucide_react2.Maximize2,
507
+ "minimize-2": import_lucide_react2.Minimize2,
524
508
  palette: import_lucide_react2.Palette,
525
509
  paintbrush: import_lucide_react2.Paintbrush,
526
510
  funnel: import_lucide_react2.Funnel,
@@ -3294,12 +3278,21 @@ function Textarea({
3294
3278
 
3295
3279
  // src/components/components/ChatInput/index.tsx
3296
3280
  var import_jsx_runtime51 = require("react/jsx-runtime");
3281
+ function useOptionalRenderer() {
3282
+ try {
3283
+ return (0, import_runtime13.useRenderer)();
3284
+ } catch {
3285
+ return null;
3286
+ }
3287
+ }
3297
3288
  function ChatInput({
3298
3289
  value,
3299
3290
  placeholder,
3300
3291
  disabled,
3301
3292
  rows = 3,
3302
3293
  hideSend,
3294
+ streaming = false,
3295
+ onStop,
3303
3296
  toolbarStart,
3304
3297
  toolbarEnd,
3305
3298
  header,
@@ -3310,14 +3303,14 @@ function ChatInput({
3310
3303
  className,
3311
3304
  style
3312
3305
  }) {
3313
- const { renderChildren } = (0, import_runtime13.useRenderer)();
3306
+ const renderer = useOptionalRenderer();
3314
3307
  const controlled = value !== void 0;
3315
3308
  const [draft, setDraft] = (0, import_react14.useState)("");
3316
3309
  const { t } = (0, import_runtime12.useI18n)();
3317
3310
  const text = controlled ? value : draft;
3318
3311
  const canSubmit = !disabled && text.trim() !== "";
3319
3312
  const customField = field !== void 0 && field !== null;
3320
- const renderSlot = (slot) => (0, import_react14.isValidElement)(slot) || typeof slot !== "object" || slot === null ? slot : renderChildren([slot]);
3313
+ const renderSlot = (slot) => (0, import_react14.isValidElement)(slot) || typeof slot !== "object" || slot === null ? slot : renderer?.renderChildren([slot]) ?? null;
3321
3314
  const composingRef = (0, import_react14.useRef)(false);
3322
3315
  const handleChange = (next) => {
3323
3316
  if (!controlled) {
@@ -3377,11 +3370,11 @@ function ChatInput({
3377
3370
  {
3378
3371
  type: "button",
3379
3372
  size: "icon",
3380
- "aria-label": t("pactor.chatInput.send"),
3381
- disabled: !canSubmit,
3382
- onClick: submit,
3373
+ "aria-label": streaming ? t("pactor.chatInput.stop") : t("pactor.chatInput.send"),
3374
+ disabled: streaming ? false : !canSubmit,
3375
+ onClick: streaming ? () => onStop?.() : submit,
3383
3376
  className: "size-8 rounded-full",
3384
- children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_lucide_react13.ArrowUp, {})
3377
+ children: streaming ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_lucide_react13.Square, {}) : /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_lucide_react13.ArrowUp, {})
3385
3378
  }
3386
3379
  )
3387
3380
  ] }) : null,
@@ -7519,7 +7512,7 @@ function useSidebarDrawer() {
7519
7512
  return null;
7520
7513
  }
7521
7514
  }
7522
- function useOptionalRenderer() {
7515
+ function useOptionalRenderer2() {
7523
7516
  try {
7524
7517
  return (0, import_runtime31.useRenderer)();
7525
7518
  } catch {
@@ -7527,7 +7520,7 @@ function useOptionalRenderer() {
7527
7520
  }
7528
7521
  }
7529
7522
  function SidebarContentSlot({ content }) {
7530
- const renderer = useOptionalRenderer();
7523
+ const renderer = useOptionalRenderer2();
7531
7524
  if (renderer !== null && typeof content === "object" && content !== null && !("$$typeof" in content) && "type" in content) {
7532
7525
  return /* @__PURE__ */ (0, import_jsx_runtime108.jsx)(import_jsx_runtime108.Fragment, { children: renderer.renderChildren([content]) });
7533
7526
  }
@@ -11010,16 +11003,26 @@ var tabsListVariants = (0, import_class_variance_authority7.cva)(
11010
11003
  default: "h-9 rounded-lg bg-muted p-[3px]",
11011
11004
  // line:页签栏通栏(下划线轨道占满容器宽),触发器自然宽度靠左排列
11012
11005
  line: "h-auto w-full justify-start gap-1 rounded-none border-b border-border bg-transparent p-0"
11006
+ },
11007
+ /** 尺寸(对齐 Button 的 size 语义):sm 经 compoundVariants 仅压缩胶囊变体 */
11008
+ size: {
11009
+ default: "",
11010
+ sm: ""
11013
11011
  }
11014
11012
  },
11013
+ compoundVariants: [
11014
+ { variant: "default", size: "sm", class: "h-8" }
11015
+ ],
11015
11016
  defaultVariants: {
11016
- variant: "default"
11017
+ variant: "default",
11018
+ size: "default"
11017
11019
  }
11018
11020
  }
11019
11021
  );
11020
11022
  function TabsList({
11021
11023
  className,
11022
11024
  variant,
11025
+ size,
11023
11026
  ...props
11024
11027
  }) {
11025
11028
  return /* @__PURE__ */ (0, import_jsx_runtime153.jsx)(
@@ -11027,7 +11030,8 @@ function TabsList({
11027
11030
  {
11028
11031
  "data-slot": "tabs-list",
11029
11032
  "data-variant": variant ?? "default",
11030
- className: cn(tabsListVariants({ variant }), className),
11033
+ "data-size": size ?? "default",
11034
+ className: cn(tabsListVariants({ variant, size }), className),
11031
11035
  ...props
11032
11036
  }
11033
11037
  );
@@ -11048,6 +11052,8 @@ function TabsTrigger({
11048
11052
  //(叠在 List 的底边轨道上),无底色/圆角/阴影;通栏 List 下取消
11049
11053
  // flex-1 拉伸,触发器保持自然宽度
11050
11054
  "group-data-[variant=line]/tabs-list:-mb-px group-data-[variant=line]/tabs-list:h-9 group-data-[variant=line]/tabs-list:flex-none group-data-[variant=line]/tabs-list:rounded-none group-data-[variant=line]/tabs-list:border-x-0 group-data-[variant=line]/tabs-list:border-t-0 group-data-[variant=line]/tabs-list:border-b-2 group-data-[variant=line]/tabs-list:py-1.5 group-data-[variant=line]/tabs-list:text-muted-foreground group-data-[variant=line]/tabs-list:data-active:border-b-primary group-data-[variant=line]/tabs-list:data-active:text-foreground",
11055
+ // size=sm:小字号 + 收紧纵向 padding(高度随 List h-8 自动收缩)
11056
+ "group-data-[size=sm]/tabs-list:py-0.5 group-data-[size=sm]/tabs-list:text-xs",
11051
11057
  className
11052
11058
  ),
11053
11059
  ...props
@@ -12978,2687 +12984,214 @@ function Watermark({
12978
12984
  );
12979
12985
  }
12980
12986
 
12981
- // src/components/chat/AgentStatus/index.tsx
12982
- var import_jsx_runtime174 = require("react/jsx-runtime");
12983
- var statusMeta = {
12984
- running: { icon: "loader-circle", className: "text-info", spin: true },
12985
- waiting: { icon: "clock", className: "text-warning" },
12986
- done: { icon: "circle-check", className: "text-success" },
12987
- error: { icon: "circle-x", className: "text-destructive" }
12987
+ // src/components/register.ts
12988
+ var builtinComponents = {
12989
+ Page,
12990
+ Grid,
12991
+ Row,
12992
+ Col,
12993
+ // 循环渲染:行模板(原始 DSL children)由 For 逐项渲染并注入 { row, rowIndex } 作用域
12994
+ For: { component: For, withScope: true },
12995
+ Flex,
12996
+ Card: Card2,
12997
+ Button: Button2,
12998
+ Alert: Alert2,
12999
+ Statistic,
13000
+ Tabs: Tabs2,
13001
+ Table: Table3,
13002
+ Form,
13003
+ Input: Input2,
13004
+ NumberInput,
13005
+ Select: Select2,
13006
+ // Layout 需要原始 DSL 子树做方向推导(含 Sider 判定),以 withScope 注册
13007
+ Layout: { component: Layout, withScope: true },
13008
+ Header,
13009
+ Sider,
13010
+ Content,
13011
+ Footer,
13012
+ Menu: Menu2,
13013
+ Link: Link2,
13014
+ Text,
13015
+ // 展示类扩展组件
13016
+ Badge: Badge2,
13017
+ Avatar: Avatar2,
13018
+ Skeleton: Skeleton2,
13019
+ Separator: Separator2,
13020
+ Kbd: Kbd2,
13021
+ Spinner: Spinner2,
13022
+ Empty: Empty2,
13023
+ AspectRatio: AspectRatio2,
13024
+ Progress: Progress2,
13025
+ // 表单类扩展组件
13026
+ Textarea: Textarea2,
13027
+ Checkbox: Checkbox2,
13028
+ ChipFilter,
13029
+ ChipNode,
13030
+ RadioGroup: RadioGroup2,
13031
+ Switch: Switch2,
13032
+ Slider: Slider2,
13033
+ Label: Label2,
13034
+ Field: Field2,
13035
+ ChatInput,
13036
+ // 导航类扩展组件
13037
+ Breadcrumb: Breadcrumb2,
13038
+ Pagination: Pagination2,
13039
+ Menubar: Menubar2,
13040
+ NavigationMenu: NavigationMenu2,
13041
+ DropdownMenu: DropdownMenu2,
13042
+ ContextMenu: ContextMenu2,
13043
+ // 反馈与弹层类扩展组件
13044
+ Dialog: Dialog2,
13045
+ AlertDialog: AlertDialog2,
13046
+ Drawer: Drawer2,
13047
+ Sheet: Sheet2,
13048
+ Popover: Popover2,
13049
+ Sonner,
13050
+ Accordion: Accordion2,
13051
+ Collapsible: Collapsible2,
13052
+ Tooltip: Tooltip2,
13053
+ HoverCard: HoverCard2,
13054
+ // 复合类扩展组件(第三批)
13055
+ Calendar: Calendar3,
13056
+ DatePicker,
13057
+ InputOTP: InputOTP2,
13058
+ Combobox: Combobox2,
13059
+ Carousel: Carousel2,
13060
+ Command: Command2,
13061
+ Resizable,
13062
+ ScrollArea: ScrollArea2,
13063
+ Toggle: Toggle2,
13064
+ ToggleGroup: ToggleGroup2,
13065
+ ButtonGroup: ButtonGroup2,
13066
+ InputGroup: InputGroup2,
13067
+ Item: Item2,
13068
+ Typography: Typography2,
13069
+ // 页面级组合类扩展组件(第四批)
13070
+ Sidebar,
13071
+ DataTable,
13072
+ // 图标(lucide 白名单)
13073
+ Icon,
13074
+ // 业务刚需类扩展组件(第五批:数据录入 / 数据展示 / 反馈)
13075
+ Rate,
13076
+ TimePicker,
13077
+ ColorPicker,
13078
+ Upload: Upload2,
13079
+ TreeSelect,
13080
+ Cascader,
13081
+ Transfer,
13082
+ Mentions,
13083
+ List: List2,
13084
+ Tree,
13085
+ Descriptions,
13086
+ Timeline,
13087
+ Image: Image2,
13088
+ QRCode,
13089
+ Segmented,
13090
+ Message,
13091
+ Notification,
13092
+ Popconfirm,
13093
+ Result,
13094
+ LoadingOverlay,
13095
+ Watermark,
13096
+ Tour,
13097
+ // 基础补齐类扩展组件(第六批:通用 / 布局 / 导航)
13098
+ Tag: Tag2,
13099
+ Status,
13100
+ Space,
13101
+ Container,
13102
+ Steps,
13103
+ Anchor,
13104
+ BackTop,
13105
+ Affix,
13106
+ // 媒体与内容类扩展组件(第七批)
13107
+ ImageViewer,
13108
+ Gallery,
13109
+ Video: Video2,
13110
+ Audio,
13111
+ FilePreview,
13112
+ DocumentPreview,
13113
+ RichText,
13114
+ Markdown: import_markdown2.MarkdownDslComponent,
13115
+ CodeBlock,
13116
+ DiffViewer,
13117
+ JSONViewer
12988
13118
  };
12989
- function AgentStatus({ status = "running", text, elapsed, className, style }) {
12990
- const meta = statusMeta[status];
12991
- return /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)(
12992
- "div",
12993
- {
12994
- "data-slot": "agent-status",
12995
- "data-status": status,
12996
- className: cn("flex items-center gap-2 text-sm", className),
12997
- style,
12998
- children: [
12999
- /* @__PURE__ */ (0, import_jsx_runtime174.jsx)("span", { className: cn(meta.className, meta.spin && "animate-spin motion-reduce:animate-none"), children: /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(Icon, { name: meta.icon, size: "sm" }) }),
13000
- text ? /* @__PURE__ */ (0, import_jsx_runtime174.jsx)("span", { "data-slot": "agent-status-text", children: text }) : null,
13001
- elapsed !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)("span", { "data-slot": "agent-status-elapsed", className: "text-xs text-muted-foreground", children: [
13002
- "\u5DF2\u7528\u65F6 ",
13003
- elapsed,
13004
- "s"
13005
- ] }) : null
13006
- ]
13007
- }
13008
- );
13119
+ function registerBuiltinComponents(registry) {
13120
+ for (const [type, component] of Object.entries(builtinComponents)) {
13121
+ registry.register(type, component);
13122
+ }
13123
+ }
13124
+ function createComponentRegistry() {
13125
+ const registry = new import_core2.Registry("ComponentRegistry");
13126
+ registerBuiltinComponents(registry);
13127
+ return registry;
13009
13128
  }
13010
13129
 
13011
- // src/components/chat/ArtifactPanel/index.tsx
13012
- var import_react62 = require("react");
13013
-
13014
- // src/components/chat/ArtifactPanel/artifact.ts
13015
- var ARTIFACT_IMAGE_EXTENSIONS = [
13016
- "png",
13017
- "jpg",
13018
- "jpeg",
13019
- "gif",
13020
- "svg",
13021
- "webp",
13022
- "avif",
13023
- "bmp",
13024
- "ico"
13025
- ];
13026
- function resolveArtifactFileType(artifact) {
13027
- const declared = artifact.fileType?.trim().toLowerCase().replace(/^\./, "");
13028
- if (declared) {
13029
- return declared;
13030
- }
13031
- const match = /\.([A-Za-z0-9]+)$/.exec(artifact.title.trim());
13032
- return match ? match[1].toLowerCase() : null;
13033
- }
13034
- function isImageArtifact(artifact) {
13035
- const ext = resolveArtifactFileType(artifact);
13036
- return ext !== null && ARTIFACT_IMAGE_EXTENSIONS.includes(ext);
13037
- }
13038
- var ARTIFACT_ICON_BY_EXTENSION = {
13039
- // 表格数据
13040
- csv: "table",
13041
- tsv: "table",
13042
- xls: "table",
13043
- xlsx: "table",
13044
- // 数据 / 数据库
13045
- json: "database",
13046
- sql: "database",
13047
- // 脚本
13048
- sh: "terminal",
13049
- bash: "terminal",
13050
- zsh: "terminal",
13051
- // 代码 / 配置
13052
- js: "code",
13053
- mjs: "code",
13054
- cjs: "code",
13055
- jsx: "code",
13056
- ts: "code",
13057
- mts: "code",
13058
- cts: "code",
13059
- tsx: "code",
13060
- py: "code",
13061
- rb: "code",
13062
- go: "code",
13063
- rs: "code",
13064
- java: "code",
13065
- kt: "code",
13066
- c: "code",
13067
- h: "code",
13068
- cc: "code",
13069
- cpp: "code",
13070
- cs: "code",
13071
- swift: "code",
13072
- php: "code",
13073
- css: "code",
13074
- scss: "code",
13075
- less: "code",
13076
- html: "code",
13077
- vue: "code",
13078
- svelte: "code",
13079
- yaml: "code",
13080
- yml: "code",
13081
- toml: "code",
13082
- xml: "code",
13083
- // 文档 / 文本
13084
- md: "file-text",
13085
- markdown: "file-text",
13086
- mdx: "file-text",
13087
- txt: "file-text",
13088
- text: "file-text",
13089
- log: "file-text",
13090
- rst: "file-text",
13091
- pdf: "file-text",
13092
- doc: "file-text",
13093
- docx: "file-text"
13094
- };
13095
- function resolveArtifactIconName(artifact) {
13096
- const ext = resolveArtifactFileType(artifact);
13097
- if (ext !== null) {
13098
- if (ARTIFACT_IMAGE_EXTENSIONS.includes(ext)) {
13099
- return "image";
13100
- }
13101
- const name = ARTIFACT_ICON_BY_EXTENSION[ext];
13102
- if (name !== void 0) {
13103
- return name;
13104
- }
13105
- }
13106
- if (artifact.kind === "code") {
13107
- return "code";
13108
- }
13109
- if (artifact.kind === "dsl") {
13110
- return "layout-grid";
13111
- }
13112
- return ext === null ? "file-text" : "file";
13113
- }
13114
- function buildArtifactTree(artifacts) {
13115
- const root = { name: "", path: "", children: [] };
13116
- for (const artifact of artifacts) {
13117
- const segments = artifact.id.split("/").filter(Boolean);
13118
- let node = root;
13119
- for (let i = 0; i < segments.length - 1; i++) {
13120
- const path = segments.slice(0, i + 1).join("/");
13121
- let child = node.children.find(
13122
- (item) => item.path === path && item.artifact === void 0
13123
- );
13124
- if (!child) {
13125
- child = { name: segments[i], path, children: [] };
13126
- node.children.push(child);
13130
+ // src/layout/admin/menu-chain.ts
13131
+ function findMenuChain(registry, menuId) {
13132
+ const walk = (menus, ancestors) => {
13133
+ for (const menu of menus) {
13134
+ const chain = [...ancestors, menu];
13135
+ if (menu.id === menuId) {
13136
+ return chain;
13137
+ }
13138
+ if (menu.children !== void 0) {
13139
+ const hit = walk(menu.children, chain);
13140
+ if (hit !== null) {
13141
+ return hit;
13142
+ }
13127
13143
  }
13128
- node = child;
13129
- }
13130
- node.children.push({
13131
- name: artifact.title,
13132
- path: artifact.id,
13133
- artifact,
13134
- children: []
13135
- });
13136
- }
13137
- const sortLevel = (nodes) => {
13138
- nodes.sort((a, b) => {
13139
- const dirDelta = Number(b.artifact === void 0) - Number(a.artifact === void 0);
13140
- return dirDelta !== 0 ? dirDelta : a.name.localeCompare(b.name);
13141
- });
13142
- for (const item of nodes) {
13143
- sortLevel(item.children);
13144
13144
  }
13145
+ return null;
13145
13146
  };
13146
- sortLevel(root.children);
13147
- return root.children;
13147
+ return walk(registry.tree(), []) ?? [];
13148
13148
  }
13149
13149
 
13150
- // src/components/chat/ArtifactPanel/download.ts
13151
- var KIND_EXTENSIONS = {
13152
- markdown: "md",
13153
- text: "txt",
13154
- code: "txt",
13155
- dsl: "json"
13156
- };
13157
- function resolveArtifactFilename(artifact) {
13158
- const title = artifact.title.trim() || "artifact";
13159
- if (/\.[A-Za-z0-9]+$/.test(title)) {
13160
- return title;
13161
- }
13162
- const ext = resolveArtifactFileType(artifact) ?? KIND_EXTENSIONS[artifact.kind];
13163
- return `${title}.${ext}`;
13164
- }
13165
- function dataUrlToBlob(dataUrl) {
13166
- const comma = dataUrl.indexOf(",");
13167
- const meta = dataUrl.slice(0, comma);
13168
- const payload = dataUrl.slice(comma + 1);
13169
- const mime = /^data:([^;,]+)/.exec(meta)?.[1] ?? "application/octet-stream";
13170
- if (meta.includes(";base64")) {
13171
- const binary = atob(payload);
13172
- const bytes = new Uint8Array(binary.length);
13173
- for (let i = 0; i < binary.length; i++) {
13174
- bytes[i] = binary.charCodeAt(i);
13175
- }
13176
- return new Blob([bytes], { type: mime });
13177
- }
13178
- return new Blob([decodeURIComponent(payload)], { type: mime });
13179
- }
13180
- function isRemoteUrl(raw) {
13181
- return /^https?:\/\//.test(raw.trim());
13182
- }
13183
- function buildArtifactBlob(artifact) {
13184
- if (artifact.kind === "dsl" && typeof artifact.content === "object") {
13185
- return new Blob([JSON.stringify(artifact.content, null, 2)], {
13186
- type: "application/json"
13187
- });
13188
- }
13189
- const raw = String(artifact.content);
13190
- if (isImageArtifact(artifact)) {
13191
- const trimmed = raw.trim();
13192
- if (trimmed.startsWith("data:")) {
13193
- return dataUrlToBlob(trimmed);
13194
- }
13195
- if (trimmed.startsWith("<svg") || trimmed.startsWith("<?xml")) {
13196
- return new Blob([raw], { type: "image/svg+xml" });
13197
- }
13198
- if (isRemoteUrl(trimmed)) {
13199
- return null;
13150
+ // src/layout/admin/menu-items.ts
13151
+ function collectDefaultOpenKeys(registry, activeMenuId) {
13152
+ const keys = [];
13153
+ const walk = (menus) => {
13154
+ for (const menu of menus) {
13155
+ if (menu.type === "group" && menu.defaultOpen === true) {
13156
+ keys.push(menu.id);
13157
+ }
13158
+ if (menu.children !== void 0) {
13159
+ walk(menu.children);
13160
+ }
13200
13161
  }
13201
- }
13202
- const ext = resolveArtifactFileType(artifact);
13203
- const mime = ext === "md" || artifact.kind === "markdown" ? "text/markdown" : "text/plain";
13204
- return new Blob([raw], { type: `${mime};charset=utf-8` });
13205
- }
13206
- function saveBlob(blob, filename) {
13207
- const url = URL.createObjectURL(blob);
13208
- const anchor = document.createElement("a");
13209
- anchor.href = url;
13210
- anchor.download = filename;
13211
- document.body.appendChild(anchor);
13212
- anchor.click();
13213
- anchor.remove();
13214
- setTimeout(() => URL.revokeObjectURL(url), 1e3);
13215
- }
13216
- async function downloadArtifact(artifact) {
13217
- const filename = resolveArtifactFilename(artifact);
13218
- const raw = String(artifact.content ?? "").trim();
13219
- if (isImageArtifact(artifact) && isRemoteUrl(raw)) {
13220
- try {
13221
- const response = await fetch(raw);
13222
- if (!response.ok) {
13223
- throw new Error(`HTTP ${response.status}`);
13162
+ };
13163
+ walk(registry.tree());
13164
+ if (activeMenuId !== void 0) {
13165
+ for (const menu of findMenuChain(registry, activeMenuId)) {
13166
+ if (menu.type === "group" && !keys.includes(menu.id)) {
13167
+ keys.push(menu.id);
13224
13168
  }
13225
- saveBlob(await response.blob(), filename);
13226
- return;
13227
- } catch {
13228
- window.open(raw, "_blank", "noopener");
13229
- return;
13230
13169
  }
13231
13170
  }
13232
- const blob = buildArtifactBlob(artifact);
13233
- if (blob) {
13234
- saveBlob(blob, filename);
13235
- }
13171
+ return keys;
13236
13172
  }
13237
13173
 
13238
- // src/components/chat/ArtifactPanel/dsl-preview.tsx
13239
- var import_core2 = require("@pactor-app/core");
13174
+ // src/layout/admin/AdminLayout.tsx
13175
+ var import_permission = require("@pactor-app/permission");
13176
+ var import_router = require("@pactor-app/router");
13240
13177
  var import_runtime50 = require("@pactor-app/runtime");
13178
+ var import_react62 = require("react");
13179
+
13180
+ // src/layout/admin/use-media-query.ts
13241
13181
  var import_react61 = require("react");
13242
- var import_jsx_runtime175 = require("react/jsx-runtime");
13243
- var ARTIFACT_DENIED_TYPE = "ChatDenied";
13244
- function ArtifactDenied({ deniedType }) {
13245
- return /* @__PURE__ */ (0, import_jsx_runtime175.jsxs)(
13246
- "div",
13247
- {
13248
- "data-slot": "artifact-denied",
13249
- "data-denied-type": deniedType,
13250
- className: "rounded-md border border-dashed border-border p-3 text-sm text-muted-foreground",
13251
- children: [
13252
- "\u8BE5\u7EC4\u4EF6\u4E0D\u5141\u8BB8\u5728\u4EA7\u7269\u9884\u89C8\u4E2D\u4F7F\u7528",
13253
- deniedType ? `\uFF1A${deniedType}` : ""
13254
- ]
13255
- }
13182
+ var BREAKPOINT_PX = {
13183
+ xs: 480,
13184
+ sm: 576,
13185
+ md: 768,
13186
+ lg: 992,
13187
+ xl: 1200,
13188
+ xxl: 1600
13189
+ };
13190
+ function useMediaQuery(query) {
13191
+ const [matches, setMatches] = (0, import_react61.useState)(
13192
+ () => typeof window !== "undefined" && typeof window.matchMedia === "function" ? window.matchMedia(query).matches : false
13256
13193
  );
13257
- }
13258
- function guardArtifactDsl(node, registry) {
13259
- const type = node.type ?? "(reference)";
13260
- if (type !== ARTIFACT_DENIED_TYPE && !registry.has(type)) {
13261
- return {
13262
- type: ARTIFACT_DENIED_TYPE,
13263
- props: { deniedType: type }
13264
- };
13265
- }
13266
- if (node.children === void 0) {
13267
- return node;
13268
- }
13269
- if (!Array.isArray(node.children)) {
13270
- return {
13271
- type: ARTIFACT_DENIED_TYPE,
13272
- props: { deniedType: `${type}(remote)` }
13273
- };
13274
- }
13275
- if (node.children.length === 0) {
13276
- return node;
13277
- }
13278
- return {
13279
- ...node,
13280
- // 数组中混排的引用元素同样无法静态过白名单:替换为受控占位
13281
- children: node.children.map(
13282
- (child) => (0, import_core2.isDslSourceRef)(child) ? { type: ARTIFACT_DENIED_TYPE, props: { deniedType: "(remote)" } } : guardArtifactDsl(child, registry)
13283
- )
13284
- };
13285
- }
13286
- function useArtifactPreviewRuntime(safeRegistry, user) {
13287
- return (0, import_react61.useMemo)(() => {
13288
- if (!safeRegistry) {
13289
- return void 0;
13290
- }
13291
- const components = new import_core2.Registry("ArtifactPreviewRegistry");
13292
- components.register(ARTIFACT_DENIED_TYPE, ArtifactDenied);
13293
- for (const name of safeRegistry.list()) {
13294
- components.register(name, safeRegistry.get(name));
13295
- }
13296
- const context = (0, import_runtime50.createRuntimeContext)({ components, user });
13297
- (0, import_runtime50.registerBuiltinActions)(context.actions);
13298
- return { context, engine: new import_runtime50.ActionEngine(context) };
13299
- }, [safeRegistry, user]);
13300
- }
13301
- var ArtifactDslGuard = class extends import_react61.Component {
13302
- constructor() {
13303
- super(...arguments);
13304
- this.state = { failed: false };
13305
- }
13306
- static getDerivedStateFromError() {
13307
- return { failed: true };
13308
- }
13309
- componentDidCatch(error) {
13310
- console.warn("[@pactor-app/ui] DSL \u4EA7\u7269\u6E32\u67D3\u5931\u8D25\uFF0C\u5DF2\u964D\u7EA7\u5C55\u793A", error);
13311
- }
13312
- render() {
13313
- return this.state.failed ? /* @__PURE__ */ (0, import_jsx_runtime175.jsx)(
13314
- "div",
13315
- {
13316
- "data-slot": "artifact-denied",
13317
- className: "rounded-md border border-dashed border-border p-3 text-sm text-muted-foreground",
13318
- children: "DSL \u4EA7\u7269\u6E32\u67D3\u5931\u8D25\uFF0C\u5DF2\u964D\u7EA7\u5C55\u793A"
13319
- }
13320
- ) : this.props.children;
13321
- }
13322
- };
13323
- function ArtifactDslNode({ node }) {
13324
- const { renderChildren } = (0, import_runtime50.useRenderer)();
13325
- return /* @__PURE__ */ (0, import_jsx_runtime175.jsx)(import_jsx_runtime175.Fragment, { children: renderChildren([node]) });
13326
- }
13327
- function ArtifactDslContent({
13328
- content,
13329
- runtime,
13330
- style
13331
- }) {
13332
- const node = typeof content === "object" && content !== null && !Array.isArray(content) && typeof content.type === "string" ? content : void 0;
13333
- if (!node || !runtime) {
13334
- return /* @__PURE__ */ (0, import_jsx_runtime175.jsx)(
13335
- "div",
13336
- {
13337
- "data-slot": "artifact-denied",
13338
- className: "rounded-md border border-dashed border-border p-3 text-sm text-muted-foreground",
13339
- style,
13340
- children: node ? "DSL \u9884\u89C8\u4E0D\u53EF\u7528\uFF08\u672A\u6CE8\u5165 Safe Registry\uFF09" : "DSL \u4EA7\u7269\u5185\u5BB9\u65E0\u6548"
13341
- }
13342
- );
13343
- }
13344
- const guarded = guardArtifactDsl(node, runtime.context.components);
13345
- return /* @__PURE__ */ (0, import_jsx_runtime175.jsx)(import_runtime50.DslRenderer, { context: runtime.context, engine: runtime.engine, children: /* @__PURE__ */ (0, import_jsx_runtime175.jsx)(ArtifactDslGuard, { children: /* @__PURE__ */ (0, import_jsx_runtime175.jsx)(ArtifactDslNode, { node: guarded }) }) });
13346
- }
13347
-
13348
- // src/components/chat/ArtifactPanel/index.tsx
13349
- var import_jsx_runtime176 = require("react/jsx-runtime");
13350
- function ArtifactKindIcon({ artifact }) {
13351
- return /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(Icon, { name: resolveArtifactIconName(artifact), size: 13 });
13352
- }
13353
- function ArtifactListView({
13354
- nodes,
13355
- activeId,
13356
- onSelect
13357
- }) {
13358
- return /* @__PURE__ */ (0, import_jsx_runtime176.jsx)("ul", { "data-slot": "artifact-panel-list", className: "flex flex-col gap-0.5", children: nodes.map((node) => /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(
13359
- ArtifactTreeRow,
13360
- {
13361
- node,
13362
- activeId,
13363
- onSelect
13364
- },
13365
- node.path
13366
- )) });
13367
- }
13368
- function ArtifactTreeRow({
13369
- node,
13370
- activeId,
13371
- onSelect
13372
- }) {
13373
- const [open, setOpen] = (0, import_react62.useState)(true);
13374
- if (node.artifact) {
13375
- return /* @__PURE__ */ (0, import_jsx_runtime176.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime176.jsxs)(
13376
- "button",
13377
- {
13378
- type: "button",
13379
- "data-slot": "artifact-panel-list-item",
13380
- "data-active": node.artifact.id === activeId,
13381
- className: "flex w-full cursor-pointer items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm hover:bg-accent data-[active=true]:bg-accent",
13382
- onClick: () => onSelect?.(node.artifact.id),
13383
- children: [
13384
- /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(ArtifactKindIcon, { artifact: node.artifact }),
13385
- /* @__PURE__ */ (0, import_jsx_runtime176.jsx)("span", { className: "min-w-0 flex-1 truncate", children: node.artifact.title }),
13386
- /* @__PURE__ */ (0, import_jsx_runtime176.jsx)("span", { className: "shrink-0 text-xs text-muted-foreground", children: node.artifact.kind })
13387
- ]
13388
- }
13389
- ) });
13390
- }
13391
- return /* @__PURE__ */ (0, import_jsx_runtime176.jsxs)("li", { children: [
13392
- /* @__PURE__ */ (0, import_jsx_runtime176.jsxs)(
13393
- "button",
13394
- {
13395
- type: "button",
13396
- "data-slot": "artifact-panel-list-folder",
13397
- "aria-expanded": open,
13398
- "data-open": open,
13399
- className: "flex w-full cursor-pointer items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm hover:bg-accent",
13400
- onClick: () => setOpen((value) => !value),
13401
- children: [
13402
- /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(
13403
- "span",
13404
- {
13405
- className: "inline-flex transition-transform data-[open=true]:rotate-90",
13406
- "data-open": open,
13407
- children: /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(Icon, { name: "chevron-right", size: 12 })
13408
- }
13409
- ),
13410
- /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(Icon, { name: "folder", size: 13 }),
13411
- /* @__PURE__ */ (0, import_jsx_runtime176.jsx)("span", { className: "min-w-0 flex-1 truncate", children: node.name })
13412
- ]
13413
- }
13414
- ),
13415
- open && /* @__PURE__ */ (0, import_jsx_runtime176.jsx)("div", { className: "pl-4", children: /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(
13416
- ArtifactListView,
13417
- {
13418
- nodes: node.children,
13419
- activeId,
13420
- onSelect
13421
- }
13422
- ) })
13423
- ] });
13424
- }
13425
- function ArtifactImageContent({ artifact }) {
13426
- const raw = String(artifact.content).trim();
13427
- const src = raw.startsWith("<svg") || raw.startsWith("<?xml") ? `data:image/svg+xml;utf8,${encodeURIComponent(raw)}` : raw;
13428
- return /* @__PURE__ */ (0, import_jsx_runtime176.jsx)("div", { "data-slot": "artifact-panel-image", className: "flex justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime176.jsx)("img", { src, alt: artifact.title, className: "max-w-full rounded-md" }) });
13429
- }
13430
- function ArtifactContent({
13431
- artifact,
13432
- runtime,
13433
- viewers
13434
- }) {
13435
- const ext = resolveArtifactFileType(artifact);
13436
- const custom = (ext ? viewers?.[ext] : void 0) ?? viewers?.[artifact.kind];
13437
- if (custom) {
13438
- return /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(import_jsx_runtime176.Fragment, { children: custom(artifact) });
13439
- }
13440
- if (isImageArtifact(artifact)) {
13441
- return /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(ArtifactImageContent, { artifact });
13442
- }
13443
- switch (artifact.kind) {
13444
- case "markdown":
13445
- return /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(import_markdown2.MarkdownDslComponent, { content: String(artifact.content) });
13446
- case "code":
13447
- return /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(
13448
- CodeBlock,
13449
- {
13450
- code: String(artifact.content),
13451
- language: artifact.language
13452
- }
13453
- );
13454
- case "text":
13455
- return /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(
13456
- "pre",
13457
- {
13458
- "data-slot": "artifact-panel-text",
13459
- className: "text-sm break-words whitespace-pre-wrap",
13460
- children: String(artifact.content)
13461
- }
13462
- );
13463
- case "dsl":
13464
- return /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(ArtifactDslContent, { content: artifact.content, runtime });
13465
- default:
13466
- return null;
13467
- }
13468
- }
13469
- function ArtifactPanel({
13470
- artifact,
13471
- artifacts,
13472
- activeArtifactId,
13473
- onSelectArtifact,
13474
- title = "\u4EA7\u7269",
13475
- emptyText = "\u6682\u65E0\u4EA7\u7269",
13476
- onClose,
13477
- onDownload,
13478
- safeRegistry,
13479
- user,
13480
- artifactViewers,
13481
- className,
13482
- style
13483
- }) {
13484
- const runtime = useArtifactPreviewRuntime(safeRegistry, user);
13485
- const [view, setView] = (0, import_react62.useState)("content");
13486
- const activeId = activeArtifactId ?? artifact?.id;
13487
- (0, import_react62.useEffect)(() => {
13488
- setView("content");
13489
- }, [activeId]);
13490
- const hasArtifacts = artifacts !== void 0 && artifacts.length > 0;
13491
- const headerTitle = view === "list" ? "\u4EA7\u7269\u76EE\u5F55" : artifact?.title ?? title;
13492
- return /* @__PURE__ */ (0, import_jsx_runtime176.jsxs)(
13493
- "aside",
13494
- {
13495
- "data-slot": "artifact-panel",
13496
- "data-kind": artifact?.kind,
13497
- className: cn("flex h-full min-w-0 flex-col", className),
13498
- style,
13499
- children: [
13500
- /* @__PURE__ */ (0, import_jsx_runtime176.jsxs)("div", { className: "flex shrink-0 items-center gap-1 border-b border-border px-2 py-2.5", children: [
13501
- hasArtifacts ? /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(
13502
- Button2,
13503
- {
13504
- icon: "list",
13505
- variant: "text",
13506
- tooltip: view === "list" ? "\u8FD4\u56DE\u5185\u5BB9" : "\u4EA7\u7269\u76EE\u5F55",
13507
- onClick: () => setView((value) => value === "list" ? "content" : "list")
13508
- }
13509
- ) : null,
13510
- hasArtifacts ? /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(
13511
- DropdownMenu2,
13512
- {
13513
- items: artifacts.map((item) => ({
13514
- label: item.title,
13515
- value: item.id,
13516
- icon: resolveArtifactIconName(item)
13517
- })),
13518
- onSelect: (id) => onSelectArtifact?.(id),
13519
- children: /* @__PURE__ */ (0, import_jsx_runtime176.jsxs)(
13520
- "span",
13521
- {
13522
- "data-slot": "artifact-panel-menu-trigger",
13523
- className: "flex min-w-0 cursor-pointer items-center gap-1 rounded-md px-1.5 py-1 text-sm font-medium hover:bg-accent",
13524
- children: [
13525
- view !== "list" && artifact ? /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(ArtifactKindIcon, { artifact }) : null,
13526
- /* @__PURE__ */ (0, import_jsx_runtime176.jsx)("span", { className: "truncate", children: headerTitle }),
13527
- /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(Icon, { name: "chevron-down", size: 12 })
13528
- ]
13529
- }
13530
- )
13531
- }
13532
- ) : /* @__PURE__ */ (0, import_jsx_runtime176.jsx)("span", { className: "min-w-0 flex-1 truncate px-1.5 text-sm font-medium", children: headerTitle }),
13533
- view !== "list" && artifact ? /* @__PURE__ */ (0, import_jsx_runtime176.jsx)("span", { className: "shrink-0 rounded-md bg-accent px-1.5 py-0.5 text-xs text-muted-foreground", children: artifact.kind }) : null,
13534
- /* @__PURE__ */ (0, import_jsx_runtime176.jsx)("span", { className: "flex-1" }),
13535
- artifact ? /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(
13536
- Button2,
13537
- {
13538
- icon: "download",
13539
- variant: "text",
13540
- tooltip: "\u4E0B\u8F7D\u4EA7\u7269",
13541
- className: "px-2",
13542
- onClick: () => onDownload ? onDownload(artifact) : void downloadArtifact(artifact)
13543
- }
13544
- ) : null,
13545
- /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(
13546
- Button2,
13547
- {
13548
- icon: "x",
13549
- variant: "text",
13550
- tooltip: "\u6536\u8D77\u4EA7\u7269\u533A",
13551
- className: "px-2",
13552
- onClick: () => onClose?.()
13553
- }
13554
- )
13555
- ] }),
13556
- /* @__PURE__ */ (0, import_jsx_runtime176.jsx)("div", { className: "scrollbar-subtle min-h-0 flex-1 overflow-auto p-4", children: view === "list" && artifacts !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(
13557
- ArtifactListView,
13558
- {
13559
- nodes: buildArtifactTree(artifacts),
13560
- activeId,
13561
- onSelect: onSelectArtifact
13562
- }
13563
- ) : artifact ? /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(
13564
- ArtifactContent,
13565
- {
13566
- artifact,
13567
- runtime,
13568
- viewers: artifactViewers
13569
- }
13570
- ) : /* @__PURE__ */ (0, import_jsx_runtime176.jsx)("p", { className: "text-sm text-muted-foreground", children: emptyText }) })
13571
- ]
13572
- }
13573
- );
13574
- }
13575
-
13576
- // src/components/chat/Attachment/index.tsx
13577
- var import_jsx_runtime177 = require("react/jsx-runtime");
13578
- var kindIcon2 = { image: "image", text: "file-text", video: "video", audio: "music", other: "file" };
13579
- function formatSize3(bytes) {
13580
- if (bytes < 1024) return `${bytes} B`;
13581
- if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
13582
- return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
13583
- }
13584
- function Attachment({ items = [], onRemove, onRetry, className, style }) {
13585
- return /* @__PURE__ */ (0, import_jsx_runtime177.jsx)("div", { "data-slot": "attachment", className: cn("flex flex-wrap gap-2", className), style, children: items.map((item, index) => {
13586
- const key = item.id ?? index;
13587
- const kind = inferKind(item.name, item.fileType);
13588
- const status = item.status ?? "done";
13589
- return /* @__PURE__ */ (0, import_jsx_runtime177.jsxs)(
13590
- "div",
13591
- {
13592
- "data-slot": "attachment-item",
13593
- "data-status": status,
13594
- className: "flex w-56 flex-col rounded-md border border-border px-2 py-1.5",
13595
- children: [
13596
- /* @__PURE__ */ (0, import_jsx_runtime177.jsxs)("div", { className: "flex items-center gap-1.5", children: [
13597
- /* @__PURE__ */ (0, import_jsx_runtime177.jsx)("span", { className: "shrink-0 text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime177.jsx)(Icon, { name: kindIcon2[kind], size: "sm" }) }),
13598
- /* @__PURE__ */ (0, import_jsx_runtime177.jsx)("span", { className: "min-w-0 flex-1 truncate text-sm", children: item.name }),
13599
- status === "uploading" ? /* @__PURE__ */ (0, import_jsx_runtime177.jsx)("span", { className: "shrink-0 animate-spin text-muted-foreground motion-reduce:animate-none", children: /* @__PURE__ */ (0, import_jsx_runtime177.jsx)(Icon, { name: "loader-circle", size: "sm" }) }) : null,
13600
- status === "error" && onRetry ? /* @__PURE__ */ (0, import_jsx_runtime177.jsx)(
13601
- "button",
13602
- {
13603
- type: "button",
13604
- "data-slot": "attachment-retry",
13605
- "aria-label": `\u91CD\u8BD5 ${item.name}`,
13606
- className: "shrink-0 text-destructive hover:opacity-80",
13607
- onClick: () => onRetry(key),
13608
- children: /* @__PURE__ */ (0, import_jsx_runtime177.jsx)(Icon, { name: "refresh-ccw", size: "sm" })
13609
- }
13610
- ) : null,
13611
- onRemove ? /* @__PURE__ */ (0, import_jsx_runtime177.jsx)(
13612
- "button",
13613
- {
13614
- type: "button",
13615
- "data-slot": "attachment-remove",
13616
- "aria-label": `\u79FB\u9664 ${item.name}`,
13617
- className: "shrink-0 text-muted-foreground hover:text-foreground",
13618
- onClick: () => onRemove(key),
13619
- children: /* @__PURE__ */ (0, import_jsx_runtime177.jsx)(Icon, { name: "x", size: "sm" })
13620
- }
13621
- ) : null
13622
- ] }),
13623
- /* @__PURE__ */ (0, import_jsx_runtime177.jsxs)("div", { className: "mt-0.5 flex items-center gap-1.5 pl-5 text-xs", children: [
13624
- item.fileSize !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime177.jsx)("span", { className: "text-muted-foreground", children: formatSize3(item.fileSize) }) : null,
13625
- status === "error" ? /* @__PURE__ */ (0, import_jsx_runtime177.jsx)("span", { className: "text-destructive", children: "\u4E0A\u4F20\u5931\u8D25" }) : null
13626
- ] }),
13627
- status === "uploading" && item.progress !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime177.jsx)("div", { "data-slot": "attachment-progress", className: "mt-1 ml-5 h-1 overflow-hidden rounded-full bg-muted", children: /* @__PURE__ */ (0, import_jsx_runtime177.jsx)("div", { className: "h-full bg-primary transition-[width]", style: { width: `${item.progress}%` } }) }) : null
13628
- ]
13629
- },
13630
- key
13631
- );
13632
- }) });
13633
- }
13634
-
13635
- // src/ui/bubble.tsx
13636
- var React7 = __toESM(require("react"), 1);
13637
- var import_class_variance_authority10 = require("class-variance-authority");
13638
- var import_jsx_runtime178 = require("react/jsx-runtime");
13639
- var bubbleVariants = (0, import_class_variance_authority10.cva)(
13640
- "group/bubble relative flex w-fit max-w-[80%] min-w-0 flex-col gap-1 group-data-[align=end]/message:self-end data-[align=end]:self-end data-[variant=ghost]:max-w-full",
13641
- {
13642
- variants: {
13643
- variant: {
13644
- default: "*:data-[slot=bubble-content]:bg-primary *:data-[slot=bubble-content]:text-primary-foreground [&>[data-slot=bubble-content]:is(button,a):hover]:bg-primary/80",
13645
- secondary: "*:data-[slot=bubble-content]:bg-secondary *:data-[slot=bubble-content]:text-secondary-foreground [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)]",
13646
- muted: "*:data-[slot=bubble-content]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[color-mix(in_oklch,var(--muted),var(--foreground)_5%)]",
13647
- tinted: "*:data-[slot=bubble-content]:bg-(--bubble-background) *:data-[slot=bubble-content]:text-foreground [&>[data-slot=bubble-content]:is(button,a):hover]:bg-(--bubble-hover-background)",
13648
- outline: "*:data-[slot=bubble-content]:border-border *:data-[slot=bubble-content]:bg-card [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:text-foreground dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-input/30",
13649
- ghost: "border-none *:data-[slot=bubble-content]:rounded-none *:data-[slot=bubble-content]:bg-transparent *:data-[slot=bubble-content]:p-0 [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:text-foreground dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted/50",
13650
- destructive: "*:data-[slot=bubble-content]:bg-destructive/10 *:data-[slot=bubble-content]:text-destructive dark:*:data-[slot=bubble-content]:bg-destructive/20 [&>[data-slot=bubble-content]:is(button,a):hover]:bg-destructive/20 dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-destructive/30"
13651
- }
13652
- },
13653
- defaultVariants: {
13654
- variant: "default"
13655
- }
13656
- }
13657
- );
13658
- function Bubble({
13659
- variant = "default",
13660
- align = "start",
13661
- className,
13662
- ...props
13663
- }) {
13664
- return /* @__PURE__ */ (0, import_jsx_runtime178.jsx)(
13665
- "div",
13666
- {
13667
- "data-slot": "bubble",
13668
- "data-variant": variant,
13669
- "data-align": align,
13670
- className: cn(bubbleVariants({ variant }), className),
13671
- ...props
13672
- }
13673
- );
13674
- }
13675
- function BubbleContent({
13676
- asChild = false,
13677
- className,
13678
- children,
13679
- ...props
13680
- }) {
13681
- const cls = cn(
13682
- "w-fit max-w-full min-w-0 overflow-hidden rounded-xl border border-transparent px-3 py-2 text-sm leading-relaxed wrap-break-word group-data-[align=end]/bubble:self-end [button]:text-left [button,a]:transition-colors [button,a]:outline-none [button,a]:focus-visible:border-ring [button,a]:focus-visible:ring-3 [button,a]:focus-visible:ring-ring/50",
13683
- className
13684
- );
13685
- if (asChild && React7.isValidElement(children)) {
13686
- return React7.cloneElement(children, {
13687
- "data-slot": "bubble-content",
13688
- className: cn(cls, children.props.className),
13689
- ...props
13690
- });
13691
- }
13692
- return /* @__PURE__ */ (0, import_jsx_runtime178.jsx)(
13693
- "div",
13694
- {
13695
- "data-slot": "bubble-content",
13696
- className: cls,
13697
- ...props,
13698
- children
13699
- }
13700
- );
13701
- }
13702
- var bubbleReactionsVariants = (0, import_class_variance_authority10.cva)(
13703
- "absolute z-10 flex w-fit shrink-0 items-center justify-center gap-1 rounded-full bg-muted px-1.5 py-0.5 text-sm ring-3 ring-card has-[button]:p-0",
13704
- {
13705
- variants: {
13706
- side: {
13707
- top: "top-0 -translate-y-3/4",
13708
- bottom: "bottom-0 translate-y-3/4"
13709
- },
13710
- align: {
13711
- start: "left-3",
13712
- end: "right-3"
13713
- }
13714
- },
13715
- defaultVariants: {
13716
- side: "bottom",
13717
- align: "end"
13718
- }
13719
- }
13720
- );
13721
-
13722
- // src/components/chat/Bubble/index.tsx
13723
- var import_jsx_runtime179 = require("react/jsx-runtime");
13724
- function Bubble2({ align = "start", variant = "muted", className, style, children }) {
13725
- return /* @__PURE__ */ (0, import_jsx_runtime179.jsx)(Bubble, { variant, align, className, style, children: /* @__PURE__ */ (0, import_jsx_runtime179.jsx)(BubbleContent, { children }) });
13726
- }
13727
-
13728
- // src/components/chat/Sender/index.tsx
13729
- var import_jsx_runtime180 = require("react/jsx-runtime");
13730
- function Sender({ name, avatar, avatarText, role, time, align = "start", className, style }) {
13731
- return /* @__PURE__ */ (0, import_jsx_runtime180.jsxs)(
13732
- "div",
13733
- {
13734
- "data-slot": "sender",
13735
- className: cn("flex items-center gap-2", align === "end" && "flex-row-reverse", className),
13736
- style,
13737
- children: [
13738
- /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(Avatar2, { src: avatar, fallback: avatarText ?? name?.slice(0, 1) ?? "?", className: "size-7" }),
13739
- /* @__PURE__ */ (0, import_jsx_runtime180.jsxs)("div", { className: cn("flex min-w-0 items-baseline gap-1.5", align === "end" && "flex-row-reverse"), children: [
13740
- name ? /* @__PURE__ */ (0, import_jsx_runtime180.jsx)("span", { "data-slot": "sender-name", className: "truncate text-sm font-medium", children: name }) : null,
13741
- role ? /* @__PURE__ */ (0, import_jsx_runtime180.jsx)("span", { "data-slot": "sender-role", className: "shrink-0 text-xs text-muted-foreground", children: role }) : null,
13742
- time ? /* @__PURE__ */ (0, import_jsx_runtime180.jsx)("span", { "data-slot": "sender-time", className: "shrink-0 text-xs text-muted-foreground", children: time }) : null
13743
- ] })
13744
- ]
13745
- }
13746
- );
13747
- }
13748
-
13749
- // src/components/chat/StreamingText/index.tsx
13750
- var import_react63 = require("react");
13751
- var import_jsx_runtime181 = require("react/jsx-runtime");
13752
- function StreamingText({ content = "", streaming, typing, speed = 2, className, style }) {
13753
- const [revealed, setRevealed] = (0, import_react63.useState)(typing ? 0 : content.length);
13754
- (0, import_react63.useEffect)(() => {
13755
- if (!typing) {
13756
- setRevealed(content.length);
13757
- return;
13758
- }
13759
- setRevealed(0);
13760
- const timer = window.setInterval(() => {
13761
- setRevealed((value) => {
13762
- if (value >= content.length) {
13763
- window.clearInterval(timer);
13764
- return value;
13765
- }
13766
- return Math.min(content.length, value + speed);
13767
- });
13768
- }, 24);
13769
- return () => window.clearInterval(timer);
13770
- }, [content, typing, speed]);
13771
- const typingDone = !typing || revealed >= content.length;
13772
- const showCursor = streaming || typing && !typingDone;
13773
- return /* @__PURE__ */ (0, import_jsx_runtime181.jsxs)("span", { "data-slot": "streaming-text", className: cn("whitespace-pre-wrap", className), style, children: [
13774
- typing ? content.slice(0, revealed) : content,
13775
- showCursor ? /* @__PURE__ */ (0, import_jsx_runtime181.jsx)(
13776
- "span",
13777
- {
13778
- "data-slot": "streaming-text-cursor",
13779
- "aria-hidden": "true",
13780
- className: "ml-0.5 inline-block animate-pulse text-primary motion-reduce:animate-none",
13781
- children: "\u258D"
13782
- }
13783
- ) : null
13784
- ] });
13785
- }
13786
-
13787
- // src/components/chat/Thinking/index.tsx
13788
- var import_react64 = require("react");
13789
- var import_jsx_runtime182 = require("react/jsx-runtime");
13790
- function Thinking({
13791
- content,
13792
- status = "thinking",
13793
- title,
13794
- expanded,
13795
- defaultExpanded,
13796
- onToggle,
13797
- className,
13798
- style
13799
- }) {
13800
- const [innerExpanded, setInnerExpanded] = (0, import_react64.useState)(defaultExpanded ?? status === "thinking");
13801
- const isExpanded = expanded ?? innerExpanded;
13802
- const resolvedTitle = title ?? (status === "thinking" ? "\u601D\u8003\u4E2D\u2026" : "\u601D\u8003\u5B8C\u6210");
13803
- const toggle = () => {
13804
- if (expanded === void 0) {
13805
- setInnerExpanded(!isExpanded);
13806
- }
13807
- onToggle?.(!isExpanded);
13808
- };
13809
- return /* @__PURE__ */ (0, import_jsx_runtime182.jsxs)(
13810
- "div",
13811
- {
13812
- "data-slot": "thinking",
13813
- "data-status": status,
13814
- className: cn("w-full", className),
13815
- style,
13816
- children: [
13817
- /* @__PURE__ */ (0, import_jsx_runtime182.jsxs)(
13818
- "button",
13819
- {
13820
- type: "button",
13821
- "data-slot": "thinking-trigger",
13822
- "aria-expanded": isExpanded,
13823
- className: "flex w-full cursor-pointer items-center gap-2 py-1 text-left text-sm",
13824
- onClick: toggle,
13825
- children: [
13826
- /* @__PURE__ */ (0, import_jsx_runtime182.jsx)("span", { className: cn("text-muted-foreground", status === "thinking" && "animate-pulse motion-reduce:animate-none"), children: /* @__PURE__ */ (0, import_jsx_runtime182.jsx)(Icon, { name: "brain", size: "sm" }) }),
13827
- /* @__PURE__ */ (0, import_jsx_runtime182.jsx)("span", { "data-slot": "thinking-title", className: "text-muted-foreground", children: resolvedTitle }),
13828
- /* @__PURE__ */ (0, import_jsx_runtime182.jsx)("span", { className: "text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime182.jsx)(Icon, { name: isExpanded ? "chevron-down" : "chevron-right", size: "sm" }) })
13829
- ]
13830
- }
13831
- ),
13832
- isExpanded && content ? /* @__PURE__ */ (0, import_jsx_runtime182.jsx)(
13833
- "div",
13834
- {
13835
- "data-slot": "thinking-content",
13836
- className: "py-1 pl-6 text-sm whitespace-pre-wrap text-muted-foreground",
13837
- children: content
13838
- }
13839
- ) : null
13840
- ]
13841
- }
13842
- );
13843
- }
13844
-
13845
- // src/components/chat/ToolCall/index.tsx
13846
- var import_react65 = require("react");
13847
- var import_jsx_runtime183 = require("react/jsx-runtime");
13848
- var statusIcon3 = {
13849
- running: { icon: "loader-circle", className: "text-info", spin: true },
13850
- done: { icon: "circle-check", className: "text-success" },
13851
- error: { icon: "circle-x", className: "text-destructive" }
13852
- };
13853
- function renderValue(value) {
13854
- if (value === void 0 || value === null) return "";
13855
- if (typeof value === "string") return value;
13856
- try {
13857
- return JSON.stringify(value, null, 2);
13858
- } catch {
13859
- return String(value);
13860
- }
13861
- }
13862
- function ToolCall({ name, params, status = "done", result, durationMs, defaultExpanded, className, style }) {
13863
- const [expanded, setExpanded] = (0, import_react65.useState)(defaultExpanded ?? status === "running");
13864
- const meta = statusIcon3[status];
13865
- const paramsText = renderValue(params);
13866
- const hasDetail = Boolean(paramsText) || Boolean(result);
13867
- const headerInner = /* @__PURE__ */ (0, import_jsx_runtime183.jsxs)(import_jsx_runtime183.Fragment, { children: [
13868
- /* @__PURE__ */ (0, import_jsx_runtime183.jsx)("span", { className: "shrink-0 text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime183.jsx)(Icon, { name: "terminal", size: "sm" }) }),
13869
- /* @__PURE__ */ (0, import_jsx_runtime183.jsx)("span", { "data-slot": "tool-call-name", className: "min-w-0 truncate font-medium", children: name ?? "\u5DE5\u5177\u8C03\u7528" }),
13870
- /* @__PURE__ */ (0, import_jsx_runtime183.jsx)("span", { className: cn("shrink-0", meta.className, meta.spin && "animate-spin motion-reduce:animate-none"), children: /* @__PURE__ */ (0, import_jsx_runtime183.jsx)(Icon, { name: meta.icon, size: "sm" }) }),
13871
- durationMs !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime183.jsxs)("span", { className: "shrink-0 text-xs text-muted-foreground", children: [
13872
- (durationMs / 1e3).toFixed(1),
13873
- "s"
13874
- ] }) : null,
13875
- hasDetail ? /* @__PURE__ */ (0, import_jsx_runtime183.jsx)("span", { className: "shrink-0 text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime183.jsx)(Icon, { name: expanded ? "chevron-down" : "chevron-right", size: "sm" }) }) : null
13876
- ] });
13877
- return /* @__PURE__ */ (0, import_jsx_runtime183.jsxs)(
13878
- "div",
13879
- {
13880
- "data-slot": "tool-call",
13881
- "data-status": status,
13882
- className: cn("w-full", className),
13883
- style,
13884
- children: [
13885
- hasDetail ? /* @__PURE__ */ (0, import_jsx_runtime183.jsx)(
13886
- "button",
13887
- {
13888
- type: "button",
13889
- "data-slot": "tool-call-trigger",
13890
- "aria-expanded": expanded,
13891
- className: "flex w-full cursor-pointer items-center gap-2 py-1 text-left text-sm",
13892
- onClick: () => setExpanded((value) => !value),
13893
- children: headerInner
13894
- }
13895
- ) : /* @__PURE__ */ (0, import_jsx_runtime183.jsx)(
13896
- "div",
13897
- {
13898
- "data-slot": "tool-call-trigger",
13899
- className: "flex w-full items-center gap-2 py-1 text-left text-sm",
13900
- children: headerInner
13901
- }
13902
- ),
13903
- hasDetail && expanded ? /* @__PURE__ */ (0, import_jsx_runtime183.jsxs)("div", { "data-slot": "tool-call-body", className: "flex flex-col gap-2 py-1 pl-6", children: [
13904
- paramsText ? /* @__PURE__ */ (0, import_jsx_runtime183.jsxs)("div", { children: [
13905
- /* @__PURE__ */ (0, import_jsx_runtime183.jsx)("div", { className: "text-xs font-medium text-muted-foreground", children: "\u53C2\u6570" }),
13906
- /* @__PURE__ */ (0, import_jsx_runtime183.jsx)("pre", { "data-slot": "tool-call-params", className: "mt-1 overflow-x-auto text-xs whitespace-pre-wrap text-muted-foreground", children: paramsText })
13907
- ] }) : null,
13908
- result ? /* @__PURE__ */ (0, import_jsx_runtime183.jsxs)("div", { children: [
13909
- /* @__PURE__ */ (0, import_jsx_runtime183.jsx)("div", { className: "text-xs font-medium text-muted-foreground", children: "\u7ED3\u679C" }),
13910
- /* @__PURE__ */ (0, import_jsx_runtime183.jsx)("pre", { "data-slot": "tool-call-result", className: "mt-1 overflow-x-auto text-xs whitespace-pre-wrap text-muted-foreground", children: result })
13911
- ] }) : null
13912
- ] }) : null
13913
- ]
13914
- }
13915
- );
13916
- }
13917
-
13918
- // src/components/chat/ChatMessage/index.tsx
13919
- var import_jsx_runtime184 = require("react/jsx-runtime");
13920
- function PartView({
13921
- part,
13922
- role,
13923
- onOpenArtifacts
13924
- }) {
13925
- if (role === "system" && (part.type === "text" || part.type === "markdown")) {
13926
- return /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(
13927
- "div",
13928
- {
13929
- "data-slot": "chat-message-system-part",
13930
- className: "w-full text-center text-xs text-muted-foreground",
13931
- children: part.type === "markdown" ? /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(import_markdown2.MarkdownDslComponent, { content: part.content }) : part.content
13932
- }
13933
- );
13934
- }
13935
- switch (part.type) {
13936
- case "text":
13937
- return /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(Bubble2, { align: role === "user" ? "end" : "start", variant: role === "user" ? "default" : "muted", children: /* @__PURE__ */ (0, import_jsx_runtime184.jsx)("span", { className: "text-sm whitespace-pre-wrap", children: part.content }) });
13938
- case "markdown":
13939
- return /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(Bubble2, { align: role === "user" ? "end" : "start", variant: role === "user" ? "default" : "ghost", children: /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(import_markdown2.MarkdownDslComponent, { content: part.content }) });
13940
- case "thinking":
13941
- return /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(Thinking, { content: part.content, status: part.status ?? "done" });
13942
- case "tool-call":
13943
- return /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(ToolCall, { name: part.name, params: part.params, status: part.status ?? "done", result: part.result });
13944
- case "tool-result":
13945
- return /* @__PURE__ */ (0, import_jsx_runtime184.jsx)("pre", { "data-slot": "chat-message-tool-result", className: "overflow-x-auto rounded-md bg-muted p-2 text-xs whitespace-pre-wrap", children: part.content });
13946
- case "status":
13947
- return /* @__PURE__ */ (0, import_jsx_runtime184.jsxs)("div", { "data-slot": "chat-message-status", className: "flex w-fit items-center gap-1.5 text-muted-foreground", children: [
13948
- /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(Icon, { name: "clock", size: "sm" }),
13949
- part.text
13950
- ] });
13951
- case "artifacts": {
13952
- const artifactsClass = "flex w-fit items-center gap-1.5 text-muted-foreground";
13953
- const label = `\u5DF2\u751F\u6210 ${part.count} \u4E2A\u4EA7\u7269`;
13954
- return onOpenArtifacts ? /* @__PURE__ */ (0, import_jsx_runtime184.jsxs)(
13955
- "button",
13956
- {
13957
- type: "button",
13958
- "data-slot": "chat-message-artifacts",
13959
- className: cn(artifactsClass, "cursor-pointer hover:text-foreground"),
13960
- onClick: onOpenArtifacts,
13961
- children: [
13962
- /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(Icon, { name: "package", size: "sm" }),
13963
- label,
13964
- /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(Icon, { name: "chevron-right", size: 12 })
13965
- ]
13966
- }
13967
- ) : /* @__PURE__ */ (0, import_jsx_runtime184.jsxs)("div", { "data-slot": "chat-message-artifacts", className: artifactsClass, children: [
13968
- /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(Icon, { name: "package", size: "sm" }),
13969
- label
13970
- ] });
13971
- }
13972
- case "error":
13973
- return /* @__PURE__ */ (0, import_jsx_runtime184.jsxs)("div", { "data-slot": "chat-message-error", className: "flex items-center gap-1.5 text-sm text-destructive", children: [
13974
- /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(Icon, { name: "circle-alert", size: "sm" }),
13975
- part.message
13976
- ] });
13977
- default:
13978
- return null;
13979
- }
13980
- }
13981
- var ACTION_ICON_BY_NAME = {
13982
- copy: "copy",
13983
- retry: "rotate-ccw",
13984
- regenerate: "refresh-ccw",
13985
- edit: "pencil",
13986
- like: "thumbs-up",
13987
- dislike: "thumbs-down",
13988
- share: "share",
13989
- delete: "trash"
13990
- };
13991
- function ChatMessage({
13992
- role = "assistant",
13993
- parts = [],
13994
- status = "completed",
13995
- agent,
13996
- time,
13997
- showSender = false,
13998
- actions = [],
13999
- onAction,
14000
- onOpenArtifacts,
14001
- className,
14002
- style
14003
- }) {
14004
- const isUser = role === "user";
14005
- const isSystem = role === "system";
14006
- const senderName = isUser ? "\u6211" : agent?.name ?? "\u52A9\u624B";
14007
- return /* @__PURE__ */ (0, import_jsx_runtime184.jsxs)(
14008
- "div",
14009
- {
14010
- "data-slot": "chat-message",
14011
- "data-role": role,
14012
- "data-status": status,
14013
- className: cn(
14014
- "flex w-full flex-col gap-1.5",
14015
- isUser && "items-end",
14016
- // system 居中弱提示(参考 @pactor-app/chat MessageBubble)
14017
- isSystem && "items-center text-muted-foreground",
14018
- className
14019
- ),
14020
- style,
14021
- children: [
14022
- showSender ? /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(
14023
- Sender,
14024
- {
14025
- name: senderName,
14026
- avatarText: isUser ? void 0 : agent?.icon ? void 0 : senderName.slice(0, 1),
14027
- time,
14028
- align: isUser ? "end" : "start"
14029
- }
14030
- ) : null,
14031
- /* @__PURE__ */ (0, import_jsx_runtime184.jsxs)("div", { className: cn("flex min-w-0 w-full max-w-full flex-col gap-2", isUser && "items-end", isSystem && "items-center"), children: [
14032
- parts.map((part, index) => /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(PartView, { part, role, onOpenArtifacts }, index)),
14033
- status === "streaming" ? /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(StreamingText, { content: "", streaming: true }) : null
14034
- ] }),
14035
- actions.length > 0 && (status === "completed" || status === "error") ? /* @__PURE__ */ (0, import_jsx_runtime184.jsx)("div", { "data-slot": "chat-message-actions", className: "flex items-center gap-1 mt-2", children: actions.map((action) => {
14036
- const label = action.label ?? action.name;
14037
- const iconName = action.icon ?? ACTION_ICON_BY_NAME[action.name];
14038
- if (iconName) {
14039
- return /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(Tooltip2, { content: label, side: "top", children: /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(
14040
- "button",
14041
- {
14042
- type: "button",
14043
- "data-slot": "chat-message-action",
14044
- "data-action": action.name,
14045
- "aria-label": label,
14046
- className: "flex cursor-pointer items-center rounded-sm p-1 text-muted-foreground hover:bg-accent hover:text-foreground",
14047
- onClick: () => onAction?.(action.name),
14048
- children: /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(Icon, { name: iconName, size: "sm" })
14049
- }
14050
- ) }, action.name);
14051
- }
14052
- return /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(
14053
- "button",
14054
- {
14055
- type: "button",
14056
- "data-slot": "chat-message-action",
14057
- "data-action": action.name,
14058
- className: "flex items-center cursor-pointer gap-1 rounded-sm px-1.5 py-0.5 text-xs text-muted-foreground hover:bg-accent hover:text-foreground",
14059
- onClick: () => onAction?.(action.name),
14060
- children: label
14061
- },
14062
- action.name
14063
- );
14064
- }) }) : null
14065
- ]
14066
- }
14067
- );
14068
- }
14069
-
14070
- // src/components/chat/ChatPage/index.tsx
14071
- var import_runtime51 = require("@pactor-app/runtime");
14072
- var import_react70 = require("react");
14073
-
14074
- // src/components/chat/Composer/index.tsx
14075
- var import_react67 = require("react");
14076
-
14077
- // src/components/chat/Composer/mention-input.tsx
14078
- var import_react66 = require("react");
14079
- var import_server = require("react-dom/server");
14080
- var import_jsx_runtime185 = require("react/jsx-runtime");
14081
- var NBSP = "\xA0";
14082
- var CHIP_ATTR = "data-mention-chip";
14083
- function escapeRegExp(text) {
14084
- return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
14085
- }
14086
- function isChipElement(node) {
14087
- return node instanceof HTMLElement && node.hasAttribute(CHIP_ATTR);
14088
- }
14089
- function serializeNode(node) {
14090
- let out = "";
14091
- node.childNodes.forEach((child) => {
14092
- if (child.nodeType === Node.TEXT_NODE) {
14093
- out += (child.textContent ?? "").replace(/\u00A0/g, " ");
14094
- } else if (isChipElement(child)) {
14095
- out += `${child.dataset["trigger"] ?? ""}${child.dataset["label"] ?? ""}`;
14096
- } else if (child instanceof HTMLBRElement) {
14097
- out += "\n";
14098
- } else if (child instanceof HTMLElement) {
14099
- const inner = serializeNode(child).replace(/\n$/, "");
14100
- out += (out === "" || out.endsWith("\n") ? "" : "\n") + inner + "\n";
14101
- }
14102
- });
14103
- return out;
14104
- }
14105
- function collectChips(field) {
14106
- return Array.from(field.querySelectorAll(`[${CHIP_ATTR}]`)).map((el) => ({
14107
- id: el.dataset["id"] ?? "",
14108
- label: el.dataset["label"] ?? "",
14109
- trigger: el.dataset["trigger"] ?? ""
14110
- }));
14111
- }
14112
- function detectActiveMention(field, sources) {
14113
- const selection = window.getSelection();
14114
- if (!selection || selection.rangeCount === 0 || !selection.isCollapsed) {
14115
- return null;
14116
- }
14117
- const anchor = selection.anchorNode;
14118
- if (!anchor || anchor.nodeType !== Node.TEXT_NODE || !field.contains(anchor)) {
14119
- return null;
14120
- }
14121
- const caretOffset = selection.anchorOffset;
14122
- const beforeCaret = (anchor.textContent ?? "").slice(0, caretOffset);
14123
- for (const source of sources) {
14124
- const trigger = source.trigger;
14125
- const match = new RegExp(
14126
- `(?:^|\\s)${escapeRegExp(trigger)}([^\\s${escapeRegExp(trigger)}]*)$`
14127
- ).exec(beforeCaret);
14128
- if (match) {
14129
- const query = match[1] ?? "";
14130
- return {
14131
- source,
14132
- query,
14133
- node: anchor,
14134
- triggerStart: caretOffset - query.length - trigger.length,
14135
- caretOffset
14136
- };
14137
- }
14138
- }
14139
- return null;
14140
- }
14141
- function chipIcon(item, source) {
14142
- return item.icon ?? source.icon ?? (source.trigger === "@" ? "user" : "file-text");
14143
- }
14144
- var MentionInput = (0, import_react66.forwardRef)(
14145
- function MentionInput2({
14146
- value,
14147
- placeholder,
14148
- disabled,
14149
- sources,
14150
- chips,
14151
- onChipsChange,
14152
- onChange,
14153
- onSubmit,
14154
- className,
14155
- style
14156
- }, ref) {
14157
- const fieldRef = (0, import_react66.useRef)(null);
14158
- const [menu, setMenu] = (0, import_react66.useState)(null);
14159
- const [empty, setEmpty] = (0, import_react66.useState)(true);
14160
- const suppressSyncRef = (0, import_react66.useRef)(false);
14161
- const composingRef = (0, import_react66.useRef)(false);
14162
- const emitChips = () => {
14163
- if (suppressSyncRef.current || !fieldRef.current) {
14164
- return;
14165
- }
14166
- onChipsChange?.(collectChips(fieldRef.current));
14167
- };
14168
- const serialize = () => fieldRef.current ? serializeNode(fieldRef.current).replace(/\n$/, "") : "";
14169
- const buildChipElement = (item, source) => {
14170
- const chip = document.createElement("span");
14171
- chip.setAttribute(CHIP_ATTR, "");
14172
- chip.dataset["id"] = item.id;
14173
- chip.dataset["label"] = item.label;
14174
- chip.dataset["trigger"] = item.trigger ?? source.trigger;
14175
- chip.contentEditable = "false";
14176
- chip.className = "mx-0.5 inline-flex items-center gap-1 rounded-md bg-muted px-1.5 py-0.5 align-middle text-xs text-foreground";
14177
- const iconMarkup = (0, import_server.renderToStaticMarkup)(
14178
- /* @__PURE__ */ (0, import_jsx_runtime185.jsx)(Icon, { name: chipIcon(item, source), size: 12 })
14179
- );
14180
- const label = document.createElement("span");
14181
- label.textContent = item.label;
14182
- chip.innerHTML = iconMarkup;
14183
- chip.appendChild(label);
14184
- return chip;
14185
- };
14186
- const insertChipElement = (item, source, replace) => {
14187
- const field = fieldRef.current;
14188
- if (!field) {
14189
- return;
14190
- }
14191
- const chip = buildChipElement(item, source);
14192
- let caretNode;
14193
- if (replace) {
14194
- const { node, start, end } = replace;
14195
- const text = node.textContent ?? "";
14196
- node.textContent = text.slice(0, start);
14197
- caretNode = document.createTextNode(`${NBSP}${text.slice(end)}`);
14198
- node.after(chip, caretNode);
14199
- } else {
14200
- caretNode = document.createTextNode(NBSP);
14201
- const selection2 = window.getSelection();
14202
- if (selection2 && selection2.rangeCount > 0 && selection2.anchorNode !== null && field.contains(selection2.anchorNode)) {
14203
- const range = selection2.getRangeAt(0);
14204
- range.deleteContents();
14205
- range.insertNode(caretNode);
14206
- range.insertNode(chip);
14207
- } else {
14208
- field.append(chip, caretNode);
14209
- }
14210
- }
14211
- const selection = window.getSelection();
14212
- if (selection) {
14213
- const range = document.createRange();
14214
- range.setStart(caretNode, 1);
14215
- range.collapse(true);
14216
- selection.removeAllRanges();
14217
- selection.addRange(range);
14218
- }
14219
- setEmpty(false);
14220
- onChange?.(serialize());
14221
- emitChips();
14222
- };
14223
- (0, import_react66.useImperativeHandle)(ref, () => ({
14224
- insertChip: (item, source) => {
14225
- fieldRef.current?.focus();
14226
- insertChipElement(item, source);
14227
- },
14228
- focus: () => fieldRef.current?.focus()
14229
- }));
14230
- (0, import_react66.useEffect)(() => {
14231
- const field = fieldRef.current;
14232
- if (field && value === "" && serializeNode(field).trim() !== "") {
14233
- suppressSyncRef.current = true;
14234
- field.innerHTML = "";
14235
- setEmpty(true);
14236
- setMenu(null);
14237
- suppressSyncRef.current = false;
14238
- }
14239
- }, [value]);
14240
- (0, import_react66.useEffect)(() => {
14241
- const field = fieldRef.current;
14242
- if (!field) {
14243
- return;
14244
- }
14245
- const keep = new Set(chips.map((chip) => `${chip.trigger}:${chip.id}`));
14246
- const stale = Array.from(field.querySelectorAll(`[${CHIP_ATTR}]`)).filter(
14247
- (el) => !keep.has(
14248
- `${el.dataset["trigger"]}:${el.dataset["id"]}`
14249
- )
14250
- );
14251
- if (stale.length > 0) {
14252
- suppressSyncRef.current = true;
14253
- stale.forEach((el) => el.remove());
14254
- suppressSyncRef.current = false;
14255
- setEmpty(serializeNode(field).trim() === "");
14256
- }
14257
- }, [chips]);
14258
- const closeMenu = () => setMenu(null);
14259
- const filteredItems = (state) => state.query ? state.source.items.filter((item) => item.label.includes(state.query)) : state.source.items;
14260
- const refreshMenu = () => {
14261
- const field = fieldRef.current;
14262
- if (!field) {
14263
- return;
14264
- }
14265
- const active = detectActiveMention(field, sources);
14266
- if (!active) {
14267
- setMenu(null);
14268
- return;
14269
- }
14270
- const range = document.createRange();
14271
- range.setStart(active.node, active.triggerStart);
14272
- range.setEnd(active.node, active.caretOffset);
14273
- const rect = typeof range.getBoundingClientRect === "function" ? range.getBoundingClientRect() : field.getBoundingClientRect();
14274
- setMenu((prev) => ({
14275
- source: active.source,
14276
- query: active.query,
14277
- left: rect.left,
14278
- top: rect.top,
14279
- // 过滤结果变化后候选下标钳制在有效范围内(DSL 每次渲染产出新
14280
- // props 对象,source 按 trigger 比较而非引用)
14281
- activeIndex: Math.min(
14282
- prev?.source.trigger === active.source.trigger ? prev.activeIndex : 0,
14283
- Math.max(filteredItems({ source: active.source, query: active.query, left: 0, top: 0, activeIndex: 0 }).length - 1, 0)
14284
- )
14285
- }));
14286
- };
14287
- const selectMenuItem = (item) => {
14288
- const field = fieldRef.current;
14289
- if (!field || !menu) {
14290
- return;
14291
- }
14292
- const active = detectActiveMention(field, sources);
14293
- insertChipElement(
14294
- { ...item, trigger: item.trigger ?? menu.source.trigger },
14295
- menu.source,
14296
- active && active.source.trigger === menu.source.trigger ? { node: active.node, start: active.triggerStart, end: active.caretOffset } : void 0
14297
- );
14298
- setMenu(null);
14299
- };
14300
- const handleInput = () => {
14301
- const field = fieldRef.current;
14302
- if (!field) {
14303
- return;
14304
- }
14305
- if ((field.textContent ?? "") === "" && field.querySelector(`[${CHIP_ATTR}]`) === null) {
14306
- field.innerHTML = "";
14307
- }
14308
- setEmpty(serializeNode(field).trim() === "");
14309
- onChange?.(serialize());
14310
- refreshMenu();
14311
- };
14312
- const handleKeyDown = (event) => {
14313
- if (menu) {
14314
- const items = filteredItems(menu);
14315
- if (event.key === "ArrowDown" || event.key === "ArrowUp") {
14316
- event.preventDefault();
14317
- if (items.length > 0) {
14318
- const delta = event.key === "ArrowDown" ? 1 : -1;
14319
- setMenu({
14320
- ...menu,
14321
- activeIndex: (menu.activeIndex + delta + items.length) % items.length
14322
- });
14323
- }
14324
- return;
14325
- }
14326
- if (event.key === "Enter" && !composingRef.current && !event.nativeEvent.isComposing) {
14327
- event.preventDefault();
14328
- const item = items[Math.min(menu.activeIndex, items.length - 1)];
14329
- if (item) {
14330
- selectMenuItem(item);
14331
- } else {
14332
- closeMenu();
14333
- }
14334
- return;
14335
- }
14336
- if (event.key === "Escape") {
14337
- event.preventDefault();
14338
- closeMenu();
14339
- return;
14340
- }
14341
- }
14342
- if (event.key === "Enter" && !event.shiftKey && !composingRef.current && !event.nativeEvent.isComposing) {
14343
- event.preventDefault();
14344
- const text = serialize();
14345
- if (text.trim() !== "" && !disabled) {
14346
- onSubmit?.(text);
14347
- }
14348
- return;
14349
- }
14350
- if (event.key === "Backspace") {
14351
- const selection = window.getSelection();
14352
- const field = fieldRef.current;
14353
- if (!selection || !selection.isCollapsed || !field) {
14354
- return;
14355
- }
14356
- let chip = null;
14357
- const anchor = selection.anchorNode;
14358
- if (anchor === field && selection.anchorOffset > 0) {
14359
- const before = field.childNodes[selection.anchorOffset - 1];
14360
- if (isChipElement(before)) {
14361
- chip = before;
14362
- }
14363
- } else if (anchor?.nodeType === Node.TEXT_NODE && selection.anchorOffset === 0) {
14364
- if (isChipElement(anchor.previousSibling)) {
14365
- chip = anchor.previousSibling;
14366
- }
14367
- }
14368
- if (chip) {
14369
- event.preventDefault();
14370
- chip.remove();
14371
- onChange?.(serialize());
14372
- emitChips();
14373
- setEmpty(serializeNode(field).trim() === "");
14374
- }
14375
- }
14376
- };
14377
- const menuItems = menu ? filteredItems(menu) : [];
14378
- const activeIndex = Math.min(menu?.activeIndex ?? 0, Math.max(menuItems.length - 1, 0));
14379
- return /* @__PURE__ */ (0, import_jsx_runtime185.jsxs)("div", { className: "relative", children: [
14380
- /* @__PURE__ */ (0, import_jsx_runtime185.jsx)(
14381
- "div",
14382
- {
14383
- ref: fieldRef,
14384
- "data-slot": "mention-input",
14385
- role: "textbox",
14386
- "aria-multiline": "true",
14387
- "aria-placeholder": placeholder,
14388
- contentEditable: !disabled,
14389
- suppressContentEditableWarning: true,
14390
- className: cn(
14391
- "min-h-[60px] w-full px-4 pt-3 pb-1 text-sm whitespace-pre-wrap break-words outline-none",
14392
- className
14393
- ),
14394
- style,
14395
- onInput: handleInput,
14396
- onKeyDown: handleKeyDown,
14397
- onCompositionStart: () => {
14398
- composingRef.current = true;
14399
- },
14400
- onCompositionEnd: () => {
14401
- composingRef.current = false;
14402
- },
14403
- onPaste: (event) => {
14404
- event.preventDefault();
14405
- const text = event.clipboardData?.getData("text/plain") ?? "";
14406
- if (text) {
14407
- document.execCommand("insertText", false, text);
14408
- }
14409
- }
14410
- }
14411
- ),
14412
- empty && placeholder !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime185.jsx)("span", { className: "pointer-events-none absolute top-3 left-4 text-sm text-muted-foreground", children: placeholder }) : null,
14413
- menu ? /* @__PURE__ */ (0, import_jsx_runtime185.jsxs)(import_jsx_runtime185.Fragment, { children: [
14414
- /* @__PURE__ */ (0, import_jsx_runtime185.jsx)(
14415
- "div",
14416
- {
14417
- className: "fixed inset-0 z-40",
14418
- onMouseDown: (event) => {
14419
- event.preventDefault();
14420
- closeMenu();
14421
- }
14422
- }
14423
- ),
14424
- /* @__PURE__ */ (0, import_jsx_runtime185.jsxs)(
14425
- "div",
14426
- {
14427
- "data-slot": "mention-menu",
14428
- role: "listbox",
14429
- className: "scrollbar-subtle fixed z-50 max-h-72 w-64 overflow-y-auto rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md",
14430
- style: {
14431
- left: menu.left,
14432
- bottom: typeof window === "undefined" ? void 0 : window.innerHeight - menu.top + 6
14433
- },
14434
- children: [
14435
- /* @__PURE__ */ (0, import_jsx_runtime185.jsx)("div", { className: "px-2 py-1 text-xs text-muted-foreground", children: menu.source.label }),
14436
- menuItems.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime185.jsx)("div", { className: "px-2 py-2 text-xs text-muted-foreground", children: "\u65E0\u5339\u914D\u9879" }) : menuItems.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime185.jsxs)(
14437
- "button",
14438
- {
14439
- type: "button",
14440
- role: "option",
14441
- "aria-selected": index === activeIndex,
14442
- className: cn(
14443
- "flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-left text-sm",
14444
- index === activeIndex ? "bg-accent" : "hover:bg-accent"
14445
- ),
14446
- onMouseDown: (event) => {
14447
- event.preventDefault();
14448
- selectMenuItem(item);
14449
- },
14450
- children: [
14451
- /* @__PURE__ */ (0, import_jsx_runtime185.jsx)(Icon, { name: chipIcon(item, menu.source), size: "sm" }),
14452
- /* @__PURE__ */ (0, import_jsx_runtime185.jsx)("span", { className: "min-w-0 flex-1 truncate", children: item.label })
14453
- ]
14454
- },
14455
- item.id
14456
- ))
14457
- ]
14458
- }
14459
- )
14460
- ] }) : null
14461
- ] });
14462
- }
14463
- );
14464
-
14465
- // src/components/chat/Composer/index.tsx
14466
- var import_jsx_runtime186 = require("react/jsx-runtime");
14467
- var toolButtonClass3 = "flex cursor-pointer items-center rounded-md p-1.5 text-muted-foreground hover:bg-accent hover:text-foreground";
14468
- var popoverPanelClass = "absolute bottom-full left-0 z-50 mb-2 max-h-72 w-64 overflow-y-auto rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md";
14469
- var popoverItemClass = "flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-left text-sm hover:bg-accent";
14470
- function Composer({
14471
- value,
14472
- placeholder,
14473
- disabled,
14474
- loading,
14475
- rows,
14476
- attachments = [],
14477
- onRemoveAttachment,
14478
- onRetryAttachment,
14479
- onAttachFiles,
14480
- onChange,
14481
- onSubmit,
14482
- models,
14483
- model,
14484
- onModelChange,
14485
- contexts,
14486
- contextItems,
14487
- onContextItemsChange,
14488
- footer,
14489
- className,
14490
- style
14491
- }) {
14492
- const textControlled = value !== void 0;
14493
- const [innerText, setInnerText] = (0, import_react67.useState)("");
14494
- const text = textControlled ? value : innerText;
14495
- const [dragOver, setDragOver] = (0, import_react67.useState)(false);
14496
- const [plusOpen, setPlusOpen] = (0, import_react67.useState)(false);
14497
- const [modelOpen, setModelOpen] = (0, import_react67.useState)(false);
14498
- const fileInputRef = (0, import_react67.useRef)(null);
14499
- const mentionRef = (0, import_react67.useRef)(null);
14500
- const sources = contexts ?? [];
14501
- const rich = sources.length > 0;
14502
- const plusSources = sources.filter((s) => s.trigger === "+");
14503
- const plusEnabled = plusSources.length > 0;
14504
- const modelEnabled = models !== void 0 && models.length > 0;
14505
- const currentModel = models?.find((m) => m.value === model) ?? models?.[0];
14506
- const [innerChips, setInnerChips] = (0, import_react67.useState)([]);
14507
- const chipsControlled = contextItems !== void 0;
14508
- const chips = chipsControlled ? contextItems : innerChips;
14509
- const handleChipsChange = (next) => {
14510
- if (!chipsControlled) {
14511
- setInnerChips(next);
14512
- }
14513
- onContextItemsChange?.(next);
14514
- };
14515
- const closePopovers = () => {
14516
- setPlusOpen(false);
14517
- setModelOpen(false);
14518
- };
14519
- const handleChange = (next) => {
14520
- if (!textControlled) {
14521
- setInnerText(next);
14522
- }
14523
- onChange?.(next);
14524
- };
14525
- const handleSubmit = (submitted) => {
14526
- onSubmit?.(submitted);
14527
- if (!textControlled) {
14528
- setInnerText("");
14529
- }
14530
- closePopovers();
14531
- };
14532
- const selectContext = (item, source) => {
14533
- if (rich) {
14534
- mentionRef.current?.insertChip(item, source);
14535
- } else {
14536
- const chip = { ...item, trigger: item.trigger ?? source.trigger };
14537
- const duplicated = chips.some(
14538
- (existing) => existing.id === chip.id && existing.trigger === chip.trigger
14539
- );
14540
- if (!duplicated) {
14541
- handleChipsChange([...chips, chip]);
14542
- }
14543
- }
14544
- closePopovers();
14545
- };
14546
- const emitFiles = (files) => {
14547
- if (files.length > 0 && onAttachFiles) {
14548
- onAttachFiles(files);
14549
- }
14550
- };
14551
- const handleDrop = (event) => {
14552
- if (!onAttachFiles) {
14553
- return;
14554
- }
14555
- event.preventDefault();
14556
- setDragOver(false);
14557
- emitFiles(Array.from(event.dataTransfer?.files ?? []));
14558
- };
14559
- const toolbarStart = plusEnabled || onAttachFiles ? /* @__PURE__ */ (0, import_jsx_runtime186.jsxs)(import_jsx_runtime186.Fragment, { children: [
14560
- plusEnabled ? /* @__PURE__ */ (0, import_jsx_runtime186.jsx)(
14561
- "button",
14562
- {
14563
- type: "button",
14564
- "aria-label": "\u6DFB\u52A0\u4E0A\u4E0B\u6587",
14565
- title: "\u6DFB\u52A0\u4E0A\u4E0B\u6587",
14566
- className: toolButtonClass3,
14567
- onClick: () => {
14568
- setPlusOpen((prev) => !prev);
14569
- setModelOpen(false);
14570
- },
14571
- children: /* @__PURE__ */ (0, import_jsx_runtime186.jsx)(Icon, { name: "plus", size: "sm" })
14572
- }
14573
- ) : null,
14574
- onAttachFiles ? /* @__PURE__ */ (0, import_jsx_runtime186.jsx)(
14575
- "button",
14576
- {
14577
- type: "button",
14578
- "aria-label": "\u6DFB\u52A0\u9644\u4EF6",
14579
- title: "\u6DFB\u52A0\u9644\u4EF6",
14580
- className: toolButtonClass3,
14581
- onClick: () => fileInputRef.current?.click(),
14582
- children: /* @__PURE__ */ (0, import_jsx_runtime186.jsx)(Icon, { name: "paperclip", size: "sm" })
14583
- }
14584
- ) : null
14585
- ] }) : void 0;
14586
- const toolbarEnd = modelEnabled ? /* @__PURE__ */ (0, import_jsx_runtime186.jsxs)(
14587
- "button",
14588
- {
14589
- type: "button",
14590
- "aria-label": "\u9009\u62E9\u6A21\u578B",
14591
- title: "\u9009\u62E9\u6A21\u578B",
14592
- className: "flex cursor-pointer items-center gap-1 rounded-md px-2 py-1 text-xs text-muted-foreground hover:bg-accent hover:text-foreground",
14593
- onClick: () => {
14594
- setModelOpen((prev) => !prev);
14595
- setPlusOpen(false);
14596
- },
14597
- children: [
14598
- currentModel?.label,
14599
- /* @__PURE__ */ (0, import_jsx_runtime186.jsx)(Icon, { name: "chevrons-up-down", size: 12 })
14600
- ]
14601
- }
14602
- ) : void 0;
14603
- const activePopover = plusOpen ? "plus" : modelOpen ? "model" : null;
14604
- return /* @__PURE__ */ (0, import_jsx_runtime186.jsxs)(
14605
- "div",
14606
- {
14607
- "data-slot": "composer",
14608
- className: cn("relative flex w-full flex-col gap-2", className),
14609
- style,
14610
- onDragOver: (event) => {
14611
- if (onAttachFiles) {
14612
- event.preventDefault();
14613
- setDragOver(true);
14614
- }
14615
- },
14616
- onDragLeave: () => setDragOver(false),
14617
- onDrop: handleDrop,
14618
- onPaste: (event) => {
14619
- const files = Array.from(event.clipboardData?.files ?? []);
14620
- if (files.length > 0 && onAttachFiles) {
14621
- event.preventDefault();
14622
- emitFiles(files);
14623
- }
14624
- },
14625
- children: [
14626
- attachments.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime186.jsx)(Attachment, { items: attachments, onRemove: onRemoveAttachment, onRetry: onRetryAttachment }) : null,
14627
- /* @__PURE__ */ (0, import_jsx_runtime186.jsx)("div", { className: cn(dragOver && "rounded-xl ring-2 ring-ring/50"), children: /* @__PURE__ */ (0, import_jsx_runtime186.jsx)(
14628
- ChatInput,
14629
- {
14630
- value: text,
14631
- placeholder,
14632
- disabled: disabled || loading,
14633
- rows,
14634
- toolbarStart,
14635
- toolbarEnd,
14636
- footer,
14637
- field: rich ? /* @__PURE__ */ (0, import_jsx_runtime186.jsx)(
14638
- MentionInput,
14639
- {
14640
- ref: mentionRef,
14641
- value: text,
14642
- placeholder,
14643
- disabled: disabled || loading,
14644
- sources,
14645
- chips,
14646
- onChipsChange: handleChipsChange,
14647
- onChange: handleChange,
14648
- onSubmit: handleSubmit
14649
- }
14650
- ) : void 0,
14651
- onChange: handleChange,
14652
- onSubmit: handleSubmit
14653
- }
14654
- ) }),
14655
- onAttachFiles ? /* @__PURE__ */ (0, import_jsx_runtime186.jsx)(
14656
- "input",
14657
- {
14658
- ref: fileInputRef,
14659
- type: "file",
14660
- multiple: true,
14661
- hidden: true,
14662
- onChange: (event) => {
14663
- emitFiles(Array.from(event.target.files ?? []));
14664
- event.target.value = "";
14665
- }
14666
- }
14667
- ) : null,
14668
- activePopover !== null ? /* @__PURE__ */ (0, import_jsx_runtime186.jsxs)(import_jsx_runtime186.Fragment, { children: [
14669
- /* @__PURE__ */ (0, import_jsx_runtime186.jsx)("div", { className: "fixed inset-0 z-40", onClick: closePopovers }),
14670
- activePopover === "model" ? /* @__PURE__ */ (0, import_jsx_runtime186.jsx)("div", { "data-slot": "composer-model-popover", className: cn(popoverPanelClass, "right-0 left-auto w-48"), role: "listbox", children: models.map((option) => /* @__PURE__ */ (0, import_jsx_runtime186.jsxs)(
14671
- "button",
14672
- {
14673
- type: "button",
14674
- role: "option",
14675
- "aria-selected": option.value === currentModel?.value,
14676
- className: popoverItemClass,
14677
- onClick: () => {
14678
- onModelChange?.(option.value);
14679
- closePopovers();
14680
- },
14681
- children: [
14682
- /* @__PURE__ */ (0, import_jsx_runtime186.jsx)("span", { className: "min-w-0 flex-1 truncate", children: option.label }),
14683
- option.value === currentModel?.value ? /* @__PURE__ */ (0, import_jsx_runtime186.jsx)(Icon, { name: "check", size: 14 }) : null
14684
- ]
14685
- },
14686
- option.value
14687
- )) }) : /* @__PURE__ */ (0, import_jsx_runtime186.jsx)("div", { "data-slot": "composer-context-popover", className: popoverPanelClass, role: "listbox", children: plusSources.map(
14688
- (source) => source.items.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime186.jsxs)("div", { children: [
14689
- /* @__PURE__ */ (0, import_jsx_runtime186.jsx)("div", { className: "px-2 py-1 text-xs text-muted-foreground", children: source.label }),
14690
- source.items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime186.jsxs)(
14691
- "button",
14692
- {
14693
- type: "button",
14694
- className: popoverItemClass,
14695
- onClick: () => selectContext(item, source),
14696
- children: [
14697
- /* @__PURE__ */ (0, import_jsx_runtime186.jsx)(Icon, { name: item.icon ?? source.icon ?? "file-text", size: "sm" }),
14698
- /* @__PURE__ */ (0, import_jsx_runtime186.jsx)("span", { className: "min-w-0 flex-1 truncate", children: item.label })
14699
- ]
14700
- },
14701
- item.id
14702
- ))
14703
- ] }, source.trigger)
14704
- ) })
14705
- ] }) : null
14706
- ]
14707
- }
14708
- );
14709
- }
14710
-
14711
- // src/components/chat/ConversationList/index.tsx
14712
- var import_react68 = require("react");
14713
- var import_jsx_runtime187 = require("react/jsx-runtime");
14714
- function ConversationList({ items = [], activeId, searchable, onSelect, onDelete, className, style }) {
14715
- const [innerActive, setInnerActive] = (0, import_react68.useState)();
14716
- const [keyword, setKeyword] = (0, import_react68.useState)("");
14717
- const active = activeId ?? innerActive;
14718
- const filtered = (0, import_react68.useMemo)(() => {
14719
- const query = keyword.trim().toLowerCase();
14720
- if (!query) return items;
14721
- return items.filter(
14722
- (item) => item.title.toLowerCase().includes(query) || (item.description ?? "").toLowerCase().includes(query)
14723
- );
14724
- }, [items, keyword]);
14725
- const select = (id) => {
14726
- if (activeId === void 0) {
14727
- setInnerActive(id);
14728
- }
14729
- onSelect?.(id);
14730
- };
14731
- return /* @__PURE__ */ (0, import_jsx_runtime187.jsxs)("div", { "data-slot": "conversation-list", className: cn("flex w-full flex-col gap-1", className), style, children: [
14732
- searchable ? /* @__PURE__ */ (0, import_jsx_runtime187.jsxs)("div", { className: "relative mb-1", children: [
14733
- /* @__PURE__ */ (0, import_jsx_runtime187.jsx)("span", { className: "absolute top-1/2 left-2 -translate-y-1/2 text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime187.jsx)(Icon, { name: "search", size: "sm" }) }),
14734
- /* @__PURE__ */ (0, import_jsx_runtime187.jsx)(
14735
- "input",
14736
- {
14737
- "data-slot": "conversation-list-search",
14738
- value: keyword,
14739
- placeholder: "\u641C\u7D22\u4F1A\u8BDD",
14740
- className: "h-8 w-full rounded-md border border-border bg-background pr-2 pl-7 text-sm outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50",
14741
- onChange: (event) => setKeyword(event.target.value)
14742
- }
14743
- )
14744
- ] }) : null,
14745
- filtered.map((item) => /* @__PURE__ */ (0, import_jsx_runtime187.jsxs)(
14746
- "div",
14747
- {
14748
- "data-slot": "conversation-list-item",
14749
- "data-active": item.id === active || void 0,
14750
- className: cn(
14751
- "group flex cursor-pointer items-center gap-2 rounded-md px-2 py-1.5 hover:bg-accent",
14752
- item.id === active && "bg-accent"
14753
- ),
14754
- onClick: () => select(item.id),
14755
- children: [
14756
- /* @__PURE__ */ (0, import_jsx_runtime187.jsxs)("div", { className: "min-w-0 flex-1", children: [
14757
- /* @__PURE__ */ (0, import_jsx_runtime187.jsx)("div", { className: cn("truncate text-sm", item.id === active && "font-medium"), children: item.title }),
14758
- item.description ? /* @__PURE__ */ (0, import_jsx_runtime187.jsx)("div", { className: "truncate text-xs text-muted-foreground", children: item.description }) : null
14759
- ] }),
14760
- item.time ? /* @__PURE__ */ (0, import_jsx_runtime187.jsx)("span", { className: "shrink-0 text-xs text-muted-foreground", children: item.time }) : null,
14761
- onDelete ? /* @__PURE__ */ (0, import_jsx_runtime187.jsx)(
14762
- "button",
14763
- {
14764
- type: "button",
14765
- "data-slot": "conversation-list-delete",
14766
- "aria-label": `\u5220\u9664 ${item.title}`,
14767
- className: "shrink-0 text-muted-foreground opacity-0 group-hover:opacity-100 hover:text-destructive",
14768
- onClick: (event) => {
14769
- event.stopPropagation();
14770
- onDelete(item.id);
14771
- },
14772
- children: /* @__PURE__ */ (0, import_jsx_runtime187.jsx)(Icon, { name: "trash-2", size: "sm" })
14773
- }
14774
- ) : null
14775
- ]
14776
- },
14777
- item.id
14778
- )),
14779
- filtered.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime187.jsx)("div", { className: "px-2 py-4 text-center text-sm text-muted-foreground", children: "\u65E0\u5339\u914D\u4F1A\u8BDD" }) : null
14780
- ] });
14781
- }
14782
-
14783
- // src/components/chat/MessageList/index.tsx
14784
- var import_react69 = require("react");
14785
- var import_jsx_runtime188 = require("react/jsx-runtime");
14786
- function MessageList({ messages = [], autoScroll = true, onAction, onOpenArtifacts, className, style }) {
14787
- const listRef = (0, import_react69.useRef)(null);
14788
- (0, import_react69.useEffect)(() => {
14789
- if (!autoScroll) return;
14790
- const el = listRef.current;
14791
- if (el) {
14792
- el.scrollTop = el.scrollHeight;
14793
- }
14794
- }, [messages, autoScroll]);
14795
- return /* @__PURE__ */ (0, import_jsx_runtime188.jsx)(
14796
- "div",
14797
- {
14798
- ref: listRef,
14799
- "data-slot": "message-list",
14800
- className: cn("flex w-full flex-col gap-4 overflow-y-auto", className),
14801
- style,
14802
- children: messages.map((message, index) => /* @__PURE__ */ (0, import_jsx_runtime188.jsx)(
14803
- ChatMessage,
14804
- {
14805
- ...message,
14806
- onAction: (action) => onAction?.({ id: message.id, action }),
14807
- onOpenArtifacts: onOpenArtifacts ? () => onOpenArtifacts({ id: message.id }) : void 0
14808
- },
14809
- message.id ?? index
14810
- ))
14811
- }
14812
- );
14813
- }
14814
-
14815
- // src/components/chat/Prompt/index.tsx
14816
- var import_jsx_runtime189 = require("react/jsx-runtime");
14817
- function Prompt({ title, description, icon, value, disabled, onSelect, className, style }) {
14818
- return /* @__PURE__ */ (0, import_jsx_runtime189.jsxs)(
14819
- "button",
14820
- {
14821
- type: "button",
14822
- "data-slot": "prompt",
14823
- disabled,
14824
- className: cn(
14825
- "flex items-start gap-2.5 rounded-md border border-border p-3 text-left transition-colors hover:border-primary disabled:pointer-events-none disabled:opacity-50",
14826
- className
14827
- ),
14828
- style,
14829
- onClick: () => onSelect?.(value ?? title ?? ""),
14830
- children: [
14831
- icon ? /* @__PURE__ */ (0, import_jsx_runtime189.jsx)("span", { className: "mt-0.5 shrink-0 text-primary", children: /* @__PURE__ */ (0, import_jsx_runtime189.jsx)(Icon, { name: icon, size: "sm" }) }) : null,
14832
- /* @__PURE__ */ (0, import_jsx_runtime189.jsxs)("span", { className: "min-w-0", children: [
14833
- /* @__PURE__ */ (0, import_jsx_runtime189.jsx)("span", { "data-slot": "prompt-title", className: "block text-sm font-medium", children: title }),
14834
- description ? /* @__PURE__ */ (0, import_jsx_runtime189.jsx)("span", { "data-slot": "prompt-description", className: "mt-0.5 block text-xs text-muted-foreground", children: description }) : null
14835
- ] })
14836
- ]
14837
- }
14838
- );
14839
- }
14840
-
14841
- // src/components/chat/Welcome/index.tsx
14842
- var import_jsx_runtime190 = require("react/jsx-runtime");
14843
- function Welcome({
14844
- title = "\u6709\u4EC0\u4E48\u53EF\u4EE5\u5E2E\u4F60\uFF1F",
14845
- description,
14846
- icon = "chat",
14847
- prompts = [],
14848
- onSelect,
14849
- className,
14850
- style
14851
- }) {
14852
- return /* @__PURE__ */ (0, import_jsx_runtime190.jsxs)(
14853
- "div",
14854
- {
14855
- "data-slot": "welcome",
14856
- className: cn("flex w-full flex-col items-center gap-4 py-10 text-center", className),
14857
- style,
14858
- children: [
14859
- /* @__PURE__ */ (0, import_jsx_runtime190.jsx)("span", { "data-slot": "welcome-icon", className: "text-primary", children: /* @__PURE__ */ (0, import_jsx_runtime190.jsx)(Icon, { name: icon, size: "lg" }) }),
14860
- /* @__PURE__ */ (0, import_jsx_runtime190.jsxs)("div", { children: [
14861
- /* @__PURE__ */ (0, import_jsx_runtime190.jsx)("div", { "data-slot": "welcome-title", className: "text-xl font-semibold", children: title }),
14862
- description ? /* @__PURE__ */ (0, import_jsx_runtime190.jsx)("div", { "data-slot": "welcome-description", className: "mt-1 text-sm text-muted-foreground", children: description }) : null
14863
- ] }),
14864
- prompts.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime190.jsx)("div", { "data-slot": "welcome-prompts", className: "grid w-full max-w-xl grid-cols-1 gap-3 text-left sm:grid-cols-2", children: prompts.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime190.jsx)(
14865
- Prompt,
14866
- {
14867
- title: item.title,
14868
- description: item.description,
14869
- icon: item.icon,
14870
- value: item.value,
14871
- onSelect
14872
- },
14873
- `${item.title}-${index}`
14874
- )) }) : null
14875
- ]
14876
- }
14877
- );
14878
- }
14879
-
14880
- // src/components/chat/ChatPage/index.tsx
14881
- var import_jsx_runtime191 = require("react/jsx-runtime");
14882
- function ChatPage({
14883
- brand,
14884
- menuItems = [],
14885
- activeMenuKey,
14886
- railItems = [],
14887
- railFooterItems = [],
14888
- menuAction,
14889
- onMenuSelect,
14890
- onMenuAction,
14891
- conversationSectionTitle,
14892
- conversationSectionCollapsed,
14893
- defaultConversationSectionCollapsed = false,
14894
- onConversationSectionToggle,
14895
- conversations = [],
14896
- activeConversationId,
14897
- onSelectConversation,
14898
- onDeleteConversation,
14899
- moreLabel,
14900
- onMore,
14901
- footerSectionTitle,
14902
- footerItems = [],
14903
- footerSectionCollapsed,
14904
- defaultFooterSectionCollapsed = false,
14905
- onFooterSectionToggle,
14906
- conversationTitle,
14907
- conversationHeaderAction,
14908
- onConversationHeaderAction,
14909
- conversationRailItems = [],
14910
- hideArtifactRailItem = false,
14911
- activeConversationRailKey,
14912
- onConversationRailChange,
14913
- messages = [],
14914
- sending,
14915
- composerPlaceholder,
14916
- welcome,
14917
- onSend,
14918
- onMessageAction,
14919
- models,
14920
- model,
14921
- onModelChange,
14922
- contexts,
14923
- contextItems,
14924
- onContextItemsChange,
14925
- attachments,
14926
- onAttachFiles,
14927
- onRemoveAttachment,
14928
- onRetryAttachment,
14929
- composerFooter,
14930
- composerBottom,
14931
- artifactTitle = "\u4EA7\u7269",
14932
- artifacts = [],
14933
- activeArtifactId,
14934
- onSelectArtifact,
14935
- artifactEmptyText = "\u6682\u65E0\u4EA7\u7269\uFF0C\u53D1\u9001\u6D88\u606F\u540E\u751F\u6210\u7684\u6587\u4EF6\u5C06\u5C55\u793A\u5728\u8FD9\u91CC",
14936
- safeRegistry,
14937
- user,
14938
- artifactViewers,
14939
- onDownloadArtifact,
14940
- artifactOpen,
14941
- defaultArtifactOpen = false,
14942
- onArtifactOpenChange,
14943
- content,
14944
- className,
14945
- style
14946
- }) {
14947
- const controlled = artifactOpen !== void 0;
14948
- const [innerOpen, setInnerOpen] = (0, import_react70.useState)(defaultArtifactOpen);
14949
- const open = controlled ? artifactOpen === true : innerOpen;
14950
- const setOpen = (next) => {
14951
- if (!controlled) setInnerOpen(next);
14952
- onArtifactOpenChange?.(next);
14953
- };
14954
- const railControlled = activeConversationRailKey !== void 0;
14955
- const [activeRailInner, setActiveRailInner] = (0, import_react70.useState)(null);
14956
- const activeRailKey = railControlled ? activeConversationRailKey : activeRailInner;
14957
- const setActiveRailKey = (next) => {
14958
- if (!railControlled) setActiveRailInner(next);
14959
- onConversationRailChange?.(next);
14960
- };
14961
- const visibleRailItems = conversationRailItems.filter((item) => item.hidden !== true);
14962
- const activeRailItem = visibleRailItems.find(
14963
- (item) => item.key === activeRailKey
14964
- );
14965
- const activePanelItem = activeRailItem?.display === "panel" && activeRailItem.content !== void 0 ? activeRailItem : void 0;
14966
- const activePopoverItem = activeRailItem !== void 0 && activeRailItem.display !== "panel" && activeRailItem.content !== void 0 ? activeRailItem : void 0;
14967
- const toggleRailItem = (item) => {
14968
- const next = activeRailKey === item.key ? null : item.key;
14969
- if (next !== null && item.display === "panel") {
14970
- setOpen(false);
14971
- }
14972
- setActiveRailKey(next);
14973
- };
14974
- const toggleArtifact = () => {
14975
- if (!open && activePanelItem) {
14976
- setActiveRailKey(null);
14977
- }
14978
- setOpen(!open);
14979
- };
14980
- (0, import_react70.useEffect)(() => {
14981
- if (!activePopoverItem) return;
14982
- const onKeyDown = (event) => {
14983
- if (event.key === "Escape") setActiveRailKey(null);
14984
- };
14985
- const onPointerDown = (event) => {
14986
- const target = event.target;
14987
- if (target.closest("[data-slot=chat-page-rail-popover]") || target.closest("[data-slot=chat-page-conv-rail]")) {
14988
- return;
14989
- }
14990
- setActiveRailKey(null);
14991
- };
14992
- document.addEventListener("keydown", onKeyDown);
14993
- document.addEventListener("mousedown", onPointerDown);
14994
- return () => {
14995
- document.removeEventListener("keydown", onKeyDown);
14996
- document.removeEventListener("mousedown", onPointerDown);
14997
- };
14998
- });
14999
- const { renderChildren } = (0, import_runtime51.useRenderer)();
15000
- const renderSlot = (slot) => (0, import_react70.isValidElement)(slot) || typeof slot !== "object" || slot === null ? slot : renderChildren([slot]);
15001
- const convCollControlled = conversationSectionCollapsed !== void 0;
15002
- const [convCollapsedInner, setConvCollapsedInner] = (0, import_react70.useState)(
15003
- defaultConversationSectionCollapsed
15004
- );
15005
- const convCollapsed = convCollControlled ? conversationSectionCollapsed === true : convCollapsedInner;
15006
- const toggleConvSection = () => {
15007
- const next = !convCollapsed;
15008
- if (!convCollControlled) setConvCollapsedInner(next);
15009
- onConversationSectionToggle?.(next);
15010
- };
15011
- const footerCollControlled = footerSectionCollapsed !== void 0;
15012
- const [footerCollapsedInner, setFooterCollapsedInner] = (0, import_react70.useState)(
15013
- defaultFooterSectionCollapsed
15014
- );
15015
- const footerCollapsed = footerCollControlled ? footerSectionCollapsed === true : footerCollapsedInner;
15016
- const toggleFooterSection = () => {
15017
- const next = !footerCollapsed;
15018
- if (!footerCollControlled) setFooterCollapsedInner(next);
15019
- onFooterSectionToggle?.(next);
15020
- };
15021
- const railVisible = railItems.length > 0 || railFooterItems.length > 0;
15022
- const railButton = (item) => /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(Tooltip2, { content: item.label, side: "right", children: /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(
15023
- Button2,
15024
- {
15025
- icon: item.icon,
15026
- variant: "text",
15027
- onClick: () => onMenuSelect?.(item.key)
15028
- }
15029
- ) }, item.key);
15030
- const convRailButton = (item, active, onClick) => {
15031
- const button = /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(
15032
- Button2,
15033
- {
15034
- icon: item.icon,
15035
- variant: "text",
15036
- className: cn(active ? "bg-accent text-accent-foreground" : void 0, "px-2"),
15037
- onClick
15038
- }
15039
- );
15040
- return item.label !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(Tooltip2, { content: item.label, side: "left", children: button }, item.key) : /* @__PURE__ */ (0, import_jsx_runtime191.jsx)("span", { children: button }, item.key);
15041
- };
15042
- const convRailVisible = !hideArtifactRailItem || visibleRailItems.length > 0;
15043
- const convRail = convRailVisible ? /* @__PURE__ */ (0, import_jsx_runtime191.jsxs)(
15044
- "div",
15045
- {
15046
- "data-slot": "chat-page-conv-rail",
15047
- className: "relative flex w-(--pactor-chat-rail-width) shrink-0 flex-col items-center gap-1 px-1 py-2",
15048
- children: [
15049
- !hideArtifactRailItem ? convRailButton(
15050
- {
15051
- key: "artifact",
15052
- icon: open ? "panel-right-close" : "package",
15053
- label: open ? "\u6536\u8D77\u4EA7\u7269\u533A" : artifactTitle
15054
- },
15055
- open,
15056
- toggleArtifact
15057
- ) : null,
15058
- visibleRailItems.map(
15059
- (item) => convRailButton(item, activeRailKey === item.key, () => toggleRailItem(item))
15060
- ),
15061
- activePopoverItem ? /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(
15062
- "div",
15063
- {
15064
- "data-slot": "chat-page-rail-popover",
15065
- className: "absolute right-full top-0 z-10 mr-2 overflow-auto rounded-lg border border-border bg-popover shadow-md",
15066
- style: {
15067
- width: "var(--pactor-chat-rail-popover-width)",
15068
- maxWidth: "calc(100cqw - 2rem)",
15069
- maxHeight: "calc(100% - 1rem)"
15070
- },
15071
- children: renderSlot(activePopoverItem.content)
15072
- }
15073
- ) : null
15074
- ]
15075
- }
15076
- ) : null;
15077
- const chatArea = /* @__PURE__ */ (0, import_jsx_runtime191.jsxs)("div", { "data-slot": "chat-page-conversation", className: "flex h-full min-w-0 flex-1 flex-col", children: [
15078
- /* @__PURE__ */ (0, import_jsx_runtime191.jsxs)(
15079
- "div",
15080
- {
15081
- "data-slot": "chat-page-conversation-header",
15082
- className: "flex shrink-0 items-center justify-between border-b border-border px-4 py-2.5",
15083
- children: [
15084
- /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(Text, { text: conversationTitle, strong: true }),
15085
- conversationHeaderAction ? /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(Tooltip2, { content: conversationHeaderAction.tooltip ?? conversationHeaderAction.label, side: "bottom", children: /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(
15086
- Button2,
15087
- {
15088
- text: conversationHeaderAction.label,
15089
- icon: conversationHeaderAction.icon,
15090
- variant: "text",
15091
- onClick: () => onConversationHeaderAction?.()
15092
- }
15093
- ) }) : null
15094
- ]
15095
- }
15096
- ),
15097
- /* @__PURE__ */ (0, import_jsx_runtime191.jsxs)("div", { className: "flex min-h-0 flex-1", children: [
15098
- /* @__PURE__ */ (0, import_jsx_runtime191.jsxs)(
15099
- "div",
15100
- {
15101
- "data-slot": "chat-page-conversation-body",
15102
- className: "mx-auto flex min-h-0 w-[61.8cqw] max-w-full flex-col",
15103
- children: [
15104
- messages.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(
15105
- Welcome,
15106
- {
15107
- title: welcome?.title,
15108
- description: welcome?.description,
15109
- prompts: welcome?.prompts,
15110
- style: { flex: 1 },
15111
- onSelect: (value) => onSend?.(value)
15112
- }
15113
- ) : /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(
15114
- MessageList,
15115
- {
15116
- messages,
15117
- className: "scrollbar-subtle",
15118
- style: { flex: 1, minHeight: 0, padding: 16 },
15119
- onAction: onMessageAction,
15120
- onOpenArtifacts: () => setOpen(true)
15121
- }
15122
- ),
15123
- /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(
15124
- Composer,
15125
- {
15126
- placeholder: composerPlaceholder,
15127
- loading: sending,
15128
- models,
15129
- model,
15130
- contexts,
15131
- contextItems,
15132
- attachments,
15133
- footer: composerFooter,
15134
- style: { padding: 16, paddingBottom: composerBottom ? 8 : 16, flexShrink: 0 },
15135
- onModelChange,
15136
- onContextItemsChange,
15137
- onAttachFiles,
15138
- onRemoveAttachment,
15139
- onRetryAttachment,
15140
- onSubmit: (text) => onSend?.(text)
15141
- }
15142
- ),
15143
- composerBottom ? /* @__PURE__ */ (0, import_jsx_runtime191.jsx)("div", { "data-slot": "chat-page-composer-bottom", className: "shrink-0 px-4 pb-2 text-center", children: renderSlot(composerBottom) }) : null
15144
- ]
15145
- }
15146
- ),
15147
- convRail
15148
- ] })
15149
- ] });
15150
- const activeArtifact = artifacts.find((item) => item.id === activeArtifactId) ?? (activeArtifactId === void 0 || activeArtifactId === "" ? artifacts[artifacts.length - 1] : void 0);
15151
- const artifactPanel = /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(
15152
- "div",
15153
- {
15154
- "data-slot": "chat-page-artifact",
15155
- className: "flex h-full min-w-0 flex-col border-l border-border bg-muted",
15156
- children: /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(
15157
- ArtifactPanel,
15158
- {
15159
- artifact: activeArtifact,
15160
- artifacts,
15161
- activeArtifactId,
15162
- title: artifactTitle,
15163
- emptyText: artifactEmptyText,
15164
- safeRegistry,
15165
- user,
15166
- artifactViewers,
15167
- onSelectArtifact: (id) => onSelectArtifact?.(id),
15168
- onDownload: onDownloadArtifact,
15169
- onClose: () => setOpen(false)
15170
- }
15171
- )
15172
- }
15173
- );
15174
- return /* @__PURE__ */ (0, import_jsx_runtime191.jsxs)(
15175
- "div",
15176
- {
15177
- "data-slot": "chat-page",
15178
- className: cn("flex w-full overflow-hidden", className),
15179
- style: { height: "100vh", ...style },
15180
- children: [
15181
- railVisible ? /* @__PURE__ */ (0, import_jsx_runtime191.jsxs)(
15182
- "div",
15183
- {
15184
- "data-slot": "chat-page-rail",
15185
- className: "flex h-full w-[52px] shrink-0 flex-col items-center gap-1 border-r border-border py-2.5",
15186
- children: [
15187
- railItems.map(railButton),
15188
- /* @__PURE__ */ (0, import_jsx_runtime191.jsx)("div", { className: "flex-1" }),
15189
- railFooterItems.map(railButton)
15190
- ]
15191
- }
15192
- ) : null,
15193
- /* @__PURE__ */ (0, import_jsx_runtime191.jsxs)(
15194
- "div",
15195
- {
15196
- "data-slot": "chat-page-menu",
15197
- className: "flex h-full w-[250px] shrink-0 flex-col gap-2 overflow-hidden border-r border-border px-2 py-3",
15198
- children: [
15199
- brand ? /* @__PURE__ */ (0, import_jsx_runtime191.jsxs)("div", { className: "flex shrink-0 items-center justify-between px-2", children: [
15200
- /* @__PURE__ */ (0, import_jsx_runtime191.jsxs)("div", { className: "flex flex-col gap-0.5", children: [
15201
- /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(Text, { text: brand.title, strong: true, size: "large" }),
15202
- brand.version !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(Text, { text: brand.version, type: "secondary", size: "small" }) : null
15203
- ] }),
15204
- menuAction ? /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(
15205
- Button2,
15206
- {
15207
- text: menuAction.label,
15208
- icon: menuAction.icon,
15209
- size: "small",
15210
- onClick: () => onMenuAction?.()
15211
- }
15212
- ) : null
15213
- ] }) : null,
15214
- /* @__PURE__ */ (0, import_jsx_runtime191.jsx)("div", { className: "scrollbar-subtle max-h-[40%] min-h-0 shrink-0 overflow-y-auto", children: /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(
15215
- Menu2,
15216
- {
15217
- items: menuItems,
15218
- selectedKey: activeMenuKey,
15219
- onSelect: (key) => onMenuSelect?.(key)
15220
- }
15221
- ) }),
15222
- conversationSectionTitle !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime191.jsxs)(
15223
- "button",
15224
- {
15225
- type: "button",
15226
- "data-slot": "chat-page-section-toggle",
15227
- "aria-expanded": !convCollapsed,
15228
- className: "flex w-full shrink-0 cursor-pointer items-center justify-between px-2 pt-2",
15229
- onClick: toggleConvSection,
15230
- children: [
15231
- /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(
15232
- Text,
15233
- {
15234
- text: `${conversationSectionTitle} (${conversations.length})`,
15235
- type: "secondary",
15236
- className: "text-sm",
15237
- strong: true
15238
- }
15239
- ),
15240
- /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(Icon, { name: convCollapsed ? "chevron-right" : "chevron-down", size: 14 })
15241
- ]
15242
- }
15243
- ) : null,
15244
- !convCollapsed ? /* @__PURE__ */ (0, import_jsx_runtime191.jsxs)("div", { "data-slot": "chat-page-section-body", className: "scrollbar-subtle flex min-h-0 flex-1 flex-col overflow-y-auto", children: [
15245
- /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(
15246
- ConversationList,
15247
- {
15248
- items: conversations,
15249
- activeId: activeConversationId,
15250
- onSelect: (id) => onSelectConversation?.(id),
15251
- onDelete: (id) => onDeleteConversation?.(id)
15252
- }
15253
- ),
15254
- moreLabel !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime191.jsx)("div", { className: "flex justify-end", children: /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(Button2, { text: `${moreLabel} >>`, variant: "link", size: "small", onClick: () => onMore?.() }) }) : null
15255
- ] }) : null,
15256
- footerSectionTitle !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime191.jsxs)(
15257
- "button",
15258
- {
15259
- type: "button",
15260
- "data-slot": "chat-page-section-toggle",
15261
- "aria-expanded": !footerCollapsed,
15262
- className: "flex w-full shrink-0 cursor-pointer items-center justify-between px-2 pt-2",
15263
- onClick: toggleFooterSection,
15264
- children: [
15265
- /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(Text, { text: footerSectionTitle, type: "secondary", className: "text-sm", strong: true }),
15266
- /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(Icon, { name: footerCollapsed ? "chevron-right" : "chevron-down", size: 14 })
15267
- ]
15268
- }
15269
- ) : null,
15270
- !footerCollapsed && footerItems.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime191.jsx)("div", { "data-slot": "chat-page-section-body", className: "scrollbar-subtle min-h-0 flex-1 overflow-y-auto", children: /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(
15271
- Menu2,
15272
- {
15273
- items: footerItems,
15274
- onSelect: (key) => onMenuSelect?.(key)
15275
- }
15276
- ) }) : null
15277
- ]
15278
- }
15279
- ),
15280
- /* @__PURE__ */ (0, import_jsx_runtime191.jsx)("div", { className: "@container h-full min-w-0 flex-1", children: content !== void 0 ? renderSlot(content) : open || activePanelItem ? /* @__PURE__ */ (0, import_jsx_runtime191.jsxs)(PanelGroup, { orientation: "horizontal", style: { width: "100%", height: "100%" }, children: [
15281
- /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(Panel, { defaultSize: "62%", children: chatArea }),
15282
- /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(ResizableHandle, { withHandle: true }),
15283
- /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(Panel, { defaultSize: "38%", minSize: "380px", maxSize: "760px", children: activePanelItem ? /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(
15284
- "div",
15285
- {
15286
- "data-slot": "chat-page-rail-panel",
15287
- className: "flex h-full min-w-0 flex-col border-l border-border bg-muted",
15288
- children: renderSlot(activePanelItem.content)
15289
- }
15290
- ) : artifactPanel })
15291
- ] }) : chatArea })
15292
- ]
15293
- }
15294
- );
15295
- }
15296
-
15297
- // src/components/chat/Citation/index.tsx
15298
- var import_jsx_runtime192 = require("react/jsx-runtime");
15299
- function Citation({ items = [], start = 1, className, style }) {
15300
- return /* @__PURE__ */ (0, import_jsx_runtime192.jsx)("span", { "data-slot": "citation", className: cn("inline-flex gap-1 align-super", className), style, children: items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime192.jsxs)(HoverCard, { children: [
15301
- /* @__PURE__ */ (0, import_jsx_runtime192.jsxs)(
15302
- HoverCardTrigger,
15303
- {
15304
- "data-slot": "citation-marker",
15305
- className: "cursor-pointer rounded-sm border border-border px-1 text-xs leading-4 text-primary hover:bg-accent",
15306
- children: [
15307
- "[",
15308
- start + index,
15309
- "]"
15310
- ]
15311
- }
15312
- ),
15313
- /* @__PURE__ */ (0, import_jsx_runtime192.jsxs)(HoverCardContent, { "data-slot": "citation-card", className: "w-72", children: [
15314
- /* @__PURE__ */ (0, import_jsx_runtime192.jsx)("div", { className: "text-sm font-medium", children: item.title }),
15315
- item.snippet ? /* @__PURE__ */ (0, import_jsx_runtime192.jsx)("div", { className: "mt-1 line-clamp-3 text-xs text-muted-foreground", children: item.snippet }) : null,
15316
- item.url ? /* @__PURE__ */ (0, import_jsx_runtime192.jsx)(
15317
- "a",
15318
- {
15319
- href: item.url,
15320
- target: "_blank",
15321
- rel: "noreferrer",
15322
- className: "mt-1 block truncate text-xs text-primary hover:underline",
15323
- children: item.url
15324
- }
15325
- ) : null
15326
- ] })
15327
- ] }, `${item.title}-${index}`)) });
15328
- }
15329
-
15330
- // src/components/chat/StepsPanel/index.tsx
15331
- var import_jsx_runtime193 = require("react/jsx-runtime");
15332
- function StepsPanel({
15333
- title = "\u6267\u884C\u6B65\u9AA4",
15334
- steps = [],
15335
- emptyText = "\u5F53\u524D\u4F1A\u8BDD\u6682\u65E0\u6267\u884C\u6B65\u9AA4",
15336
- className,
15337
- style
15338
- }) {
15339
- return /* @__PURE__ */ (0, import_jsx_runtime193.jsxs)(
15340
- "div",
15341
- {
15342
- "data-slot": "steps-panel",
15343
- className: cn("px-3.5 py-3 text-foreground", className),
15344
- style,
15345
- children: [
15346
- /* @__PURE__ */ (0, import_jsx_runtime193.jsx)("div", { className: "mb-1 text-[13px] font-semibold", children: title }),
15347
- steps.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime193.jsx)("div", { className: "py-4 text-center text-[13px] text-muted-foreground", children: emptyText }) : /* @__PURE__ */ (0, import_jsx_runtime193.jsx)("ol", { children: steps.map((step, index) => {
15348
- const status = step.status ?? "pending";
15349
- return /* @__PURE__ */ (0, import_jsx_runtime193.jsxs)(
15350
- "li",
15351
- {
15352
- "data-status": status,
15353
- className: cn(
15354
- "relative flex gap-2 py-1.5",
15355
- // 步骤之间的连接线(对齐 16px 图标中心)
15356
- 'not-last:before:absolute not-last:before:left-[7.5px] not-last:before:top-7 not-last:before:-bottom-1 not-last:before:w-px not-last:before:bg-border not-last:before:content-[""]'
15357
- ),
15358
- children: [
15359
- /* @__PURE__ */ (0, import_jsx_runtime193.jsx)(
15360
- "span",
15361
- {
15362
- className: cn(
15363
- "flex h-5 w-4 shrink-0 items-center justify-center",
15364
- status !== "pending" && "text-primary"
15365
- ),
15366
- children: status === "done" ? /* @__PURE__ */ (0, import_jsx_runtime193.jsx)(Icon, { name: "check-circle", size: 16 }) : status === "running" ? /* @__PURE__ */ (0, import_jsx_runtime193.jsx)(
15367
- Icon,
15368
- {
15369
- name: "loading",
15370
- size: 16,
15371
- className: "animate-spin motion-reduce:animate-none"
15372
- }
15373
- ) : /* @__PURE__ */ (0, import_jsx_runtime193.jsx)("span", { className: "size-1.5 rounded-full bg-muted-foreground/50" })
15374
- }
15375
- ),
15376
- /* @__PURE__ */ (0, import_jsx_runtime193.jsxs)("div", { className: "min-w-0 flex-1", children: [
15377
- /* @__PURE__ */ (0, import_jsx_runtime193.jsx)(
15378
- "div",
15379
- {
15380
- className: cn(
15381
- "text-[13px] leading-5",
15382
- status === "pending" && "text-muted-foreground"
15383
- ),
15384
- children: step.title
15385
- }
15386
- ),
15387
- step.description ? /* @__PURE__ */ (0, import_jsx_runtime193.jsx)("div", { className: "mt-0.5 text-xs leading-[18px] text-muted-foreground", children: step.description }) : null
15388
- ] }),
15389
- step.duration ? /* @__PURE__ */ (0, import_jsx_runtime193.jsx)("span", { className: "shrink-0 text-xs leading-5 text-muted-foreground", children: step.duration }) : null
15390
- ]
15391
- },
15392
- `${step.title}-${index}`
15393
- );
15394
- }) })
15395
- ]
15396
- }
15397
- );
15398
- }
15399
-
15400
- // src/components/chat/Suggestion/index.tsx
15401
- var import_jsx_runtime194 = require("react/jsx-runtime");
15402
- function normalize(item) {
15403
- if (typeof item === "string") return { label: item, value: item };
15404
- return { label: item.label, value: item.value ?? item.label, icon: item.icon };
15405
- }
15406
- function Suggestion({ items = [], justify = "start", onSelect, className, style }) {
15407
- return /* @__PURE__ */ (0, import_jsx_runtime194.jsx)(
15408
- "div",
15409
- {
15410
- "data-slot": "suggestion",
15411
- className: cn("flex flex-wrap gap-2", justify === "center" && "justify-center", className),
15412
- style,
15413
- children: items.map((item, index) => {
15414
- const { label, value, icon } = normalize(item);
15415
- return /* @__PURE__ */ (0, import_jsx_runtime194.jsxs)(
15416
- "button",
15417
- {
15418
- type: "button",
15419
- "data-slot": "suggestion-item",
15420
- "data-value": value,
15421
- className: "flex items-center gap-1.5 rounded-full border border-border px-3 py-1 text-sm transition-colors hover:bg-accent",
15422
- onClick: () => onSelect?.(value),
15423
- children: [
15424
- icon ? /* @__PURE__ */ (0, import_jsx_runtime194.jsx)(Icon, { name: icon, size: "sm" }) : null,
15425
- label
15426
- ]
15427
- },
15428
- `${value}-${index}`
15429
- );
15430
- })
15431
- }
15432
- );
15433
- }
15434
-
15435
- // src/components/register.ts
15436
- var builtinComponents = {
15437
- Page,
15438
- Grid,
15439
- Row,
15440
- Col,
15441
- // 循环渲染:行模板(原始 DSL children)由 For 逐项渲染并注入 { row, rowIndex } 作用域
15442
- For: { component: For, withScope: true },
15443
- Flex,
15444
- Card: Card2,
15445
- Button: Button2,
15446
- Alert: Alert2,
15447
- Statistic,
15448
- Tabs: Tabs2,
15449
- Table: Table3,
15450
- Form,
15451
- Input: Input2,
15452
- NumberInput,
15453
- Select: Select2,
15454
- // Layout 需要原始 DSL 子树做方向推导(含 Sider 判定),以 withScope 注册
15455
- Layout: { component: Layout, withScope: true },
15456
- Header,
15457
- Sider,
15458
- Content,
15459
- Footer,
15460
- Menu: Menu2,
15461
- Link: Link2,
15462
- Text,
15463
- // 展示类扩展组件
15464
- Badge: Badge2,
15465
- Avatar: Avatar2,
15466
- Skeleton: Skeleton2,
15467
- Separator: Separator2,
15468
- Kbd: Kbd2,
15469
- Spinner: Spinner2,
15470
- Empty: Empty2,
15471
- AspectRatio: AspectRatio2,
15472
- Progress: Progress2,
15473
- // 表单类扩展组件
15474
- Textarea: Textarea2,
15475
- Checkbox: Checkbox2,
15476
- ChipFilter,
15477
- ChipNode,
15478
- RadioGroup: RadioGroup2,
15479
- Switch: Switch2,
15480
- Slider: Slider2,
15481
- Label: Label2,
15482
- Field: Field2,
15483
- ChatInput,
15484
- // 导航类扩展组件
15485
- Breadcrumb: Breadcrumb2,
15486
- Pagination: Pagination2,
15487
- Menubar: Menubar2,
15488
- NavigationMenu: NavigationMenu2,
15489
- DropdownMenu: DropdownMenu2,
15490
- ContextMenu: ContextMenu2,
15491
- // 反馈与弹层类扩展组件
15492
- Dialog: Dialog2,
15493
- AlertDialog: AlertDialog2,
15494
- Drawer: Drawer2,
15495
- Sheet: Sheet2,
15496
- Popover: Popover2,
15497
- Sonner,
15498
- Accordion: Accordion2,
15499
- Collapsible: Collapsible2,
15500
- Tooltip: Tooltip2,
15501
- HoverCard: HoverCard2,
15502
- // 复合类扩展组件(第三批)
15503
- Calendar: Calendar3,
15504
- DatePicker,
15505
- InputOTP: InputOTP2,
15506
- Combobox: Combobox2,
15507
- Carousel: Carousel2,
15508
- Command: Command2,
15509
- Resizable,
15510
- ScrollArea: ScrollArea2,
15511
- Toggle: Toggle2,
15512
- ToggleGroup: ToggleGroup2,
15513
- ButtonGroup: ButtonGroup2,
15514
- InputGroup: InputGroup2,
15515
- Item: Item2,
15516
- Typography: Typography2,
15517
- // 页面级组合类扩展组件(第四批)
15518
- Sidebar,
15519
- DataTable,
15520
- // 图标(lucide 白名单)
15521
- Icon,
15522
- // 业务刚需类扩展组件(第五批:数据录入 / 数据展示 / 反馈)
15523
- Rate,
15524
- TimePicker,
15525
- ColorPicker,
15526
- Upload: Upload2,
15527
- TreeSelect,
15528
- Cascader,
15529
- Transfer,
15530
- Mentions,
15531
- List: List2,
15532
- Tree,
15533
- Descriptions,
15534
- Timeline,
15535
- Image: Image2,
15536
- QRCode,
15537
- Segmented,
15538
- Message,
15539
- Notification,
15540
- Popconfirm,
15541
- Result,
15542
- LoadingOverlay,
15543
- Watermark,
15544
- Tour,
15545
- // 基础补齐类扩展组件(第六批:通用 / 布局 / 导航)
15546
- Tag: Tag2,
15547
- Status,
15548
- Space,
15549
- Container,
15550
- Steps,
15551
- Anchor,
15552
- BackTop,
15553
- Affix,
15554
- // 媒体与内容类扩展组件(第七批)
15555
- ImageViewer,
15556
- Gallery,
15557
- Video: Video2,
15558
- Audio,
15559
- FilePreview,
15560
- DocumentPreview,
15561
- RichText,
15562
- Markdown: import_markdown2.MarkdownDslComponent,
15563
- CodeBlock,
15564
- DiffViewer,
15565
- JSONViewer,
15566
- // AI 与会话类扩展组件(第八批:chat 子目录)
15567
- Bubble: Bubble2,
15568
- Sender,
15569
- Thinking,
15570
- AgentStatus,
15571
- StreamingText,
15572
- Suggestion,
15573
- Prompt,
15574
- Welcome,
15575
- Citation,
15576
- Attachment,
15577
- ToolCall,
15578
- ChatMessage,
15579
- ChatPage,
15580
- ArtifactPanel,
15581
- MessageList,
15582
- Composer,
15583
- ConversationList,
15584
- StepsPanel
15585
- };
15586
- function registerBuiltinComponents(registry) {
15587
- for (const [type, component] of Object.entries(builtinComponents)) {
15588
- registry.register(type, component);
15589
- }
15590
- }
15591
- function createComponentRegistry() {
15592
- const registry = new import_core3.Registry("ComponentRegistry");
15593
- registerBuiltinComponents(registry);
15594
- return registry;
15595
- }
15596
-
15597
- // src/layout/admin/menu-chain.ts
15598
- function findMenuChain(registry, menuId) {
15599
- const walk = (menus, ancestors) => {
15600
- for (const menu of menus) {
15601
- const chain = [...ancestors, menu];
15602
- if (menu.id === menuId) {
15603
- return chain;
15604
- }
15605
- if (menu.children !== void 0) {
15606
- const hit = walk(menu.children, chain);
15607
- if (hit !== null) {
15608
- return hit;
15609
- }
15610
- }
15611
- }
15612
- return null;
15613
- };
15614
- return walk(registry.tree(), []) ?? [];
15615
- }
15616
-
15617
- // src/layout/admin/menu-items.ts
15618
- function collectDefaultOpenKeys(registry, activeMenuId) {
15619
- const keys = [];
15620
- const walk = (menus) => {
15621
- for (const menu of menus) {
15622
- if (menu.type === "group" && menu.defaultOpen === true) {
15623
- keys.push(menu.id);
15624
- }
15625
- if (menu.children !== void 0) {
15626
- walk(menu.children);
15627
- }
15628
- }
15629
- };
15630
- walk(registry.tree());
15631
- if (activeMenuId !== void 0) {
15632
- for (const menu of findMenuChain(registry, activeMenuId)) {
15633
- if (menu.type === "group" && !keys.includes(menu.id)) {
15634
- keys.push(menu.id);
15635
- }
15636
- }
15637
- }
15638
- return keys;
15639
- }
15640
-
15641
- // src/layout/admin/AdminLayout.tsx
15642
- var import_permission = require("@pactor-app/permission");
15643
- var import_router = require("@pactor-app/router");
15644
- var import_runtime52 = require("@pactor-app/runtime");
15645
- var import_react72 = require("react");
15646
-
15647
- // src/layout/admin/use-media-query.ts
15648
- var import_react71 = require("react");
15649
- var BREAKPOINT_PX = {
15650
- xs: 480,
15651
- sm: 576,
15652
- md: 768,
15653
- lg: 992,
15654
- xl: 1200,
15655
- xxl: 1600
15656
- };
15657
- function useMediaQuery(query) {
15658
- const [matches, setMatches] = (0, import_react71.useState)(
15659
- () => typeof window !== "undefined" && typeof window.matchMedia === "function" ? window.matchMedia(query).matches : false
15660
- );
15661
- (0, import_react71.useEffect)(() => {
13194
+ (0, import_react61.useEffect)(() => {
15662
13195
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
15663
13196
  return;
15664
13197
  }
@@ -15678,7 +13211,7 @@ function useBreakpointBelow(breakpoint) {
15678
13211
  }
15679
13212
 
15680
13213
  // src/layout/admin/AdminLayout.tsx
15681
- var import_jsx_runtime195 = require("react/jsx-runtime");
13214
+ var import_jsx_runtime174 = require("react/jsx-runtime");
15682
13215
  function buildVisibleMenuTree(registry, permissionChecker) {
15683
13216
  const tree = registry.tree();
15684
13217
  return permissionChecker === void 0 ? [...tree] : (0, import_permission.filterMenusByPermission)(tree, permissionChecker);
@@ -15701,8 +13234,8 @@ function CollapsedGroupFlyout({
15701
13234
  activeMenuId,
15702
13235
  defaultOpenKeys
15703
13236
  }) {
15704
- const [open, setOpen] = (0, import_react72.useState)(false);
15705
- const closeTimer = (0, import_react72.useRef)(void 0);
13237
+ const [open, setOpen] = (0, import_react62.useState)(false);
13238
+ const closeTimer = (0, import_react62.useRef)(void 0);
15706
13239
  const openNow = () => {
15707
13240
  window.clearTimeout(closeTimer.current);
15708
13241
  setOpen(true);
@@ -15711,12 +13244,12 @@ function CollapsedGroupFlyout({
15711
13244
  window.clearTimeout(closeTimer.current);
15712
13245
  closeTimer.current = window.setTimeout(() => setOpen(false), 200);
15713
13246
  };
15714
- (0, import_react72.useEffect)(() => () => window.clearTimeout(closeTimer.current), []);
15715
- return /* @__PURE__ */ (0, import_jsx_runtime195.jsxs)(Popover, { open, onOpenChange: setOpen, children: [
15716
- /* @__PURE__ */ (0, import_jsx_runtime195.jsx)(
13247
+ (0, import_react62.useEffect)(() => () => window.clearTimeout(closeTimer.current), []);
13248
+ return /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)(Popover, { open, onOpenChange: setOpen, children: [
13249
+ /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
15717
13250
  PopoverTrigger,
15718
13251
  {
15719
- render: /* @__PURE__ */ (0, import_jsx_runtime195.jsx)(
13252
+ render: /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
15720
13253
  "button",
15721
13254
  {
15722
13255
  type: "button",
@@ -15734,7 +13267,7 @@ function CollapsedGroupFlyout({
15734
13267
  )
15735
13268
  }
15736
13269
  ),
15737
- /* @__PURE__ */ (0, import_jsx_runtime195.jsxs)(
13270
+ /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)(
15738
13271
  PopoverContent,
15739
13272
  {
15740
13273
  "data-slot": "menu-flyout",
@@ -15751,8 +13284,8 @@ function CollapsedGroupFlyout({
15751
13284
  }
15752
13285
  },
15753
13286
  children: [
15754
- /* @__PURE__ */ (0, import_jsx_runtime195.jsx)("div", { className: "px-3 pt-2 pb-1 text-xs font-semibold text-muted-foreground", children: menu.title }),
15755
- /* @__PURE__ */ (0, import_jsx_runtime195.jsx)(
13287
+ /* @__PURE__ */ (0, import_jsx_runtime174.jsx)("div", { className: "px-3 pt-2 pb-1 text-xs font-semibold text-muted-foreground", children: menu.title }),
13288
+ /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
15756
13289
  MenuTree,
15757
13290
  {
15758
13291
  menus: menu.children ?? [],
@@ -15776,9 +13309,9 @@ function MenuTree({
15776
13309
  collapsed = false
15777
13310
  }) {
15778
13311
  if (collapsed) {
15779
- return /* @__PURE__ */ (0, import_jsx_runtime195.jsx)("div", { "data-slot": "menu", "data-collapsed": "true", className: "flex flex-col gap-1", children: menus.map((menu) => {
13312
+ return /* @__PURE__ */ (0, import_jsx_runtime174.jsx)("div", { "data-slot": "menu", "data-collapsed": "true", className: "flex flex-col gap-1", children: menus.map((menu) => {
15780
13313
  if (menu.type === "group") {
15781
- return /* @__PURE__ */ (0, import_jsx_runtime195.jsx)(
13314
+ return /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
15782
13315
  CollapsedGroupFlyout,
15783
13316
  {
15784
13317
  menu,
@@ -15790,7 +13323,7 @@ function MenuTree({
15790
13323
  menu.id
15791
13324
  );
15792
13325
  }
15793
- return /* @__PURE__ */ (0, import_jsx_runtime195.jsx)(
13326
+ return /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
15794
13327
  "button",
15795
13328
  {
15796
13329
  type: "button",
@@ -15810,7 +13343,7 @@ function MenuTree({
15810
13343
  );
15811
13344
  }) });
15812
13345
  }
15813
- return /* @__PURE__ */ (0, import_jsx_runtime195.jsx)(
13346
+ return /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
15814
13347
  Accordion,
15815
13348
  {
15816
13349
  type: "multiple",
@@ -15819,27 +13352,27 @@ function MenuTree({
15819
13352
  className: "flex flex-col gap-0.5 px-2",
15820
13353
  children: menus.map((menu) => {
15821
13354
  if (menu.type === "group") {
15822
- return /* @__PURE__ */ (0, import_jsx_runtime195.jsxs)(
13355
+ return /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)(
15823
13356
  AccordionItem,
15824
13357
  {
15825
13358
  value: menu.id,
15826
13359
  "data-slot": "menu-group",
15827
13360
  className: "border-b-0",
15828
13361
  children: [
15829
- /* @__PURE__ */ (0, import_jsx_runtime195.jsx)(
13362
+ /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
15830
13363
  AccordionTrigger,
15831
13364
  {
15832
13365
  "data-slot": "menu-group-trigger",
15833
13366
  className: cn(menuItemClass2, "py-2 font-medium"),
15834
13367
  disabled: menu.disabled,
15835
13368
  title: menu.title,
15836
- children: /* @__PURE__ */ (0, import_jsx_runtime195.jsxs)("span", { className: "inline-flex items-center gap-2", children: [
15837
- menu.icon ? /* @__PURE__ */ (0, import_jsx_runtime195.jsx)(Icon, { name: menu.icon, size: "sm" }) : null,
13369
+ children: /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)("span", { className: "inline-flex items-center gap-2", children: [
13370
+ menu.icon ? /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(Icon, { name: menu.icon, size: "sm" }) : null,
15838
13371
  menu.title
15839
13372
  ] })
15840
13373
  }
15841
13374
  ),
15842
- /* @__PURE__ */ (0, import_jsx_runtime195.jsx)(AccordionContent, { "data-slot": "menu-group-content", className: "pb-1", children: /* @__PURE__ */ (0, import_jsx_runtime195.jsx)("div", { className: "flex flex-col gap-0.5 pl-3", children: /* @__PURE__ */ (0, import_jsx_runtime195.jsx)(
13375
+ /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(AccordionContent, { "data-slot": "menu-group-content", className: "pb-1", children: /* @__PURE__ */ (0, import_jsx_runtime174.jsx)("div", { className: "flex flex-col gap-0.5 pl-3", children: /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
15843
13376
  MenuTree,
15844
13377
  {
15845
13378
  menus: menu.children ?? [],
@@ -15854,7 +13387,7 @@ function MenuTree({
15854
13387
  menu.id
15855
13388
  );
15856
13389
  }
15857
- return /* @__PURE__ */ (0, import_jsx_runtime195.jsxs)(
13390
+ return /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)(
15858
13391
  "button",
15859
13392
  {
15860
13393
  type: "button",
@@ -15868,7 +13401,7 @@ function MenuTree({
15868
13401
  title: menu.title,
15869
13402
  onClick: () => navigateMenuItem(registry.findById(menu.id), bridge),
15870
13403
  children: [
15871
- menu.icon ? /* @__PURE__ */ (0, import_jsx_runtime195.jsx)(Icon, { name: menu.icon, size: "sm" }) : null,
13404
+ menu.icon ? /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(Icon, { name: menu.icon, size: "sm" }) : null,
15872
13405
  menu.title
15873
13406
  ]
15874
13407
  },
@@ -15888,23 +13421,23 @@ function AdminLayout({
15888
13421
  headerExtra,
15889
13422
  children
15890
13423
  }) {
15891
- const { t } = (0, import_runtime52.useI18n)();
13424
+ const { t } = (0, import_runtime50.useI18n)();
15892
13425
  const mode = config.mode ?? "top-side";
15893
13426
  const showHeader = config.header ?? true;
15894
13427
  const showSidebar = (config.sidebar ?? true) && mode !== "top-bottom";
15895
13428
  const showTabs = config.tabs ?? false;
15896
13429
  const showBreadcrumb = config.breadcrumb ?? false;
15897
13430
  const showFooter = config.footer ?? false;
15898
- const [collapsed, setCollapsed] = (0, import_react72.useState)(config.collapsed ?? false);
13431
+ const [collapsed, setCollapsed] = (0, import_react62.useState)(config.collapsed ?? false);
15899
13432
  const broken = useBreakpointBelow(config.breakpoint);
15900
13433
  const effectiveCollapsed = collapsed || broken;
15901
- const [bridgeRoute, setBridgeRoute] = (0, import_react72.useState)(
13434
+ const [bridgeRoute, setBridgeRoute] = (0, import_react62.useState)(
15902
13435
  () => (0, import_router.resolveRoute)(registry, bridge.getLocation())
15903
13436
  );
15904
- const [tabs, setTabs] = (0, import_react72.useState)([]);
15905
- const tabsRef = (0, import_react72.useRef)(tabs);
13437
+ const [tabs, setTabs] = (0, import_react62.useState)([]);
13438
+ const tabsRef = (0, import_react62.useRef)(tabs);
15906
13439
  tabsRef.current = tabs;
15907
- (0, import_react72.useEffect)(() => {
13440
+ (0, import_react62.useEffect)(() => {
15908
13441
  const handleLocation = (location) => {
15909
13442
  const next = (0, import_router.resolveRoute)(registry, location);
15910
13443
  setBridgeRoute(next);
@@ -15925,16 +13458,16 @@ function AdminLayout({
15925
13458
  }, [registry, bridge]);
15926
13459
  const route = routeProp ?? bridgeRoute;
15927
13460
  const activeMenuId = route?.activeMenu;
15928
- const visibleMenus = (0, import_react72.useMemo)(
13461
+ const visibleMenus = (0, import_react62.useMemo)(
15929
13462
  () => buildVisibleMenuTree(registry, permissionChecker),
15930
13463
  [registry, permissionChecker]
15931
13464
  );
15932
- const defaultOpenKeysRef = (0, import_react72.useRef)(null);
13465
+ const defaultOpenKeysRef = (0, import_react62.useRef)(null);
15933
13466
  if (defaultOpenKeysRef.current === null) {
15934
13467
  defaultOpenKeysRef.current = collectDefaultOpenKeys(registry, activeMenuId);
15935
13468
  }
15936
13469
  const defaultOpenKeys = defaultOpenKeysRef.current;
15937
- const activeTopId = (0, import_react72.useMemo)(() => {
13470
+ const activeTopId = (0, import_react62.useMemo)(() => {
15938
13471
  if (activeMenuId !== void 0) {
15939
13472
  const chain = findMenuChain(registry, activeMenuId);
15940
13473
  if (chain.length > 0) {
@@ -15943,11 +13476,11 @@ function AdminLayout({
15943
13476
  }
15944
13477
  return void 0;
15945
13478
  }, [registry, activeMenuId]);
15946
- const [selectedTopId, setSelectedTopId] = (0, import_react72.useState)();
13479
+ const [selectedTopId, setSelectedTopId] = (0, import_react62.useState)();
15947
13480
  const secondaryTopId = selectedTopId ?? activeTopId ?? visibleMenus.find((m) => m.type === "group")?.id ?? visibleMenus[0]?.id;
15948
13481
  const secondaryTop = visibleMenus.find((m) => m.id === secondaryTopId);
15949
13482
  const hasSecondary = (secondaryTop?.children?.length ?? 0) > 0;
15950
- const breadcrumbItems = (0, import_react72.useMemo)(() => {
13483
+ const breadcrumbItems = (0, import_react62.useMemo)(() => {
15951
13484
  if (!showBreadcrumb || activeMenuId === void 0) {
15952
13485
  return [];
15953
13486
  }
@@ -15963,7 +13496,7 @@ function AdminLayout({
15963
13496
  };
15964
13497
  const fixedHeader = config.fixedHeader ?? true;
15965
13498
  const fixedSider = config.fixedSider ?? true;
15966
- const header = showHeader ? /* @__PURE__ */ (0, import_jsx_runtime195.jsxs)(
13499
+ const header = showHeader ? /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)(
15967
13500
  "header",
15968
13501
  {
15969
13502
  "data-slot": "admin-header",
@@ -15972,21 +13505,21 @@ function AdminLayout({
15972
13505
  fixedHeader && "sticky top-0 z-20"
15973
13506
  ),
15974
13507
  children: [
15975
- mode !== "side-full" && /* @__PURE__ */ (0, import_jsx_runtime195.jsxs)(import_jsx_runtime195.Fragment, { children: [
13508
+ mode !== "side-full" && /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)(import_jsx_runtime174.Fragment, { children: [
15976
13509
  brand.logo,
15977
- /* @__PURE__ */ (0, import_jsx_runtime195.jsx)("span", { "data-slot": "admin-brand", className: "text-lg font-semibold", children: brand.title })
13510
+ /* @__PURE__ */ (0, import_jsx_runtime174.jsx)("span", { "data-slot": "admin-brand", className: "text-lg font-semibold", children: brand.title })
15978
13511
  ] }),
15979
- /* @__PURE__ */ (0, import_jsx_runtime195.jsx)("div", { className: "flex-1" }),
13512
+ /* @__PURE__ */ (0, import_jsx_runtime174.jsx)("div", { className: "flex-1" }),
15980
13513
  headerExtra
15981
13514
  ]
15982
13515
  }
15983
13516
  ) : null;
15984
- const primaryColumn = /* @__PURE__ */ (0, import_jsx_runtime195.jsx)(
13517
+ const primaryColumn = /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
15985
13518
  "div",
15986
13519
  {
15987
13520
  "data-slot": "admin-primary-col",
15988
13521
  className: "flex w-12 shrink-0 flex-col items-center gap-1 border-r border-border py-2",
15989
- children: visibleMenus.map((menu) => /* @__PURE__ */ (0, import_jsx_runtime195.jsx)(
13522
+ children: visibleMenus.map((menu) => /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
15990
13523
  "button",
15991
13524
  {
15992
13525
  type: "button",
@@ -16013,7 +13546,7 @@ function AdminLayout({
16013
13546
  }
16014
13547
  );
16015
13548
  const showTrigger = config.collapsible && mode !== "two-column";
16016
- const sidebar = showSidebar ? /* @__PURE__ */ (0, import_jsx_runtime195.jsxs)(
13549
+ const sidebar = showSidebar ? /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)(
16017
13550
  "aside",
16018
13551
  {
16019
13552
  "data-slot": "admin-sidebar",
@@ -16025,20 +13558,20 @@ function AdminLayout({
16025
13558
  ),
16026
13559
  style: mode === "two-column" && !hasSecondary ? { width: 56 } : void 0,
16027
13560
  children: [
16028
- mode === "side-full" && /* @__PURE__ */ (0, import_jsx_runtime195.jsxs)(
13561
+ mode === "side-full" && /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)(
16029
13562
  "div",
16030
13563
  {
16031
13564
  "data-slot": "admin-sidebar-brand",
16032
13565
  className: "flex items-center gap-2 border-b border-border px-4 py-4 font-semibold",
16033
13566
  children: [
16034
13567
  brand.logo,
16035
- /* @__PURE__ */ (0, import_jsx_runtime195.jsx)("span", { children: brand.title })
13568
+ /* @__PURE__ */ (0, import_jsx_runtime174.jsx)("span", { children: brand.title })
16036
13569
  ]
16037
13570
  }
16038
13571
  ),
16039
- mode === "two-column" ? /* @__PURE__ */ (0, import_jsx_runtime195.jsxs)("div", { "data-slot": "admin-two-col", className: "flex h-full", children: [
13572
+ mode === "two-column" ? /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)("div", { "data-slot": "admin-two-col", className: "flex h-full", children: [
16040
13573
  primaryColumn,
16041
- hasSecondary && /* @__PURE__ */ (0, import_jsx_runtime195.jsx)("div", { "data-slot": "admin-secondary-col", className: "min-w-0 flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime195.jsx)(
13574
+ hasSecondary && /* @__PURE__ */ (0, import_jsx_runtime174.jsx)("div", { "data-slot": "admin-secondary-col", className: "min-w-0 flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
16042
13575
  MenuTree,
16043
13576
  {
16044
13577
  menus: secondaryTop?.children ?? [],
@@ -16048,7 +13581,7 @@ function AdminLayout({
16048
13581
  defaultOpenKeys
16049
13582
  }
16050
13583
  ) })
16051
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime195.jsx)(
13584
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
16052
13585
  MenuTree,
16053
13586
  {
16054
13587
  menus: visibleMenus,
@@ -16059,7 +13592,7 @@ function AdminLayout({
16059
13592
  collapsed: effectiveCollapsed
16060
13593
  }
16061
13594
  ),
16062
- showTrigger && /* @__PURE__ */ (0, import_jsx_runtime195.jsx)(
13595
+ showTrigger && /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
16063
13596
  "button",
16064
13597
  {
16065
13598
  type: "button",
@@ -16074,14 +13607,14 @@ function AdminLayout({
16074
13607
  ]
16075
13608
  }
16076
13609
  ) : null;
16077
- const body = /* @__PURE__ */ (0, import_jsx_runtime195.jsxs)("div", { "data-slot": "admin-body", className: "flex min-w-0 flex-1 flex-col", children: [
16078
- showTabs && /* @__PURE__ */ (0, import_jsx_runtime195.jsx)(
13610
+ const body = /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)("div", { "data-slot": "admin-body", className: "flex min-w-0 flex-1 flex-col", children: [
13611
+ showTabs && /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
16079
13612
  "div",
16080
13613
  {
16081
13614
  "data-slot": "admin-tabs",
16082
13615
  role: "tablist",
16083
13616
  className: "flex items-center gap-1 border-b border-border bg-card px-4 pt-2",
16084
- children: tabs.map((tab, index) => /* @__PURE__ */ (0, import_jsx_runtime195.jsxs)(
13617
+ children: tabs.map((tab, index) => /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)(
16085
13618
  "div",
16086
13619
  {
16087
13620
  "data-slot": "admin-tab",
@@ -16092,7 +13625,7 @@ function AdminLayout({
16092
13625
  tab.key === currentPath ? "bg-card font-medium text-foreground" : "bg-muted text-muted-foreground"
16093
13626
  ),
16094
13627
  children: [
16095
- /* @__PURE__ */ (0, import_jsx_runtime195.jsx)(
13628
+ /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
16096
13629
  "button",
16097
13630
  {
16098
13631
  type: "button",
@@ -16103,7 +13636,7 @@ function AdminLayout({
16103
13636
  children: tab.title
16104
13637
  }
16105
13638
  ),
16106
- index > 0 && /* @__PURE__ */ (0, import_jsx_runtime195.jsx)(
13639
+ index > 0 && /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
16107
13640
  "button",
16108
13641
  {
16109
13642
  type: "button",
@@ -16120,21 +13653,21 @@ function AdminLayout({
16120
13653
  ))
16121
13654
  }
16122
13655
  ),
16123
- /* @__PURE__ */ (0, import_jsx_runtime195.jsxs)(
13656
+ /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)(
16124
13657
  "main",
16125
13658
  {
16126
13659
  "data-slot": "admin-content",
16127
13660
  className: "flex-1 bg-muted/40 p-6",
16128
13661
  children: [
16129
- showBreadcrumb && breadcrumbItems.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime195.jsx)(
13662
+ showBreadcrumb && breadcrumbItems.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
16130
13663
  "nav",
16131
13664
  {
16132
13665
  "data-slot": "admin-breadcrumb",
16133
13666
  "aria-label": t("pactor.layout.breadcrumb"),
16134
13667
  className: "mb-4",
16135
- children: /* @__PURE__ */ (0, import_jsx_runtime195.jsx)("ol", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: breadcrumbItems.map((title, index) => /* @__PURE__ */ (0, import_jsx_runtime195.jsxs)("li", { className: "flex items-center gap-2", children: [
16136
- index > 0 && /* @__PURE__ */ (0, import_jsx_runtime195.jsx)("span", { "aria-hidden": true, children: "/" }),
16137
- /* @__PURE__ */ (0, import_jsx_runtime195.jsx)("span", { "data-slot": "breadcrumb-link", children: title })
13668
+ children: /* @__PURE__ */ (0, import_jsx_runtime174.jsx)("ol", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: breadcrumbItems.map((title, index) => /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)("li", { className: "flex items-center gap-2", children: [
13669
+ index > 0 && /* @__PURE__ */ (0, import_jsx_runtime174.jsx)("span", { "aria-hidden": true, children: "/" }),
13670
+ /* @__PURE__ */ (0, import_jsx_runtime174.jsx)("span", { "data-slot": "breadcrumb-link", children: title })
16138
13671
  ] }, index)) })
16139
13672
  }
16140
13673
  ),
@@ -16143,7 +13676,7 @@ function AdminLayout({
16143
13676
  }
16144
13677
  )
16145
13678
  ] });
16146
- const footer = showFooter ? /* @__PURE__ */ (0, import_jsx_runtime195.jsx)(
13679
+ const footer = showFooter ? /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
16147
13680
  "footer",
16148
13681
  {
16149
13682
  "data-slot": "admin-footer",
@@ -16151,7 +13684,7 @@ function AdminLayout({
16151
13684
  children: brand.title
16152
13685
  }
16153
13686
  ) : null;
16154
- return /* @__PURE__ */ (0, import_jsx_runtime195.jsx)(
13687
+ return /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
16155
13688
  "div",
16156
13689
  {
16157
13690
  "data-slot": "admin-layout",
@@ -16159,9 +13692,9 @@ function AdminLayout({
16159
13692
  "data-fixed-header": fixedHeader || void 0,
16160
13693
  "data-fixed-sider": fixedSider || void 0,
16161
13694
  className: "flex min-h-screen flex-col bg-background text-foreground",
16162
- children: mode === "side-full" ? /* @__PURE__ */ (0, import_jsx_runtime195.jsxs)("div", { "data-slot": "admin-side-full", className: "flex min-h-screen flex-1", children: [
13695
+ children: mode === "side-full" ? /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)("div", { "data-slot": "admin-side-full", className: "flex min-h-screen flex-1", children: [
16163
13696
  sidebar,
16164
- /* @__PURE__ */ (0, import_jsx_runtime195.jsxs)(
13697
+ /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)(
16165
13698
  "div",
16166
13699
  {
16167
13700
  "data-slot": "admin-side-full-main",
@@ -16173,9 +13706,9 @@ function AdminLayout({
16173
13706
  ]
16174
13707
  }
16175
13708
  )
16176
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime195.jsxs)(import_jsx_runtime195.Fragment, { children: [
13709
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)(import_jsx_runtime174.Fragment, { children: [
16177
13710
  header,
16178
- /* @__PURE__ */ (0, import_jsx_runtime195.jsxs)("div", { "data-slot": "admin-main", className: "flex min-h-0 flex-1", children: [
13711
+ /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)("div", { "data-slot": "admin-main", className: "flex min-h-0 flex-1", children: [
16179
13712
  sidebar,
16180
13713
  body
16181
13714
  ] }),
@@ -16186,9 +13719,9 @@ function AdminLayout({
16186
13719
  }
16187
13720
 
16188
13721
  // src/layout/basic/BlankLayout.tsx
16189
- var import_jsx_runtime196 = require("react/jsx-runtime");
13722
+ var import_jsx_runtime175 = require("react/jsx-runtime");
16190
13723
  function BlankLayout({ children }) {
16191
- return /* @__PURE__ */ (0, import_jsx_runtime196.jsx)(
13724
+ return /* @__PURE__ */ (0, import_jsx_runtime175.jsx)(
16192
13725
  "div",
16193
13726
  {
16194
13727
  "data-slot": "blank-layout",
@@ -16200,8 +13733,8 @@ function BlankLayout({ children }) {
16200
13733
 
16201
13734
  // src/layout/chat/ChatLayout.tsx
16202
13735
  var import_permission2 = require("@pactor-app/permission");
16203
- var import_react73 = require("react");
16204
- var import_jsx_runtime197 = require("react/jsx-runtime");
13736
+ var import_react63 = require("react");
13737
+ var import_jsx_runtime176 = require("react/jsx-runtime");
16205
13738
  function ChatLayout({
16206
13739
  brand,
16207
13740
  menu,
@@ -16216,7 +13749,7 @@ function ChatLayout({
16216
13749
  sidebarFooter,
16217
13750
  children
16218
13751
  }) {
16219
- const registryMenus = (0, import_react73.useMemo)(() => {
13752
+ const registryMenus = (0, import_react63.useMemo)(() => {
16220
13753
  if (menu !== void 0 || registry === void 0) {
16221
13754
  return [];
16222
13755
  }
@@ -16225,10 +13758,10 @@ function ChatLayout({
16225
13758
  return visible.flatMap((item) => menuItemToMenuData(item));
16226
13759
  }, [menu, registry, permissionChecker]);
16227
13760
  const menuItems = menu ?? registryMenus;
16228
- const [bridgePath, setBridgePath] = (0, import_react73.useState)(
13761
+ const [bridgePath, setBridgePath] = (0, import_react63.useState)(
16229
13762
  () => bridge?.getLocation().pathname ?? "/"
16230
13763
  );
16231
- (0, import_react73.useEffect)(() => {
13764
+ (0, import_react63.useEffect)(() => {
16232
13765
  if (bridge === void 0) {
16233
13766
  return;
16234
13767
  }
@@ -16236,7 +13769,7 @@ function ChatLayout({
16236
13769
  setBridgePath(location.pathname);
16237
13770
  });
16238
13771
  }, [bridge]);
16239
- const activeKey = (0, import_react73.useMemo)(() => {
13772
+ const activeKey = (0, import_react63.useMemo)(() => {
16240
13773
  if (activeMenuKey !== void 0) {
16241
13774
  return activeMenuKey;
16242
13775
  }
@@ -16256,7 +13789,7 @@ function ChatLayout({
16256
13789
  bridge.push(item.path);
16257
13790
  }
16258
13791
  };
16259
- const sidebarContent = sidebar !== void 0 && sidebar !== null ? sidebar : menuItems.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime197.jsx)(
13792
+ const sidebarContent = sidebar !== void 0 && sidebar !== null ? sidebar : menuItems.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(
16260
13793
  Menu2,
16261
13794
  {
16262
13795
  items: menuItems.map((item) => chatMenuItemToUiMenuItem(item)),
@@ -16264,7 +13797,7 @@ function ChatLayout({
16264
13797
  onSelect: handleSelect
16265
13798
  }
16266
13799
  ) : void 0;
16267
- return /* @__PURE__ */ (0, import_jsx_runtime197.jsx)(
13800
+ return /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(
16268
13801
  Sidebar,
16269
13802
  {
16270
13803
  brand,
@@ -16272,7 +13805,7 @@ function ChatLayout({
16272
13805
  sidebarFooter,
16273
13806
  collapsible,
16274
13807
  locationKey: routeProp?.path ?? bridgePath,
16275
- children: /* @__PURE__ */ (0, import_jsx_runtime197.jsx)(
13808
+ children: /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(
16276
13809
  "div",
16277
13810
  {
16278
13811
  "data-slot": "chat-layout-content",
@@ -16326,26 +13859,26 @@ function menuItemToMenuData(item) {
16326
13859
  }
16327
13860
 
16328
13861
  // src/layout/basic/LoginLayout.tsx
16329
- var import_jsx_runtime198 = require("react/jsx-runtime");
13862
+ var import_jsx_runtime177 = require("react/jsx-runtime");
16330
13863
  function LoginLayout({
16331
13864
  variant = "center",
16332
13865
  brand,
16333
13866
  children
16334
13867
  }) {
16335
- const brandBlock = /* @__PURE__ */ (0, import_jsx_runtime198.jsxs)("div", { "data-slot": "login-brand", className: "flex flex-col items-center gap-2", children: [
13868
+ const brandBlock = /* @__PURE__ */ (0, import_jsx_runtime177.jsxs)("div", { "data-slot": "login-brand", className: "flex flex-col items-center gap-2", children: [
16336
13869
  brand.logo,
16337
- /* @__PURE__ */ (0, import_jsx_runtime198.jsx)("h1", { className: "text-xl font-semibold", children: brand.title }),
16338
- brand.description !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime198.jsx)("div", { className: "text-sm text-muted-foreground", children: brand.description })
13870
+ /* @__PURE__ */ (0, import_jsx_runtime177.jsx)("h1", { className: "text-xl font-semibold", children: brand.title }),
13871
+ brand.description !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime177.jsx)("div", { className: "text-sm text-muted-foreground", children: brand.description })
16339
13872
  ] });
16340
13873
  if (variant === "split") {
16341
- return /* @__PURE__ */ (0, import_jsx_runtime198.jsxs)(
13874
+ return /* @__PURE__ */ (0, import_jsx_runtime177.jsxs)(
16342
13875
  "div",
16343
13876
  {
16344
13877
  "data-slot": "login-layout",
16345
13878
  "data-variant": "split",
16346
13879
  className: "grid min-h-screen grid-cols-2 bg-background text-foreground",
16347
13880
  children: [
16348
- /* @__PURE__ */ (0, import_jsx_runtime198.jsx)(
13881
+ /* @__PURE__ */ (0, import_jsx_runtime177.jsx)(
16349
13882
  "div",
16350
13883
  {
16351
13884
  "data-slot": "login-brand-panel",
@@ -16353,7 +13886,7 @@ function LoginLayout({
16353
13886
  children: brandBlock
16354
13887
  }
16355
13888
  ),
16356
- /* @__PURE__ */ (0, import_jsx_runtime198.jsx)(
13889
+ /* @__PURE__ */ (0, import_jsx_runtime177.jsx)(
16357
13890
  "div",
16358
13891
  {
16359
13892
  "data-slot": "login-form-panel",
@@ -16365,37 +13898,37 @@ function LoginLayout({
16365
13898
  }
16366
13899
  );
16367
13900
  }
16368
- return /* @__PURE__ */ (0, import_jsx_runtime198.jsx)(
13901
+ return /* @__PURE__ */ (0, import_jsx_runtime177.jsx)(
16369
13902
  "div",
16370
13903
  {
16371
13904
  "data-slot": "login-layout",
16372
13905
  "data-variant": "center",
16373
13906
  className: "flex min-h-screen items-center justify-center bg-muted/40 text-foreground",
16374
- children: /* @__PURE__ */ (0, import_jsx_runtime198.jsxs)(Card, { "data-slot": "login-card", className: "w-full max-w-sm gap-4 py-6", children: [
16375
- /* @__PURE__ */ (0, import_jsx_runtime198.jsxs)(CardHeader, { className: "px-6", children: [
16376
- /* @__PURE__ */ (0, import_jsx_runtime198.jsx)(CardTitle, { className: "sr-only", children: brand.title }),
13907
+ children: /* @__PURE__ */ (0, import_jsx_runtime177.jsxs)(Card, { "data-slot": "login-card", className: "w-full max-w-sm gap-4 py-6", children: [
13908
+ /* @__PURE__ */ (0, import_jsx_runtime177.jsxs)(CardHeader, { className: "px-6", children: [
13909
+ /* @__PURE__ */ (0, import_jsx_runtime177.jsx)(CardTitle, { className: "sr-only", children: brand.title }),
16377
13910
  brandBlock
16378
13911
  ] }),
16379
- /* @__PURE__ */ (0, import_jsx_runtime198.jsx)(CardContent, { className: "flex flex-col gap-4 px-6", children })
13912
+ /* @__PURE__ */ (0, import_jsx_runtime177.jsx)(CardContent, { className: "flex flex-col gap-4 px-6", children })
16380
13913
  ] })
16381
13914
  }
16382
13915
  );
16383
13916
  }
16384
13917
 
16385
13918
  // src/layout/basic/LandingLayout.tsx
16386
- var import_jsx_runtime199 = require("react/jsx-runtime");
13919
+ var import_jsx_runtime178 = require("react/jsx-runtime");
16387
13920
  function LandingLayout({
16388
13921
  navbar,
16389
13922
  footer,
16390
13923
  children
16391
13924
  }) {
16392
- return /* @__PURE__ */ (0, import_jsx_runtime199.jsxs)(
13925
+ return /* @__PURE__ */ (0, import_jsx_runtime178.jsxs)(
16393
13926
  "div",
16394
13927
  {
16395
13928
  "data-slot": "landing-layout",
16396
13929
  className: "flex min-h-screen flex-col bg-background text-foreground",
16397
13930
  children: [
16398
- navbar !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime199.jsx)(
13931
+ navbar !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime178.jsx)(
16399
13932
  "header",
16400
13933
  {
16401
13934
  "data-slot": "landing-navbar",
@@ -16403,8 +13936,8 @@ function LandingLayout({
16403
13936
  children: navbar
16404
13937
  }
16405
13938
  ),
16406
- /* @__PURE__ */ (0, import_jsx_runtime199.jsx)("main", { "data-slot": "landing-content", className: "flex-1", children }),
16407
- footer !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime199.jsx)(
13939
+ /* @__PURE__ */ (0, import_jsx_runtime178.jsx)("main", { "data-slot": "landing-content", className: "flex-1", children }),
13940
+ footer !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime178.jsx)(
16408
13941
  "footer",
16409
13942
  {
16410
13943
  "data-slot": "landing-footer",
@@ -16418,7 +13951,7 @@ function LandingLayout({
16418
13951
  }
16419
13952
 
16420
13953
  // src/layout/registry.ts
16421
- var import_core4 = require("@pactor-app/core");
13954
+ var import_core3 = require("@pactor-app/core");
16422
13955
  function registerBuiltinLayouts(registry) {
16423
13956
  registry.register("admin", AdminLayout);
16424
13957
  registry.register("blank", BlankLayout);
@@ -16427,7 +13960,7 @@ function registerBuiltinLayouts(registry) {
16427
13960
  registry.register("chat", ChatLayout);
16428
13961
  }
16429
13962
  function createLayoutRegistry() {
16430
- const registry = new import_core4.Registry("LayoutRegistry");
13963
+ const registry = new import_core3.Registry("LayoutRegistry");
16431
13964
  registerBuiltinLayouts(registry);
16432
13965
  return registry;
16433
13966
  }
@@ -16531,7 +14064,7 @@ var OverlayManager = class {
16531
14064
  };
16532
14065
 
16533
14066
  // src/interaction/actions.ts
16534
- var import_runtime53 = require("@pactor-app/runtime");
14067
+ var import_runtime51 = require("@pactor-app/runtime");
16535
14068
  function createUiBridge() {
16536
14069
  return {};
16537
14070
  }
@@ -16547,7 +14080,7 @@ function registerInteractionActions(actions, manager, ui) {
16547
14080
  return failure("[pactor-interaction] overlay.open \u7F3A\u5C11 overlay \u914D\u7F6E\u53C2\u6570");
16548
14081
  }
16549
14082
  const { content, ...rest } = overlay;
16550
- const resolved = (0, import_runtime53.resolveDeep)(rest, ctx.scope);
14083
+ const resolved = (0, import_runtime51.resolveDeep)(rest, ctx.scope);
16551
14084
  const config = { ...resolved, content };
16552
14085
  const data = await manager.open(config, {
16553
14086
  parentScope: { ...ctx.scope }
@@ -16610,10 +14143,10 @@ function isRecord(value) {
16610
14143
  }
16611
14144
 
16612
14145
  // src/interaction/provider.tsx
16613
- var import_runtime54 = require("@pactor-app/runtime");
16614
- var import_react74 = require("react");
14146
+ var import_runtime52 = require("@pactor-app/runtime");
14147
+ var import_react64 = require("react");
16615
14148
  var import_react_dom2 = require("react-dom");
16616
- var import_jsx_runtime200 = require("react/jsx-runtime");
14149
+ var import_jsx_runtime179 = require("react/jsx-runtime");
16617
14150
  var TOAST_DURATION = 3e3;
16618
14151
  var toastTypeClass = {
16619
14152
  success: "border-l-4 border-l-success",
@@ -16625,11 +14158,11 @@ function InteractionProvider({
16625
14158
  bridge,
16626
14159
  children
16627
14160
  }) {
16628
- const [confirmState, setConfirmState] = (0, import_react74.useState)(null);
16629
- const [confirmOpen, setConfirmOpen] = (0, import_react74.useState)(false);
16630
- const [toasts, setToasts] = (0, import_react74.useState)([]);
16631
- const { t } = (0, import_runtime54.useI18n)();
16632
- const { modal, message } = (0, import_react74.useMemo)(() => {
14161
+ const [confirmState, setConfirmState] = (0, import_react64.useState)(null);
14162
+ const [confirmOpen, setConfirmOpen] = (0, import_react64.useState)(false);
14163
+ const [toasts, setToasts] = (0, import_react64.useState)([]);
14164
+ const { t } = (0, import_runtime52.useI18n)();
14165
+ const { modal, message } = (0, import_react64.useMemo)(() => {
16633
14166
  const pushToast = (type, content) => {
16634
14167
  const id = Date.now() + Math.random();
16635
14168
  setToasts((prev) => [...prev, { id, type, content }]);
@@ -16651,7 +14184,7 @@ function InteractionProvider({
16651
14184
  };
16652
14185
  return { modal: modalImpl, message: messageImpl };
16653
14186
  }, []);
16654
- (0, import_react74.useEffect)(() => {
14187
+ (0, import_react64.useEffect)(() => {
16655
14188
  bridge.modal = modal;
16656
14189
  bridge.message = message;
16657
14190
  return () => {
@@ -16669,11 +14202,11 @@ function InteractionProvider({
16669
14202
  setConfirmOpen(false);
16670
14203
  state?.onCancel?.();
16671
14204
  };
16672
- return /* @__PURE__ */ (0, import_jsx_runtime200.jsxs)(import_jsx_runtime200.Fragment, { children: [
14205
+ return /* @__PURE__ */ (0, import_jsx_runtime179.jsxs)(import_jsx_runtime179.Fragment, { children: [
16673
14206
  children,
16674
14207
  typeof document !== "undefined" && (0, import_react_dom2.createPortal)(
16675
- /* @__PURE__ */ (0, import_jsx_runtime200.jsxs)(import_jsx_runtime200.Fragment, { children: [
16676
- /* @__PURE__ */ (0, import_jsx_runtime200.jsx)(
14208
+ /* @__PURE__ */ (0, import_jsx_runtime179.jsxs)(import_jsx_runtime179.Fragment, { children: [
14209
+ /* @__PURE__ */ (0, import_jsx_runtime179.jsx)(
16677
14210
  Dialog,
16678
14211
  {
16679
14212
  open: confirmOpen,
@@ -16687,29 +14220,29 @@ function InteractionProvider({
16687
14220
  setConfirmState(null);
16688
14221
  }
16689
14222
  },
16690
- children: /* @__PURE__ */ (0, import_jsx_runtime200.jsxs)(DialogContent, { "data-slot": "confirm-dialog", className: "sm:max-w-sm", children: [
16691
- /* @__PURE__ */ (0, import_jsx_runtime200.jsxs)(DialogHeader, { children: [
16692
- /* @__PURE__ */ (0, import_jsx_runtime200.jsx)(DialogTitle, { children: confirmState?.title ?? "" }),
16693
- confirmState?.content !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime200.jsx)(
14223
+ children: /* @__PURE__ */ (0, import_jsx_runtime179.jsxs)(DialogContent, { "data-slot": "confirm-dialog", className: "sm:max-w-sm", children: [
14224
+ /* @__PURE__ */ (0, import_jsx_runtime179.jsxs)(DialogHeader, { children: [
14225
+ /* @__PURE__ */ (0, import_jsx_runtime179.jsx)(DialogTitle, { children: confirmState?.title ?? "" }),
14226
+ confirmState?.content !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime179.jsx)(
16694
14227
  DialogDescription,
16695
14228
  {
16696
- render: /* @__PURE__ */ (0, import_jsx_runtime200.jsx)("div", { children: confirmState.content })
14229
+ render: /* @__PURE__ */ (0, import_jsx_runtime179.jsx)("div", { children: confirmState.content })
16697
14230
  }
16698
14231
  )
16699
14232
  ] }),
16700
- /* @__PURE__ */ (0, import_jsx_runtime200.jsxs)(DialogFooter, { children: [
16701
- /* @__PURE__ */ (0, import_jsx_runtime200.jsx)(Button, { type: "button", variant: "outline", onClick: handleCancel, children: t("pactor.alertDialog.cancel") }),
16702
- /* @__PURE__ */ (0, import_jsx_runtime200.jsx)(Button, { type: "button", onClick: handleOk, children: t("pactor.alertDialog.confirm") })
14233
+ /* @__PURE__ */ (0, import_jsx_runtime179.jsxs)(DialogFooter, { children: [
14234
+ /* @__PURE__ */ (0, import_jsx_runtime179.jsx)(Button, { type: "button", variant: "outline", onClick: handleCancel, children: t("pactor.alertDialog.cancel") }),
14235
+ /* @__PURE__ */ (0, import_jsx_runtime179.jsx)(Button, { type: "button", onClick: handleOk, children: t("pactor.alertDialog.confirm") })
16703
14236
  ] })
16704
14237
  ] })
16705
14238
  }
16706
14239
  ),
16707
- toasts.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime200.jsx)(
14240
+ toasts.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime179.jsx)(
16708
14241
  "div",
16709
14242
  {
16710
14243
  "data-slot": "toast-container",
16711
14244
  className: "fixed top-4 right-4 z-[100] flex w-80 flex-col gap-2",
16712
- children: toasts.map((toast2) => /* @__PURE__ */ (0, import_jsx_runtime200.jsx)(
14245
+ children: toasts.map((toast2) => /* @__PURE__ */ (0, import_jsx_runtime179.jsx)(
16713
14246
  "div",
16714
14247
  {
16715
14248
  "data-slot": "toast",
@@ -16733,9 +14266,9 @@ function InteractionProvider({
16733
14266
 
16734
14267
  // src/interaction/host.tsx
16735
14268
  var import_lucide_react40 = require("lucide-react");
16736
- var import_runtime55 = require("@pactor-app/runtime");
16737
- var import_react75 = require("react");
16738
- var import_jsx_runtime201 = require("react/jsx-runtime");
14269
+ var import_runtime53 = require("@pactor-app/runtime");
14270
+ var import_react65 = require("react");
14271
+ var import_jsx_runtime180 = require("react/jsx-runtime");
16739
14272
  function toCssWidth(width) {
16740
14273
  if (width === void 0) {
16741
14274
  return void 0;
@@ -16743,12 +14276,12 @@ function toCssWidth(width) {
16743
14276
  return typeof width === "number" ? `${width}px` : width;
16744
14277
  }
16745
14278
  function OverlayHost({ manager, resolvePage }) {
16746
- const renderer = (0, import_runtime55.useRenderer)();
16747
- const stack = (0, import_react75.useSyncExternalStore)(
14279
+ const renderer = (0, import_runtime53.useRenderer)();
14280
+ const stack = (0, import_react65.useSyncExternalStore)(
16748
14281
  (onChange) => manager.subscribe(onChange),
16749
14282
  () => manager.stack()
16750
14283
  );
16751
- (0, import_react75.useSyncExternalStore)(
14284
+ (0, import_react65.useSyncExternalStore)(
16752
14285
  (onChange) => {
16753
14286
  const offState = renderer.context.state.subscribe(onChange);
16754
14287
  const offData = renderer.context.data.subscribe(onChange);
@@ -16759,7 +14292,7 @@ function OverlayHost({ manager, resolvePage }) {
16759
14292
  },
16760
14293
  () => `${renderer.context.state.getVersion()}:${renderer.context.data.getVersion()}`
16761
14294
  );
16762
- return /* @__PURE__ */ (0, import_jsx_runtime201.jsx)(import_jsx_runtime201.Fragment, { children: stack.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime201.jsx)(
14295
+ return /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(import_jsx_runtime180.Fragment, { children: stack.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(
16763
14296
  OverlayEntryView,
16764
14297
  {
16765
14298
  entry,
@@ -16776,7 +14309,7 @@ function OverlayEntryView({
16776
14309
  renderer,
16777
14310
  resolvePage
16778
14311
  }) {
16779
- const { t } = (0, import_runtime55.useI18n)();
14312
+ const { t } = (0, import_runtime53.useI18n)();
16780
14313
  const handleCancel = () => manager.close(entry.id);
16781
14314
  let body = null;
16782
14315
  if (entry.content) {
@@ -16785,7 +14318,7 @@ function OverlayEntryView({
16785
14318
  parent: manager.parentScopeOf(entry.id)
16786
14319
  });
16787
14320
  } else if (entry.page) {
16788
- body = /* @__PURE__ */ (0, import_jsx_runtime201.jsx)(
14321
+ body = /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(
16789
14322
  PageOverlayBody,
16790
14323
  {
16791
14324
  entry,
@@ -16795,9 +14328,9 @@ function OverlayEntryView({
16795
14328
  );
16796
14329
  }
16797
14330
  if (entry.type === "drawer") {
16798
- return /* @__PURE__ */ (0, import_jsx_runtime201.jsx)(ShadcnDrawerView, { entry, onCancel: handleCancel, children: body });
14331
+ return /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(ShadcnDrawerView, { entry, onCancel: handleCancel, children: body });
16799
14332
  }
16800
- return /* @__PURE__ */ (0, import_jsx_runtime201.jsx)(
14333
+ return /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(
16801
14334
  Dialog,
16802
14335
  {
16803
14336
  open: true,
@@ -16806,7 +14339,7 @@ function OverlayEntryView({
16806
14339
  handleCancel();
16807
14340
  }
16808
14341
  },
16809
- children: /* @__PURE__ */ (0, import_jsx_runtime201.jsxs)(
14342
+ children: /* @__PURE__ */ (0, import_jsx_runtime180.jsxs)(
16810
14343
  DialogContent,
16811
14344
  {
16812
14345
  "data-slot": "overlay-modal",
@@ -16814,25 +14347,25 @@ function OverlayEntryView({
16814
14347
  style: entry.width === void 0 ? void 0 : { width: toCssWidth(entry.width) },
16815
14348
  showCloseButton: false,
16816
14349
  children: [
16817
- /* @__PURE__ */ (0, import_jsx_runtime201.jsxs)(DialogHeader, { children: [
16818
- /* @__PURE__ */ (0, import_jsx_runtime201.jsx)(DialogTitle, { children: entry.title ?? "" }),
16819
- /* @__PURE__ */ (0, import_jsx_runtime201.jsx)(
14350
+ /* @__PURE__ */ (0, import_jsx_runtime180.jsxs)(DialogHeader, { children: [
14351
+ /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(DialogTitle, { children: entry.title ?? "" }),
14352
+ /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(
16820
14353
  DialogClose,
16821
14354
  {
16822
- render: /* @__PURE__ */ (0, import_jsx_runtime201.jsx)(
14355
+ render: /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(
16823
14356
  "button",
16824
14357
  {
16825
14358
  type: "button",
16826
14359
  "data-slot": "overlay-modal-close",
16827
14360
  "aria-label": t("pactor.overlay.close"),
16828
14361
  className: "absolute top-4 right-4 cursor-pointer rounded-xs opacity-70 transition-opacity hover:opacity-100 focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-none",
16829
- children: /* @__PURE__ */ (0, import_jsx_runtime201.jsx)(import_lucide_react40.XIcon, { className: "size-4" })
14362
+ children: /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(import_lucide_react40.XIcon, { className: "size-4" })
16830
14363
  }
16831
14364
  )
16832
14365
  }
16833
14366
  )
16834
14367
  ] }),
16835
- /* @__PURE__ */ (0, import_jsx_runtime201.jsx)("div", { "data-slot": "overlay-modal-body", children: body })
14368
+ /* @__PURE__ */ (0, import_jsx_runtime180.jsx)("div", { "data-slot": "overlay-modal-body", children: body })
16836
14369
  ]
16837
14370
  }
16838
14371
  )
@@ -16844,9 +14377,9 @@ function ShadcnDrawerView({
16844
14377
  onCancel,
16845
14378
  children
16846
14379
  }) {
16847
- const { t } = (0, import_runtime55.useI18n)();
14380
+ const { t } = (0, import_runtime53.useI18n)();
16848
14381
  const panelStyle = entry.width === void 0 ? void 0 : { width: toCssWidth(entry.width), maxWidth: toCssWidth(entry.width) };
16849
- return /* @__PURE__ */ (0, import_jsx_runtime201.jsx)(
14382
+ return /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(
16850
14383
  Drawer,
16851
14384
  {
16852
14385
  direction: "right",
@@ -16857,7 +14390,7 @@ function ShadcnDrawerView({
16857
14390
  onCancel();
16858
14391
  }
16859
14392
  },
16860
- children: /* @__PURE__ */ (0, import_jsx_runtime201.jsxs)(
14393
+ children: /* @__PURE__ */ (0, import_jsx_runtime180.jsxs)(
16861
14394
  DrawerContent,
16862
14395
  {
16863
14396
  "data-slot": "drawer-panel",
@@ -16865,27 +14398,27 @@ function ShadcnDrawerView({
16865
14398
  style: panelStyle,
16866
14399
  overlayProps: { onPointerDown: onCancel },
16867
14400
  children: [
16868
- /* @__PURE__ */ (0, import_jsx_runtime201.jsxs)(
14401
+ /* @__PURE__ */ (0, import_jsx_runtime180.jsxs)(
16869
14402
  DrawerHeader,
16870
14403
  {
16871
14404
  "data-slot": "drawer-header",
16872
14405
  className: "flex flex-row items-center justify-between border-b border-border px-6 py-4",
16873
14406
  children: [
16874
- /* @__PURE__ */ (0, import_jsx_runtime201.jsx)(DrawerTitle, { className: "text-lg", children: entry.title ?? "" }),
16875
- /* @__PURE__ */ (0, import_jsx_runtime201.jsx)(DrawerClose, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime201.jsx)(
14407
+ /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(DrawerTitle, { className: "text-lg", children: entry.title ?? "" }),
14408
+ /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(DrawerClose, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(
16876
14409
  "button",
16877
14410
  {
16878
14411
  type: "button",
16879
14412
  "data-slot": "drawer-close",
16880
14413
  "aria-label": t("pactor.overlay.close"),
16881
14414
  className: "cursor-pointer rounded-xs opacity-70 transition-opacity hover:opacity-100 focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-none",
16882
- children: /* @__PURE__ */ (0, import_jsx_runtime201.jsx)(import_lucide_react40.XIcon, { className: "size-4" })
14415
+ children: /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(import_lucide_react40.XIcon, { className: "size-4" })
16883
14416
  }
16884
14417
  ) })
16885
14418
  ]
16886
14419
  }
16887
14420
  ),
16888
- /* @__PURE__ */ (0, import_jsx_runtime201.jsx)("div", { "data-slot": "drawer-body", className: "flex-1 overflow-auto p-6", children })
14421
+ /* @__PURE__ */ (0, import_jsx_runtime180.jsx)("div", { "data-slot": "drawer-body", className: "flex-1 overflow-auto p-6", children })
16889
14422
  ]
16890
14423
  }
16891
14424
  )
@@ -16897,9 +14430,9 @@ function PageOverlayBody({
16897
14430
  renderer,
16898
14431
  resolvePage
16899
14432
  }) {
16900
- const [child, setChild] = (0, import_react75.useState)(null);
16901
- const [error, setError] = (0, import_react75.useState)(null);
16902
- (0, import_react75.useEffect)(() => {
14433
+ const [child, setChild] = (0, import_react65.useState)(null);
14434
+ const [error, setError] = (0, import_react65.useState)(null);
14435
+ (0, import_react65.useEffect)(() => {
16903
14436
  if (!resolvePage) {
16904
14437
  setError(
16905
14438
  new Error(
@@ -16917,7 +14450,7 @@ function PageOverlayBody({
16917
14450
  return;
16918
14451
  }
16919
14452
  const host = renderer.context;
16920
- created = (0, import_runtime55.createPageRuntime)(pageDsl, {
14453
+ created = (0, import_runtime53.createPageRuntime)(pageDsl, {
16921
14454
  app: host.app,
16922
14455
  user: host.user,
16923
14456
  components: host.components,
@@ -16941,32 +14474,28 @@ function PageOverlayBody({
16941
14474
  };
16942
14475
  }, [entry.id]);
16943
14476
  if (error) {
16944
- return /* @__PURE__ */ (0, import_jsx_runtime201.jsx)("div", { role: "alert", children: error.message });
14477
+ return /* @__PURE__ */ (0, import_jsx_runtime180.jsx)("div", { role: "alert", children: error.message });
16945
14478
  }
16946
14479
  if (!child) {
16947
14480
  return null;
16948
14481
  }
16949
- return /* @__PURE__ */ (0, import_jsx_runtime201.jsx)(import_runtime55.PageRuntimeView, { runtime: child });
14482
+ return /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(import_runtime53.PageRuntimeView, { runtime: child });
16950
14483
  }
16951
14484
  // Annotate the CommonJS export names for ESM import in node:
16952
14485
  0 && (module.exports = {
16953
14486
  Accordion,
16954
14487
  AdminLayout,
16955
14488
  Affix,
16956
- AgentStatus,
16957
14489
  Alert,
16958
14490
  AlertDialog,
16959
14491
  Anchor,
16960
- ArtifactPanel,
16961
14492
  AspectRatio,
16962
- Attachment,
16963
14493
  Audio,
16964
14494
  Avatar,
16965
14495
  BackTop,
16966
14496
  Badge,
16967
14497
  BlankLayout,
16968
14498
  Breadcrumb,
16969
- Bubble,
16970
14499
  Button,
16971
14500
  ButtonGroup,
16972
14501
  CONTROL_SIZE_AREA,
@@ -16980,12 +14509,9 @@ function PageOverlayBody({
16980
14509
  Cascader,
16981
14510
  ChatInput,
16982
14511
  ChatLayout,
16983
- ChatMessage,
16984
- ChatPage,
16985
14512
  Checkbox,
16986
14513
  ChipFilter,
16987
14514
  ChipNode,
16988
- Citation,
16989
14515
  ClearHoverButton,
16990
14516
  CodeBlock,
16991
14517
  Col,
@@ -16993,11 +14519,9 @@ function PageOverlayBody({
16993
14519
  ColorPicker,
16994
14520
  Combobox,
16995
14521
  Command,
16996
- Composer,
16997
14522
  Container,
16998
14523
  Content,
16999
14524
  ContextMenu,
17000
- ConversationList,
17001
14525
  DataTable,
17002
14526
  DatePicker,
17003
14527
  Descriptions,
@@ -17041,7 +14565,6 @@ function PageOverlayBody({
17041
14565
  Menu,
17042
14566
  Menubar,
17043
14567
  Message,
17044
- MessageList,
17045
14568
  NavigationMenu,
17046
14569
  Notification,
17047
14570
  NumberInput,
@@ -17053,7 +14576,6 @@ function PageOverlayBody({
17053
14576
  Popconfirm,
17054
14577
  Popover,
17055
14578
  Progress,
17056
- Prompt,
17057
14579
  QRCode,
17058
14580
  RadioGroup,
17059
14581
  RailTooltip,
@@ -17065,7 +14587,6 @@ function PageOverlayBody({
17065
14587
  ScrollArea,
17066
14588
  Segmented,
17067
14589
  Select,
17068
- Sender,
17069
14590
  Separator,
17070
14591
  Sheet,
17071
14592
  Sidebar,
@@ -17078,21 +14599,16 @@ function PageOverlayBody({
17078
14599
  Statistic,
17079
14600
  Status,
17080
14601
  Steps,
17081
- StepsPanel,
17082
- StreamingText,
17083
- Suggestion,
17084
14602
  Switch,
17085
14603
  Table,
17086
14604
  Tabs,
17087
14605
  Tag,
17088
14606
  Text,
17089
14607
  Textarea,
17090
- Thinking,
17091
14608
  TimePicker,
17092
14609
  Timeline,
17093
14610
  Toggle,
17094
14611
  ToggleGroup,
17095
- ToolCall,
17096
14612
  Tooltip,
17097
14613
  Tour,
17098
14614
  Transfer,
@@ -17102,8 +14618,6 @@ function PageOverlayBody({
17102
14618
  Upload,
17103
14619
  Video,
17104
14620
  Watermark,
17105
- Welcome,
17106
- buildArtifactTree,
17107
14621
  builtinComponents,
17108
14622
  collectDefaultOpenKeys,
17109
14623
  createComponentRegistry,
@@ -17118,5 +14632,6 @@ function PageOverlayBody({
17118
14632
  registerInteractionActions,
17119
14633
  resolveLayout,
17120
14634
  useFormContext,
14635
+ useOptionalRenderer,
17121
14636
  useSidebarDrawer
17122
14637
  });