weifuwu 0.61.2 → 0.63.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.
Files changed (72) hide show
  1. package/README.md +168 -11
  2. package/dist/client/diff.d.ts +13 -1
  3. package/dist/client/index.js +3 -3
  4. package/dist/client/popup.d.ts +22 -0
  5. package/dist/client/types.d.ts +63 -0
  6. package/dist/client/ui.d.ts +6 -0
  7. package/dist/components/Accordion/Accordion.d.ts +9 -0
  8. package/dist/components/Affix/Affix.d.ts +16 -0
  9. package/dist/components/AspectRatio/AspectRatio.d.ts +10 -0
  10. package/dist/components/AvatarGroup/AvatarGroup.d.ts +21 -0
  11. package/dist/components/BackTop/BackTop.d.ts +16 -0
  12. package/dist/components/Calendar/Calendar.d.ts +21 -0
  13. package/dist/components/Carousel/Carousel.d.ts +17 -0
  14. package/dist/components/Cascader/Cascader.d.ts +21 -0
  15. package/dist/components/CheckboxGroup/CheckboxGroup.d.ts +23 -0
  16. package/dist/components/CodeBlock/CodeBlock.d.ts +14 -0
  17. package/dist/components/Collapse/Collapse.d.ts +28 -0
  18. package/dist/components/ColorPicker/ColorPicker.d.ts +16 -0
  19. package/dist/components/Command/Command.d.ts +22 -0
  20. package/dist/components/ContextMenu/ContextMenu.d.ts +17 -0
  21. package/dist/components/CopyButton/CopyButton.d.ts +18 -0
  22. package/dist/components/Descriptions/Descriptions.d.ts +21 -0
  23. package/dist/components/Highlight/Highlight.d.ts +13 -0
  24. package/dist/components/HoverCard/HoverCard.d.ts +16 -0
  25. package/dist/components/Icon/Icon.d.ts +1 -1
  26. package/dist/components/Img/Img.d.ts +4 -0
  27. package/dist/components/InView/InView.d.ts +1 -1
  28. package/dist/components/InfiniteScroll/InfiniteScroll.d.ts +15 -0
  29. package/dist/components/InputNumber/InputNumber.d.ts +25 -0
  30. package/dist/components/Label/Label.d.ts +11 -0
  31. package/dist/components/List/List.d.ts +18 -0
  32. package/dist/components/Markdown/Markdown.d.ts +14 -0
  33. package/dist/components/Markdown/parser.d.ts +32 -0
  34. package/dist/components/Mentions/Mentions.d.ts +19 -0
  35. package/dist/components/Menu/Menu.d.ts +25 -0
  36. package/dist/components/Menubar/Menubar.d.ts +22 -0
  37. package/dist/components/MessageBubble/MessageBubble.d.ts +20 -0
  38. package/dist/components/Notification/Notification.d.ts +70 -0
  39. package/dist/components/PasswordInput/PasswordInput.d.ts +21 -0
  40. package/dist/components/PinInput/PinInput.d.ts +18 -0
  41. package/dist/components/QRCode/QRCode.d.ts +20 -0
  42. package/dist/components/QRCode/qr.d.ts +15 -0
  43. package/dist/components/Rate/Rate.d.ts +16 -0
  44. package/dist/components/Resizable/Resizable.d.ts +18 -0
  45. package/dist/components/Result/Result.d.ts +17 -0
  46. package/dist/components/Select/Select.d.ts +4 -2
  47. package/dist/components/Table/Table.d.ts +10 -0
  48. package/dist/components/TagsInput/TagsInput.d.ts +21 -0
  49. package/dist/components/Timeline/Timeline.d.ts +25 -0
  50. package/dist/components/ToggleGroup/ToggleGroup.d.ts +33 -0
  51. package/dist/components/Transfer/Transfer.d.ts +18 -0
  52. package/dist/components/Tree/Tree.d.ts +27 -0
  53. package/dist/components/Typography/Typography.d.ts +39 -0
  54. package/dist/components/VirtualList/VirtualList.d.ts +21 -0
  55. package/dist/components/Watermark/Watermark.d.ts +19 -0
  56. package/dist/components/index.d.ts +85 -0
  57. package/dist/components/index.js +14 -1
  58. package/dist/components/style.css +4824 -2211
  59. package/dist/db/postgres/connection.d.ts +24 -3
  60. package/dist/db/postgres/pool.d.ts +30 -8
  61. package/dist/db/redis/client.d.ts +43 -0
  62. package/dist/db/redis/connection.d.ts +12 -0
  63. package/dist/db/redis/pipeline.d.ts +26 -0
  64. package/dist/db/redis/pool.d.ts +27 -2
  65. package/dist/index.d.ts +1 -0
  66. package/dist/index.js +1055 -94
  67. package/dist/layout/weifuwu-layout.css +11 -1
  68. package/dist/postgres/types.d.ts +2 -1
  69. package/dist/redis/types.d.ts +6 -0
  70. package/dist/scheduler/cron.d.ts +26 -0
  71. package/dist/scheduler/index.d.ts +69 -0
  72. package/package.json +2 -4
package/README.md CHANGED
@@ -10,7 +10,7 @@ npm install weifuwu
10
10
 
11
11
  > ⚠️ **注意:前后端都有 `ctx.ui`,但用途完全不同**
12
12
  > - **后端** `ctx.ui`(SSR/编译):`ctx.ui.html`(HTML 模板)、`ctx.ui.js`(TSX→JS 动态编译)、`ctx.ui.css`(CSS 编译)、`ctx.ui.ssr`(组件 SSR)、`ctx.ui.ssrData`(数据序列化)
13
- > - **前端** `ctx.ui`(渲染引擎):`ctx.ui.$()`(响应式状态)、`ctx.ui.render()` / `dirty()`(渲染控制)、`useMedia()` / `useBreakpoint()` / `usePopupPosition()`(浏览器事件监听)
13
+ > - **前端** `ctx.ui`(渲染引擎):`ctx.ui.$()`(响应式状态)、`ctx.ui.render()` / `dirty()`(渲染控制)、`useMedia()` / `useBreakpoint()` / `usePopupPosition()` / `useInView()` / `useScrollPosition()`(浏览器事件监听)
14
14
  > 后端的是「把页面和代码交给浏览器」,前端的是「在浏览器里驱动 UI」。
15
15
 
16
16
  ---
@@ -62,7 +62,7 @@ npm install weifuwu
62
62
 
63
63
  **自研数据层** — `ctx.sql`(PG v3 协议)与 `ctx.redis`(RESP2 协议)为**自研客户端**:确定性输出、行为可预测、统一错误模型。jsonb 自动解码、TTL 安全 API、schema 写前校验——高频痛点(双重编码/parseRow 样板/`'EX'` 参数顺序)从根上消除。
64
64
 
65
- > **实践验证**:多租户 AI 平台(`apps/agent-platform`——14 页 + 部门聊天 + 知识库 + HITL 审批)已完全运行在框架上:auth(userSystem)/ AI 引擎(ai)/ 实时消息(messager)/ UI(48 组件)/ 数据管道(ctx.api)零自研替代。框架哲学(中间件注入、诚实裁剪、机制与策略分离)经受住了真实复杂应用的检验——这也是我们确定「哪些进框架、哪些留应用层」的依据。
65
+ > **实践验证**:多租户 AI 平台(`apps/agent-platform`——14 页 + 部门聊天 + 知识库 + HITL 审批)已完全运行在框架上:auth(userSystem)/ AI 引擎(ai)/ 实时消息(messager)/ UI(61 组件)/ 数据管道(ctx.api)零自研替代。框架哲学(中间件注入、诚实裁剪、机制与策略分离)经受住了真实复杂应用的检验——这也是我们确定「哪些进框架、哪些留应用层」的依据。
66
66
 
67
67
  ---
68
68
 
@@ -164,7 +164,7 @@ createApp().use(router({ routes })).mount('#root', RouteView, { hydrate: true })
164
164
 
165
165
  - 访问页面:SPA 客户端渲染;SSR 页面内容直接进 HTML(`curl /` 可见,SEO)
166
166
  - 改组件刷新即生效,无需构建步骤
167
- - 完整可运行示例见 `apps/demo`(博客页 = SSR + Hydration,SPA 页 = 纯客户端)
167
+ - 完整可运行示例见 `apps/components-demo`(组件 cheatsheet)与 `apps/agent-platform`(全栈 SaaS 应用)
168
168
 
169
169
  > 想**零后端、零构建**最快跑起来?直接跳到下面的「CDN 快速原型」。
170
170
 
@@ -235,14 +235,14 @@ createApp().use(router({ routes })).mount('#root', RouteView, { hydrate: true })
235
235
  </html>
236
236
  ```
237
237
 
238
- 将此 HTML 保存到本地用浏览器打开即可运行。完整的 CDN 示例见 [`apps/html/test.html`](./apps/html/test.html)。
238
+ 将此 HTML 保存到本地用浏览器打开即可运行。
239
239
 
240
240
  ### CDN 资源地址说明
241
241
 
242
242
  | 资源 | CDN 地址 | 说明 |
243
243
  |------|---------|------|
244
244
  | `weifuwu/client` | `https://unpkg.com/weifuwu@latest/dist/client/index.js` | 客户端核心(createApp, h, 路由, 状态管理等) |
245
- | `weifuwu/components` | `https://unpkg.com/weifuwu@latest/dist/components/index.js` | 48 个 UI 组件(Button, Card, Table, Modal, Icon 等) |
245
+ | `weifuwu/components` | `https://unpkg.com/weifuwu@latest/dist/components/index.js` | 91 个 UI 组件(Button, Card, Table, Modal, Icon 等) |
246
246
  | `weifuwu/components` | `https://unpkg.com/weifuwu@latest/dist/components/style.css` | 组件 CSS + 141 个主题 Token + 67 个布局原语 |
247
247
  | 独立布局系统 | `https://unpkg.com/weifuwu@latest/dist/layout/weifuwu-layout.css` | 仅 CSS 布局,不依赖 JS |
248
248
 
@@ -266,6 +266,7 @@ createApp().use(router({ routes })).mount('#root', RouteView, { hydrate: true })
266
266
  | `weifuwu` | **userSystem** | 用户系统(scrypt 密码哈希 + 混合会话 + 多租户感知)→ `ctx.user` / `ctx.auth` / `ctx.tenantId` + `/api/auth/*` | Router, postgres |
267
267
  | `weifuwu` | **messager** | 消息系统(会话/消息持久化 + WS 实时投递 + Redis 跨进程广播)→ `ctx.msg` + `/api/messages/*` | Router, postgres, (redis) |
268
268
  | `weifuwu` | **queue** | 可靠任务队列(Redis Streams,at-least-once + DLQ)→ `ctx.queue` | Router, redis |
269
+ | `weifuwu` | **scheduler** | 计划任务(延时 `ctx.schedule` + cron `ctx.cron`/`ctx.cancelCron`,触发后入队) | Router, redis, queue |
269
270
  | `weifuwu` | **ai** | LLM 对话(自研 OpenAI 兼容协议 + 自研 SSE 解码,默认 DeepSeek)→ `ctx.ai` + embedding + `ctx.ui.useChat` + `AiChat` | Router |
270
271
  | `weifuwu/dev` | **dev loader** | Node loader:服务端直接跑 `.ts/.tsx`(`--import weifuwu/dev`) | esbuild |
271
272
  | `weifuwu` | **graphql** | GraphQL 端点(支持 GraphiQL) | Router |
@@ -282,7 +283,7 @@ createApp().use(router({ routes })).mount('#root', RouteView, { hydrate: true })
282
283
  | `weifuwu/client` | **ErrorBoundary** | 错误边界组件 | createApp |
283
284
  | `weifuwu/client` | **lockScroll/trapFocus** | 滚动锁定 / 焦点陷阱工具 | — |
284
285
  | `weifuwu/client` | **popup** | 弹层 fixed 定位工具(`computeFixedPos` / `computeFixedPosRect`) | — |
285
- | `weifuwu/components` | **48 个组件** | Button/Table/Modal/Confirm/Toast/... + `confirm()` / `toast()` 命令式中间件 | weifuwu/client |
286
+ | `weifuwu/components` | **91 个组件** | Button/Table/Modal/Confirm/Toast/... + `confirm()` / `toast()` 命令式中间件 | weifuwu/client |
286
287
  | `weifuwu/layout` | **CSS 布局** | 67 个布局原语 + 141 个主题 Token(也支持 `weifuwu/layout/style.css`) | — |
287
288
 
288
289
  ---
@@ -669,7 +670,9 @@ app.post('/transfer', async (req, ctx) => {
669
670
  | **int8(超出安全范围)** | **`string`**(防静默丢精度,金额/ID 关键) |
670
671
  | float / numeric | `number` |
671
672
  | boolean | `boolean` |
672
- | text / varchar / uuid / date | `string` |
673
+ | text / varchar / uuid | `string` |
674
+ | **timestamptz** | **`Date`**(带时区,ISO 解析无本地时区魔法) |
675
+ | timestamp / date / interval | `string`(无时区语义——转 Date 按本地时区解析即时区魔法,诚实裁剪不转) |
673
676
  | NULL | `null` |
674
677
 
675
678
  ### 类型层(查询泛型 + schema 写前校验)
@@ -699,9 +702,28 @@ await ctx.sql.insert('decks', { title: 'x', status: 'INVALID' }) // → Validati
699
702
  | `ctx.sql.transaction(fn)` | 事务(回调收到 `{ query }`) |
700
703
  | `ctx.sql.register(table, schema)` | 注册表结构(写前校验) |
701
704
  | `ctx.sql.insert(table, row)` | schema 校验 + 参数化插入 |
705
+ | `ctx.sql.insertMany(table, rows[], { batchSize? })` | **批量插入**:多行 VALUES 单次往返(默认 500/批;所有行键必须一致) |
706
+ | `ctx.sql.update(table, set, where, { returning? })` | **参数化 UPDATE**:SET/WHERE 全部参数化,返回 `affectedRows` |
707
+ | `ctx.sql.delete(table, where)` | **参数化 DELETE**:WHERE 必填(防全表误删),返回 `affectedRows` |
702
708
  | `ctx.sql\`...\` 内嵌片段` | 条件 SQL 片段(嵌套过滤,参数自动重编号) |
703
709
  | `ctx.sql.close()` | 关闭连接池 |
704
710
 
711
+ ### 影响行数(affectedRows)
712
+
713
+ `INSERT / UPDATE / DELETE / MERGE` 的返回行数组带**非枚举** `affectedRows` 属性(不干扰 `deepEqual`/`JSON.stringify`):
714
+
715
+ ```ts
716
+ const r = await ctx.sql`UPDATE messages SET read = true WHERE id = ${id}`
717
+ if (r.affectedRows === 0) return new Response('not found', { status: 404 })
718
+ ```
719
+
720
+ ```ts
721
+ // 批量插入:100 行 1 次往返
722
+ await ctx.sql.insertMany('agent_logs', logs, { batchSize: 500 })
723
+ // 语义化更新/删除:WHERE 全参数化 + 返回影响行数
724
+ await ctx.sql.update('users', { role: 'admin' }, { id: userId })
725
+ await ctx.sql.delete('messages', { id: msgId })
726
+
705
727
  ### 条件片段(嵌套过滤)
706
728
 
707
729
  ```ts
@@ -721,7 +743,8 @@ const rows = await ctx.sql`
721
743
  | `max`(或 `poolSize`) | `number` | `10` | 连接池大小 |
722
744
  | `acquireTimeoutMs` | `number` | `30000` | 池全忙时 acquire 超时(防饿死,0=无限) |
723
745
  | `statementTimeoutMs`(或 `statementTimeout`) | `number` | `0` | 语句超时(慢查询保护,0=禁用) |
724
- | `onQuery` | `(sql, durationMs, rowCount) => void` | | 查询观测钩子(慢查询日志/审计) |
746
+ | `idleTimeoutMs` | `number` | `0` | 空闲连接回收(超时未用关闭,容量收缩后自动重建;0=禁用) |
747
+ | `onQuery` | `(sql, durationMs, rowCount, traceId?) => void` | — | 查询观测钩子;第 4 参数为请求级 traceId(`x-trace-id` 头经 ALS 传播) |
725
748
 
726
749
  ### 幂等迁移(内置)
727
750
 
@@ -816,6 +839,12 @@ await ctx.redis.set('user', 1) // 实际写入 'api:user'
816
839
  | `cache(key, fn, ttl)` | 缓存读-算-写(null 不缓存防穿透) |
817
840
  | `publish(channel, msg)` | Pub-Sub 发布 |
818
841
  | `createSubscriber()` | 独立订阅连接(`subscribe`/`psubscribe` 回调式) |
842
+ | `hset / hget / hgetall / hdel` | hash 字段读写(`hgetall` → `Record`,缺失 `{}`) |
843
+ | `lpush / rpush / lpop / rpop / lrange` | list 队列操作(`lrange` 支持负数区间) |
844
+ | `sadd / srem / smembers` | set 成员操作(`sadd` 重复不加) |
845
+ | `zadd / zrange` | zset 有序集(score 升序) |
846
+ | `mget / mset / exists / setnx / incrby` | 批量读写 / 存在性 / 原子设值(锁基础)/ 增量 |
847
+ | `pipeline()` | 管道:批量命令一次往返(池级,key 自动加前缀) |
819
848
  | `command(name, ...args)` | 底层命令透传 |
820
849
  | `close()` | 关闭连接池 |
821
850
 
@@ -824,11 +853,50 @@ await ctx.redis.set('user', 1) // 实际写入 'api:user'
824
853
  | `url` | `string` | `REDIS_URL` 环境变量 | 连接字符串 |
825
854
  | `poolSize` | `number` | `5` | 连接池大小 |
826
855
  | `keyPrefix` | `string` | `''` | 所有 key 自动加前缀(多应用隔离) |
856
+ | `commandTimeoutMs` | `number` | `0` | 命令超时(阻塞命令 resolve(null);防挂起。0=禁用) |
857
+ | `socketTimeoutMs` | `number` | `0` | socket 响应超时(僵尸连接自愈:pending 有命令且超时无数据 → 主动断开重连。0=禁用) |
858
+
859
+ > **连接健康**:断线自动剔除死连接并重建(池不萎缩);`CLIENT KILL`/网络抖动后服务自愈,命令不命中死连接。
827
860
 
828
861
  > **裁剪声明**:集群(MOVED 路由)/ 哨兵 / 自动管道不支持(standalone 优先)。
829
862
 
830
863
  ---
831
864
 
865
+ ## scheduler — 计划任务(即时/延时/cron)
866
+
867
+ > 依赖 `queue`(触发后入队执行)。三类任务:即时(queue.add 已有)、延时(`ctx.schedule`)、定时(`ctx.cron`)。
868
+
869
+ ```ts
870
+ import { queue, scheduler } from 'weifuwu'
871
+
872
+ const q = queue()
873
+ app.use(q)
874
+ app.use(scheduler({ queue: q })) // 依赖 ctx.queue(触发后入队)
875
+
876
+ // 延时任务(单次):delayMs 或指定时间
877
+ await ctx.schedule('email.send', { to, body }, { delayMs: 30_000 })
878
+ await ctx.schedule('report.build', {}, { when: new Date('2026-09-01T00:00:00Z') })
879
+
880
+ // cron 定时任务(重复):每分钟触发 → 入队执行
881
+ ctx.cron('* * * * *', 'heartbeat.check', { scope: 'health' })
882
+ // 改需求 = 重新注册(同 name 覆盖更新,旧定义不残留)
883
+ ctx.cron('*/5 * * * *', 'heartbeat.check', { scope: 'health' })
884
+ // 停用 = cancel(删定义 + 清理 pending 触发点)
885
+ await ctx.cancelCron('heartbeat.check')
886
+
887
+ // 执行端:与 queue 完全一致
888
+ const worker = ctx.queue.worker('email.send', async (job) => { ... })
889
+ ```
890
+
891
+ - **延时**:ZSET(score=触发时间戳)+ 守护循环(独立连接)→ 到期 `ZREM` 原子抢占(多实例不重复)→ `queue.add`
892
+ - **多应用隔离**:`scheduler({ prefix })`——ZSET/HASH 应用级共享,多应用共用 redis 时必须各自 prefix(同应用多实例共享 prefix = 协作消费)
893
+ - **cron**:HASH 注册表(**field = name,同 name 重新注册 = 覆盖更新**,改表达式不残留旧定义)+ 滚动生成触发点(`ZADD NX` 幂等)→ 复用延时链路;`nextRunAt` 原子推进
894
+ - **取消**:`ctx.cancelCron(name)` 删定义 + 清理 pending 触发点(停用 cron 必须 cancel——定义无 TTL 会累积)
895
+ - **崩溃恢复**:未消费触发点留在 ZSET,重启后补扫立即触发(at-least-once,幂等由业务保证)
896
+ - **cron 表达式**:5 字段(分 时 日 月 周),支持 `*`/步进/列表/范围;时区 = 服务器本地;非法表达式注册即抛错
897
+ - **裁剪**:❌ cron 秒/年/别名(@daily)/特殊字符(L/W/#)、时区配置、单次任务取消(v2)、分布式锁(原子命令抢占替代)
898
+ - **文档红线**:cron 定义持久化在 HASH——进程重启后守护循环恢复即继续触发(无需重新注册);**停用必须 `cancelCron`**(定义无 TTL,不取消会永久触发)
899
+
832
900
  ## ui — SSR 渲染 + JS/CSS 编译
833
901
 
834
902
  ```ts
@@ -1343,6 +1411,8 @@ ctx.ui.render(['name'])
1343
1411
  | `useMedia()` | `useMedia(query, cb)` | 响应式媒体查询,断点变化时自动回调 |
1344
1412
  | `useBreakpoint()` | `useBreakpoint(cb \| bps, cb?)` | 命名断点 mobile/tablet/desktop |
1345
1413
  | `usePopupPosition()` | `usePopupPosition(opts)` | 弹层坐标跟随:scroll/resize 时自动重算 fixed 坐标 |
1414
+ | `useInView()` | `useInView(opts)` | 可见性观察(IntersectionObserver 封装,替代组件自建 scroll 监听);`isIn` 响应式 + `ready` |
1415
+ | `useScrollPosition()` | `useScrollPosition({ getScroller? })` | 滚动位置跟踪(全局 scroll 监听 + rAF 节流);`y` 响应式,容器/视口通用 |
1346
1416
 
1347
1417
  > 每个方法的完整说明见下文对应章节。
1348
1418
 
@@ -1357,6 +1427,8 @@ ctx.ui.render(['name'])
1357
1427
  | `ctx.ui.useMedia()` | 注册监听 | 浏览器事件驱动 | 当前组件 | **响应式媒体查询** — 断点变化时自动 dirty |
1358
1428
  | `ctx.ui.useBreakpoint()` | 注册监听 | 浏览器事件驱动 | 当前组件 | **命名断点** — mobile/tablet/desktop 自动 dirty |
1359
1429
  | `ctx.ui.usePopupPosition()` | 注册监听 | 浏览器事件驱动 | 当前组件 | **弹层坐标跟随** — scroll/resize 时自动重算 fixed 坐标 |
1430
+ | `ctx.ui.useInView()` | 注册监听 | IO 合成器线程评估 | 当前组件 | **可见性观察**(IO 封装,无 scroll-linked 警告)— Affix/BackTop/InView 统一使用;rootMargin/threshold 支持函数 |
1431
+ | `ctx.ui.useScrollPosition()` | 注册监听 | 全局 scroll + rAF 节流 | 当前组件 | **滚动位置跟踪** — `y` 响应式(视口/内部容器通用),Affix/VirtualList 使用 |
1360
1432
 
1361
1433
  `render()` 和 `dirty()` 无参 = 当前组件,传参 = 指定组件列表。三套 API 同一 scope 机制。
1362
1434
 
@@ -2227,7 +2299,9 @@ import type { RouterOptions } from 'weifuwu/client'
2227
2299
 
2228
2300
  # 组件库 (`weifuwu/components`)
2229
2301
 
2230
- 48 个 HTML 原语组件。每个是 `(_init, ctx) => (props) => VNode`(两阶段组件,与前端框架同一模型),引用 `--wf-*` CSS 变量做主题。另含 `confirm()` / `toast()` 命令式中间件。
2302
+ 91 个 HTML 原语组件。每个是 `(_init, ctx) => (props) => VNode`(两阶段组件,与前端框架同一模型),引用 `--wf-*` CSS 变量做主题。另含 `confirm()` / `toast()` 命令式中间件。
2303
+
2304
+ > **组件速查(weifuwu 组件 ↔ antd / Element Plus / shadcn-ui 对应 + 迁移示例)**:见 [`docs/components-map.md`](./docs/components-map.md)——从其他组件库迁来的开发者按功能直接找对应组件。
2231
2305
 
2232
2306
  ```ts
2233
2307
  import { Button, Input, Table, Modal, Toast } from 'weifuwu/components'
@@ -2317,6 +2391,33 @@ import 'weifuwu/components/style.css' // 包含 Token + 67 布局原语 + 组
2317
2391
  </Field>
2318
2392
  <Button type="submit">登录</Button>
2319
2393
  </Form>
2394
+
2395
+ // ├─ 新增批次组件(全量实现)
2396
+ <Rate value={3} onChange={setRate} /> // 评分
2397
+ <ToggleGroup type="single" options={toolbar} value={fmt} /> // 工具栏切换
2398
+ <CheckboxGroup options={members} value={selected} onChange={setSelected} /> // 多选列表
2399
+ <PinInput length={6} value={code} onChange={setCode} /> // 验证码
2400
+ <CopyButton value="https://weifuwu.dev" label="复制" /> // 复制
2401
+ <ColorPicker value={color} showInput onChange={setColor} /> // 颜色
2402
+ <Notification /> + notification.success({ title, description }) // 队列通知
2403
+ <Collapse items={docs} active={open} /> // 行内折叠
2404
+ <Tree data={orgTree} checkable checkedKeys={keys} /> // 树形(父子联动)
2405
+ <Cascader options={regions} value={['zj','hz']} /> // 级联选择
2406
+ <Transfer data={members} targetKeys={selected} /> // 穿梭框
2407
+ <Command items={commands} open={open} onOpenChange={setOpen} /> // ⌘K 命令面板
2408
+ <Carousel autoplay>{slides}</Carousel> // 轮播
2409
+ <Resizable defaultSize={180}>…</Resizable> // 拖拽分割
2410
+ <Calendar month={5} year={2025} events={events} /> // 月历
2411
+ <Watermark text="内部资料">…</Watermark> // 水印
2412
+ <VirtualList height={400} itemHeight={36} items={rows} renderItem={render} /> // 虚拟列表
2413
+ <QRCode value="https://weifuwu.dev" size={128} /> // 二维码(自研编码)
2414
+ <Img src="photo.png" preview /> // 图片点击放大
2415
+ <BackTop /> <Affix offsetTop={64}>…</Affix> // 回顶 / 固定
2416
+ <HoverCard content={<UserCard />}>…</HoverCard> // 悬停富内容
2417
+ <Mentions options={users} value={text} /> // @提及
2418
+ <ContextMenu items={actions}>…</ContextMenu> // 右键菜单
2419
+ <Menubar menus={menus} /> // 水平菜单
2420
+ <InfiniteScroll hasMore onLoadMore>…</InfiniteScroll> // 无限滚动
2320
2421
  ```
2321
2422
 
2322
2423
  > 所有组件引用 `--wf-*` CSS 变量做主题,详见下文的「样式定制指南」。
@@ -2389,6 +2490,9 @@ props 变化 ──────────────────────
2389
2490
  | SearchInput | `SearchInput` | `value`, `placeholder`, `onInput`, `onClear` | 搜索框 |
2390
2491
  | SegmentedControl | `SegmentedControl` | `options: SegmentedOption[]`, `value`, `onChange`, `size` | 分段选择器 |
2391
2492
  | ProgressBar | `ProgressBar` | `value`, `max`, `label`, `showValue` | 进度条 |
2493
+ | InputNumber | `InputNumber` | `value`, `min`, `max`, `step`, `precision`, `onChange` | 数字输入(增减按钮) |
2494
+ | PasswordInput | `PasswordInput` | `value`, `onInput`, `autoComplete` | 密码输入(可见性切换) |
2495
+ | TagsInput | `TagsInput` | `value: string[]`, `maxTags`, `allowDuplicates` | 标签输入(中文输入法感知) |
2392
2496
 
2393
2497
  ### 数据展示
2394
2498
 
@@ -2399,6 +2503,14 @@ props 变化 ──────────────────────
2399
2503
  | Badge | `Badge` | `variant: BadgeVariant`, `dot` | 徽标 |
2400
2504
  | Tag | `Tag` | `variant: 'default'\|'primary'\|'success'\|'danger'`, `closable`, `onClose` | 标签 |
2401
2505
  | Avatar | `Avatar` | `src`, `name`, `size`, `color` | 头像 |
2506
+ | AvatarGroup | `AvatarGroup` | `items`, `max`, `size` | 头像组(堆叠 + 溢出 +N) |
2507
+ | Timeline | `Timeline` | `items: TimelineItem[]`, `mode`, `reverse` | 时间线(执行日志/历史) |
2508
+ | Descriptions | `Descriptions` | `items: DescriptionItem[]`, `column`, `bordered` | 描述列表(详情页字段) |
2509
+ | Markdown | `Markdown` | `content` | AI 回复渲染(安全子集 parser) |
2510
+ | CodeBlock | `CodeBlock` | `code`, `lang`, `title` | 代码块(语言标签 + 复制) |
2511
+ | Highlight | `Highlight` | `text`, `query: string \| string[]` | 搜索词高亮(mark) |
2512
+ | List | `List` | `items`, `renderItem`, `divided`, `header/footer/empty` | 通用列表 |
2513
+ | Result | `Result` | `status`, `title`, `desc`, `extra` | 结果页(成功/失败/警告/信息) |
2402
2514
  | Icon | `Icon` | `name: IconName`, `size` | 图标(内置 25 个 stroke 图标,currentColor 随字号) |
2403
2515
  | StatCard | `StatCard` | `label`, `value`, `trend: 'up'\|'down'`, `trendLabel`, `icon`, `animate` | 统计卡片 |
2404
2516
  | PageHeader | `PageHeader` | `title`, `sub`, `display` | 页面标题(actions 放 children) |
@@ -2425,12 +2537,47 @@ props 变化 ──────────────────────
2425
2537
  | 组件 | 导入名 | 关键 Props | 说明 |
2426
2538
  |-----|--------|-----------|------|
2427
2539
  | Breadcrumb | `Breadcrumb` | `items: BreadcrumbItem[]` | 面包屑 |
2540
+ | Menu | `Menu` | `items: MenuItem[]`, `activeKey`, `onSelect` | 侧栏导航(分组 + 图标 + 方向键) |
2428
2541
  | Tabs | `Tabs` | `items: TabItem[]`, `active`, `onChange` | 标签页 |
2429
2542
  | Dropdown | `Dropdown` | `trigger`, `items: DropdownItem[]`, `open`, `onOpenChange` | 下拉菜单 |
2430
2543
  | Pagination | `Pagination` | `total`, `page`, `pageSize`, `onChange` | 分页 |
2431
2544
  | Steps | `Steps` | `items: StepItem[]`(`{ key, label }`), `current`, `active` | 步骤条 |
2432
2545
  | Accordion | `Accordion` | `items: AccordionItem[]`, `multiple` | 手风琴 |
2433
2546
 
2547
+ ### 新增批次(全量 91 组件)
2548
+
2549
+ | 组件 | 导入名 | 关键 Props | 说明 |
2550
+ |-----|--------|-----------|------|
2551
+ | Rate | `Rate` | `value`, `count`, `onChange`, `allowClear`, `readOnly`, `size` | 评分(键盘方向键/Home/End) |
2552
+ | Typography | `Title` `Text` `Paragraph` | `Title: level 1-5`;`Text: type/strong/underline/strike/mark/code`;`Paragraph: ellipsis` | 语义排版(Title/Text/Paragraph 三组件) |
2553
+ | Label | `Label` | `htmlFor`, `required` | 独立标签(必填星号) |
2554
+ | AspectRatio | `AspectRatio` | `ratio` | 宽高比容器(内容填满) |
2555
+ | Toggle | `Toggle` | `pressed`, `onPressedChange`, `variant`, `size` | 切换按钮(shadcn 对齐) |
2556
+ | ToggleGroup | `ToggleGroup` | `type: 'single'\|'multiple'`, `options`, `value`, `onChange` | 切换组 |
2557
+ | CheckboxGroup | `CheckboxGroup` | `options`, `value: string[]`, `onChange`, `cols` | 复选框组(栅格列数) |
2558
+ | PinInput | `PinInput` | `length`, `value`, `onChange`, `type` | 验证码输入(自动聚焦/粘贴分派/回退) |
2559
+ | CopyButton | `CopyButton` | `value`, `label`, `onCopy` | 复制按钮(clipboard + execCommand 降级) |
2560
+ | ColorPicker | `ColorPicker` | `value`, `onChange`, `showInput`, `preset` | 颜色选择(预设色板 + hex 输入) |
2561
+ | HoverCard | `HoverCard` | `content`, `position`, `openDelay`, `closeDelay` | 悬停富内容卡(shadcn) |
2562
+ | Notification | `Notification` | 命令式 `notification.success/error/warning/open` | 队列式通知(antd 对齐) |
2563
+ | BackTop | `BackTop` | `visibilityHeight`, `target`, `smooth` | 回到顶部(滚动超阈值显示) |
2564
+ | Affix | `Affix` | `offsetTop`, `target` | 固定定位(滚动超阈值钉住) |
2565
+ | ContextMenu | `ContextMenu` | `items: ContextMenuItem[]`(`{ label, onClick, variant: 'danger' }`) | 右键菜单(光标定位 + 方向键) |
2566
+ | Mentions | `Mentions` | `options: { value, label }[]`, `value`, `onChange`, `prefix` | @提及(composition 抑制) |
2567
+ | Collapse | `Collapse` | `items: CollapseItem[]`(`{ key, title, content, loading }`), `active`, `multiple` | 行内折叠(异步 loading) |
2568
+ | Tree | `Tree` | `data: TreeNode[]`, `expandedKeys`, `checkedKeys`, `checkable`, `selectedKeys`, `onCheck/onExpand/onSelect` | 树(递归 + 勾选父子联动 + 半选传播) |
2569
+ | Cascader | `Cascader` | `options: CascaderOption[]`, `value: string[]`, `onChange` | 级联选择(多列推进) |
2570
+ | Transfer | `Transfer` | `data: { key, label }[]`, `targetKeys`, `onChange`, `titles` | 穿梭框(选中 + 批量移动) |
2571
+ | Command | `Command` | `items: CommandItem[]`, `open`, `onOpenChange`, `shortcut` | 命令面板(⌘K 全局 + 键盘流) |
2572
+ | Menubar | `Menubar` | `menus: { key, label, items }[]` | 水平菜单栏(←→ 切换 + ↓ 展开) |
2573
+ | Carousel | `Carousel` | `children`, `autoplay`, `interval`, `loop`, `showArrows/Dots` | 轮播(箭头/圆点/循环/自动播放) |
2574
+ | Resizable | `Resizable` | `direction`, `defaultSize`, `min/maxSize` | 拖拽分割面板(pointer + 键盘方向键) |
2575
+ | Calendar | `Calendar` | `month`, `year`, `events`, `selectedDate`, `onMonthChange/onSelectDate` | 月历(事件点 + 月切换 + 选日) |
2576
+ | Watermark | `Watermark` | `text`, `fontSize`, `rotate`, `zIndex` | 水印(canvas 平铺) |
2577
+ | VirtualList | `VirtualList` | `items`, `height`, `itemHeight`, `renderItem`, `overscan` | 虚拟列表(spacer + 可见窗口,1000+ 条) |
2578
+ | InfiniteScroll | `InfiniteScroll` | `hasMore`, `loadMore`, `children`, `loader` | 触底加载(IntersectionObserver) |
2579
+ | QRCode | `QRCode` | `value`, `ecLevel`, `size`, `color`, `bgColor` | 二维码(自研 Reed-Solomon,版本 1-6) |
2580
+
2434
2581
  ### 图表
2435
2582
 
2436
2583
  | 组件 | 导入名 | 关键 Props | 说明 |
@@ -2450,6 +2597,7 @@ props 变化 ──────────────────────
2450
2597
  | 组件 | 导入名 | 关键 Props | 说明 |
2451
2598
  |-----|--------|-----------|------|
2452
2599
  | AiChat | `AiChat` | `chat`, `maxHeight?`, `labels?`, `renderMessage?`, `renderToolArgs?` | 标准 AI 对话界面:气泡 + 工具卡 + 审批卡 + 自动滚动 + 错误重试(接收 `ctx.ui.useChat()` handle) |
2600
+ | MessageBubble | `MessageBubble` | `content`, `role`, `status`, `actions` | 独立消息气泡(业务聊天页复用) |
2453
2601
  | ToolCallCard | `ToolCallCard` | `call`, `progress?`, `result?`, `renderArgs?` | 工具调用卡片:running(进度条)/ ok / error 三态(协议 §4) |
2454
2602
  | ApprovalCard | `ApprovalCard` | `request`, `status?`, `onApprove`, `onReject` | 人工审批卡片:待批(允许/拒绝+备注)/ 已批 / 已拒 / 超时(协议 §4.5) |
2455
2603
 
@@ -2709,7 +2857,7 @@ app.get('/layout.css', (req, ctx) => ctx.ui.css('weifuwu/layout'))
2709
2857
  </style>
2710
2858
  ```
2711
2859
 
2712
- 完整的零样式示例:`apps/weifuwu-demo`(一个页面 = 组件 + 原语,无 style.css)。
2860
+ 完整的零样式示例:`apps/components-demo`(组件 + 原语即插即用,无手写样式)。
2713
2861
 
2714
2862
  诚实例外(合理场景,仍可内联 `<style>` 解决):打印/PDF 导出规则、第三方库宿主样式、
2715
2863
  业务特有的一次性视觉(如色板选择器交互)。
@@ -2957,6 +3105,14 @@ app.get('/api/search', async (req, ctx) => {
2957
3105
  await ctx.limit('search', { max: 30, windowMs: 60_000 }) // 手动限流,超限抛 429
2958
3106
  })
2959
3107
 
3108
+ // 登录/注册防爆破:ctx.limit 默认按 IP 维度(每 IP 独立计数)
3109
+ app.post('/api/auth/register', async (req, ctx) => {
3110
+ await ctx.limit('register', { max: 5, windowMs: 60_000 }) // 每 IP 每分钟 5 次
3111
+ })
3112
+
3113
+ // 系统级总量限制:scope: 'global' 全局共享维度
3114
+ await ctx.limit('total-jobs', { max: 1000, windowMs: 60_000, scope: 'global' })
3115
+
2960
3116
  // 登录防爆破(配合 userSystem):组合键 ip:email(key 接收标准 Request,取头拿 IP)
2961
3117
  app.use(rateLimit({ key: (req) => `login:${req.headers.get('x-forwarded-for')}:${req.headers.get('x-user-email')}`, max: 5, windowMs: 15 * 60_000 }))
2962
3118
  ```
@@ -3035,7 +3191,8 @@ ctx.msg.sendTo('u2', { type: 'mention' }) // 用户维度点对点
3035
3191
 
3036
3192
  - **数据模型**:`_weifuwu_conversations` / `_weifuwu_conversation_members` / `_weifuwu_messages`(`sender_type + sender_id` 不 FK users——user/agent/system 消息天然可存);direct 会话同对用户唯一、历史游标分页、未读数(`last_read_at`)、编辑/删除软删
3037
3193
  - **实时协议内置**:`handler()` 提供 `connected / subscribe→subscribed / unsubscribe / ping→pong`——前端 `ctx.ws.send({ type: 'subscribe', room })` 直接可用,两端协议由框架定义
3038
- - **跨进程**:`redis` 选项 → Redis pub/sub 广播(psubscribe 模式),多实例部署天然一致;无 redis 优雅降级单进程
3194
+ - **跨进程**:`redis` 选项 → Redis pub/sub 广播(psubscribe 模式),多实例部署天然一致;无 redis 优雅降级单进程。
3195
+ **环回去重**:`broadcast` = 本地直发 + Redis publish,本实例的 subscriber 会收到自己 publish 的消息——publish 携带实例唯一标识 `_pid`(`wf:{pid}:{seq}`),订阅回调跳过自己的环回,保证每个事件恰好投递一次(防 token 级事件重复/乱序)
3039
3196
  - **与 userSystem 咬合**:`sendTo(ctx.user.id)` 按身份路由、`createConversation(ctx.user.id)` 创建者即身份、成员校验自动对齐——身份是消息的路由,消息是身份的交互
3040
3197
  - **裁剪**:已读回执状态机(只做未读数)、附件存储、全文搜索、消息确认/重试(可靠投递用 queue)、移动端推送
3041
3198
 
@@ -11,5 +11,17 @@ export declare function patchValue(parent: Node, oldNode: Node | null, oldInput:
11
11
  export declare function patchProps(el: Element, oldProps: any, newProps: any): void;
12
12
  /** 为无 key 的子节点自动分配位置 key,确保 keyed diff 正确性 */
13
13
  export declare function ensureKeys(oldChildren: any[], newChildren: any[]): void;
14
+ /**
15
+ * 将 children 映射到它们实际产生的 DOM 节点(每个 child 一个 Node[])。
16
+ *
17
+ * 1 VNode ≠ 1 DOM 节点:Fragment 展开成多个直属节点(_childNodes),
18
+ * null/boolean/Portal 产生 0 个。explicitNodes 提供限定范围(Fragment 子项
19
+ * 用其自身 _childNodes),否则从 source(parent.childNodes 或给定快照)按计数游标分配。
20
+ */
21
+ export declare function mapChildDomNodes(source: Node[], children: any[]): (Node[] | null)[];
14
22
  export declare function normalize(children: any): any[];
15
- export declare function patchKeyedChildren(parent: Node, oldChildren: any[], newChildren: any[], ctx: WfuiContext): void;
23
+ /**
24
+ * keyed 子节点 diff。返回每个 new child 的 DOM 节点范围(newNodes,可为空)。
25
+ * oldNodes:old children → 实际 DOM 节点(mapChildDomNodes 结果)。
26
+ */
27
+ export declare function patchKeyedChildren(parent: Node, oldChildren: any[], newChildren: any[], ctx: WfuiContext, oldNodes?: (Node[] | null)[], rangeStart?: Node | null): (Node[] | null)[];
@@ -1,4 +1,4 @@
1
- var ge="__wfAsyncComponent";function qe(e){let t=e;return t[ge]=!0,t}function I(e){return typeof e=="function"&&e?.[ge]===!0}var W=Symbol("Fragment"),N=Symbol("Portal");function X(e,t,n){return{type:e,props:he(t),key:n??void 0}}var De=X;function Fe(e,t,n){return X(e,t,n)}function $e(e,t,...n){let o=he(t??{});return n.length>0&&(o.children=n.length===1?n[0]:n),{type:e,props:o,key:t?.key??void 0}}function he(e){if(!e)return{};let t={};for(let n of Object.keys(e))n!=="key"&&(t[n]=e[n]);return t}function Be(e,t){return{type:N,props:{children:e,portalKey:t},key:t??void 0,_placement:"remote"}}var Ke=0,A=new Map,F=[];function Ce(e){F.push(e)}var $=new WeakMap;function j(){$=new WeakMap}function Z(e,t){let n=$.get(e);if(n)return n;let o={promise:null};return o.promise=Promise.resolve().then(()=>e(t)).then(r=>{if(typeof r!="function")throw new Error(`asyncComponent factory <${e.name||"anonymous"}> must return a Component (initProps, ctx) => (props) => VNode.`);return o.resolved=r,r}),$.set(e,o),o}async function xe(e,t){return Z(e,t).promise}function we(e){return $.get(e)?.resolved}function ze(e){let t=e._child;if(t!=null)if(Array.isArray(t))for(let n of t)n&&typeof n=="object"&&_(n);else typeof t=="object"&&_(t)}function _(e){if(e==null||typeof e!="object")return;let t=e;if(t._id){if(t._customId&&A.delete(t._customId),A.delete(t._id),F.length>0){for(let n of F)n(t._id);if(t._customId)for(let n of F)n(t._customId)}t._id=void 0,t._customId=void 0,t._render=void 0,t._parentNode=void 0,t._refNode=void 0}if(t._child!=null){if(Array.isArray(t._child))for(let n of t._child)n&&typeof n=="object"&&_(n);else _(t._child);t._child=void 0}if(t.props?.children&&typeof t.type=="string"){let n=Array.isArray(t.props.children)?t.props.children:[t.props.children];for(let o of n)o&&typeof o=="object"&&_(o)}typeof t.props?.ref=="function"&&t.props.ref(null),t._remoteEl&&(ze(t),t._remoteEl.remove(),t._remoteEl=void 0)}function U(){return`_wf_${Ke++}`}var be=new WeakMap;function Ge(e){let t=be.get(e)??{count:0,warned:!1};t.count++,t.count>=3&&!t.warned&&(t.warned=!0,console.warn("[weifuwu] ref \u51FD\u6570\u6BCF\u6B21\u6E32\u67D3\u90FD\u53D8\u5316\uFF08\u5185\u8054 ref\uFF09\u2014\u2014ref \u56DE\u8C03\u5728\u6BCF\u6B21\u6E32\u67D3\u540E\u91CD\u65B0\u6267\u884C\uFF08\u6027\u80FD\u635F\u8017\uFF09\u3002\u628A ref \u5B9A\u4E49\u5230 mount \u4F5C\u7528\u57DF\uFF08\u7A33\u5B9A\u5F15\u7528\uFF09\uFF1Aconst listRef = (el) => {...}; return h('div', { ref: listRef })")),be.set(e,t)}function M(e,t,n,o,r){if(n==null){if(o==null)return null;let u=S(o,r);return u==null?null:(t&&t.parentNode?t.parentNode.insertBefore(u,t):e.appendChild(u),u)}if(o==null)return t?(_(n),t.remove()):_(n),null;let s=Te(n),i=Te(o);if(s!==i){_(n);let u=S(o,r);return u==null?null:(t?.parentNode&&t.parentNode.replaceChild(u,t),u)}if(i==="text")return t&&t.textContent!==String(o)&&(t.textContent=String(o)),t;let l=o,a=n;if(typeof l.type=="function"){let u=l.type;a._render&&(l._render=a._render,l._id=a._id,l._id&&A.set(l._id,l)),l._parentNode=e,l._refNode=t;let m=Object.create(r);if(m.ui=Object.create(r.ui),m.ui._selfId=l._id,m.ui._selfVNode=l,l._ctxVersion=a._ctxVersion??m.ui._ctxVersion??0,a._render&&Ye(a.props,l.props)&&!m.ui._dirtySet?.has(a._id)&&l._ctxVersion===m.ui._ctxVersion)return l._child=a._child,t;m.ui._dirtySet?.delete(a._id);let y;try{typeof l._render=="function"?y=l._render(l.props):y=ne(u,l.props,l,m)}catch(d){let p=r.ui?._errorHandler;p?(p(d),y=null):(console.error(`[weifuwu] Component render error in <${u?.name||"anonymous"}> (id: ${a._id??"?"}, phase: update)`,d),y=null)}let f=a._child;l._child=y;let c=M(e,t,f,y,m);return c||(l._refNode=null),c}if(l.type===W)return Ae(e,a,l,r),t;if(typeof l.type=="string"){if(t&&t.nodeType===1){let u=a.props?.ref,m=l.props?.ref;u!==m&&(typeof m=="function"&&m(t),typeof u=="function"&&typeof m=="function"&&Ge(t)),te(t,a.props,l.props),Ae(t,a,l,r)}else if(t){_(n);let u=S(o,r);return u==null?null:(t.parentNode?.replaceChild(u,t),u)}return t}if(l.type===N)return q(a,l,r),null;if(Array.isArray(o)){let u=Array.isArray(n)?n:[];return B(u,o),K(e,u,o,r),t}return t}var ve=new Map;function Je(e){let t=ve.get(e);return t||(t=`fn:${e.name||"anon"}`,ve.set(e,t)),t}function Te(e){if(e==null||typeof e=="boolean")return"null";if(typeof e=="string"||typeof e=="number")return"text";if(Array.isArray(e))return"array";let t=e;return typeof t.type=="function"?Je(t.type):t.type===W?"fragment":t.type===N?"portal":typeof t.type=="string"?"tag:"+t.type:"unknown"}function te(e,t,n){let o=t?Object.keys(t).filter(i=>i!=="children"&&i!=="key"&&i!=="innerHTML"):[],r=n?Object.keys(n).filter(i=>i!=="children"&&i!=="key"&&i!=="innerHTML"):[],s=new Set(r);for(let i of o)if(!s.has(i)){if(i==="ref")continue;i.startsWith("on")&&typeof t[i]=="function"?e.removeEventListener(i.slice(2).toLowerCase(),t[i]):i==="value"&&(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement)?e.value="":e.removeAttribute(i==="className"?"class":i)}for(let i of r){if(i==="ref")continue;let l=t?.[i],a=n?.[i];if(i==="innerHTML")a!==l&&(e.innerHTML=String(a??""));else if(a!==l)if(i==="class"||i==="className")e instanceof SVGElement?e.setAttribute("class",_e(a)):e.className=_e(a);else if(i==="style"&&typeof a=="object"){let u=e.style;for(let m of Object.keys(a)){let y=a[m];y!=null&&(u[m]=typeof y=="number"?y+"px":String(y))}}else if(i.startsWith("on")&&typeof a=="function"){let u=i.slice(2).toLowerCase();typeof l=="function"&&e.removeEventListener(u,l),e.addEventListener(u,a)}else i==="value"&&(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement)?e.value=String(a??""):a===!0?e.setAttribute(i,""):a!=null&&a!==!1?e.setAttribute(i,String(a)):i==="value"&&(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement)?e.value="":e.removeAttribute(i)}}function _e(e){return typeof e=="string"?e:Array.isArray(e)?e.filter(Boolean).join(" "):e&&typeof e=="object"?Object.entries(e).filter(([,t])=>t).map(([t])=>t).join(" "):""}function ee(e){if(!(e==null||typeof e!="object"))return e.key}function B(e,t){if(!t.some(o=>o&&typeof o=="object"&&o.key!==void 0)){for(let o=0;o<t.length;o++){let r=t[o];r&&typeof r=="object"&&(r.key=o)}for(let o=0;o<e.length;o++){let r=e[o];r&&typeof r=="object"&&(r.key=o)}}}function Ae(e,t,n,o){let r=H(t.props?.children),s=H(n.props?.children);B(r,s),K(e,r,s,o)}function H(e){if(e==null)return[];if(!Array.isArray(e))return[e];let t=[];for(let n of e)Array.isArray(n)?t.push(...n):t.push(n);return t}function K(e,t,n,o){if(!n.some(f=>f&&typeof f=="object"&&f.key!==void 0)){let f=Math.max(t.length,n.length);for(let c=0;c<f;c++){let d=c<t.length?t[c]:null,p=c<n.length?n[c]:null;if(p==null){if(d!=null){_(d);let g=e.childNodes[c];g&&g.remove()}}else if(d==null){let g=S(p,o);g!=null&&e.appendChild(g)}else{let g=e.childNodes[c]||null;M(e,g,d,p,o)}}return}let s=0;for(let f=0;f<t.length;f++){let c=t[f];if(c==null||typeof c=="boolean")continue;if(ee(c)===void 0){let p=e.childNodes[s];p&&p.remove()}else c&&typeof c=="object"&&c._placement==="remote"||s++}let i=new Map,l=0;for(let f=0;f<t.length;f++){let c=ee(t[f]);if(c!==void 0){let d=t[f],p=d&&typeof d=="object"&&d._placement==="remote";i.set(c,{vnode:d,node:p?null:e.childNodes[l]||null,remote:!!p,index:l}),p||l++}}let a=n.map(f=>ee(f)),u=new Set(a);for(let f of i.keys())if(!u.has(f)){let c=i.get(f);_(c.vnode),c.node&&c.node?.remove(),i.delete(f)}let m=-1,y=e.firstChild;for(let f=0;f<n.length;f++){let c=a[f],d=n[f],p=c!==void 0?i.get(c):void 0,g=d&&typeof d=="object"&&d._placement==="remote";if(p)if(p.node)p.index<m&&e.insertBefore(p.node,y),m=Math.max(m,p.index),M(e,p.node,p.vnode,d,o),y=(p.node.parentNode===e?p.node:e.firstChild)?.nextSibling??null;else if(p.remote)q(p.vnode,d,o);else{let h=M(e,null,p.vnode,d,o);h!=null&&(e.insertBefore(h,y),y=h.nextSibling)}else if(g)V(d,o);else{let h=S(d,o);h!=null&&(e.insertBefore(h,y),y=h.nextSibling)}}}function Qe(e,t){if(e===t)return!0;if(Array.isArray(e)&&Array.isArray(t)){if(e.length!==t.length)return!1;for(let n=0;n<e.length;n++)if(e[n]!==t[n])return!1;return!0}return e===t}function Ye(e,t){if(e===t)return!0;if(!e||!t)return!1;let n=new Set([...Object.keys(e),...Object.keys(t)]);for(let o of n)if(o!=="key"){if(o==="children"){if(!Qe(e[o],t[o]))return!1}else if(e[o]!==t[o])return!1}return!0}var oe="http://www.w3.org/2000/svg",re=new Set(["svg","path","circle","line","rect","text","g","polyline","polygon","ellipse","defs","use","clipPath","mask","linearGradient","radialGradient","stop","tspan"]);function Re(e,t){return S(e,t)}function S(e,t){if(e==null||typeof e=="boolean")return null;if(typeof e=="string"||typeof e=="number")return document.createTextNode(String(e));if(Array.isArray(e))return et(e,t);let n=e;if(n.type===N)return V(n,t),null;if(n.type===W){let i=document.createDocumentFragment(),l=n.props?.children==null?[]:Array.isArray(n.props.children)?n.props.children:[n.props.children];for(let a of l){let u=S(a,t);u!=null&&i.appendChild(u)}return i}if(typeof n.type=="function")return Ze(n.type,n.props,n,t);let o=n.type,r=re.has(o)?document.createElementNS(oe,o):document.createElement(o);n.el=r;let s;for(let[i,l]of Object.entries(n.props??{}))i==="children"||i==="key"||i==="value"||i==="innerHTML"||ke(r,i,l);if("value"in(n.props??{})&&r instanceof HTMLSelectElement?s=n.props.value:"value"in(n.props??{})&&ke(r,"value",n.props.value),"innerHTML"in(n.props??{}))r.innerHTML=String(n.props.innerHTML??"");else{let i=se(n.props?.children);for(let l of i){let a=S(l,t);if(a!=null&&(r.appendChild(a),l&&typeof l=="object"&&typeof l.type=="function")){let u=l;u._parentNode||(u._parentNode=r,u._refNode=a)}}}return s!==void 0&&(r.value=String(s)),typeof n.props?.ref=="function"&&n.props.ref(r),r}function Xe(e){let t=e.ui;t&&typeof t.render=="function"&&t.render(["_wf_root"])}function ne(e,t,n,o){let r;if(I(e)){if(r=we(e),!r)return Z(e,o).promise.then(()=>Xe(o),()=>{}),null}else r=e;let s=r(t,o);if(typeof s!="function")throw new Error(`Component ${e.name||"anonymous"} must return a render function. Use (init_props, ctx) => (props) => VNode pattern.`);return n._render=s,s(t)}function Ze(e,t,n,o){o.ui=o.ui??{},n._id||(n._id=U(),A.set(n._id,n));let r=Object.create(o);r.ui=Object.create(o.ui),r.ui._selfId=n._id,r.ui._selfVNode=n,n._ctxVersion=r.ui._ctxVersion??0;let s;try{s=ne(e,t,n,r)}catch(l){let a=o.ui?._errorHandler;a?(a(l),s=null):(console.error(`[weifuwu] Component render error in <${e.name||"anonymous"}> (id: ${n._id??"?"}, phase: mount)`,l),s=null)}if(s==null)return n._child=null,null;n._child=s;let i=S(s,r);return n._refNode||(n._refNode=i),i}function et(e,t){let n=document.createDocumentFragment();for(let o of e){let r=S(o,t);r!=null&&n.appendChild(r)}return n}function tt(){let e=document.getElementById("__wf_portal");return e||(e=document.createElement("div"),e.id="__wf_portal",e.style.cssText="position:fixed;inset:0;pointer-events:none;z-index:9999",document.body.appendChild(e)),e}function V(e,t){let n=tt(),o=document.createElement("div");o.style.pointerEvents="auto",n.appendChild(o),e._remoteEl=o;let r=H(e.props?.children);e._child=r;for(let s of r){let i=S(s,t);i!=null&&o.appendChild(i)}}function q(e,t,n){let o=e?._remoteEl;if(t._remoteEl=o,!o){V(t,n);return}let r=H(t.props?.children),s=e._child||[];t._child=r,B(s,r),K(o,s,r,n)}function se(e){if(e==null)return[];if(!Array.isArray(e))return[e];let t=[];for(let n of e)Array.isArray(n)?t.push(...n):t.push(n);return t}function ke(e,t,n){if(t==="class"||t==="className")e instanceof SVGElement?e.setAttribute("class",String(n??"")):e.className=String(n??"");else if(t==="style"&&typeof n=="object"&&n!==null){let o=e.style;for(let r of Object.keys(n)){let s=n[r];s!=null&&(o[r]=typeof s=="number"?s+"px":String(s))}}else t.startsWith("on")&&typeof n=="function"?e.addEventListener(t.slice(2).toLowerCase(),n):t==="value"&&(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement)?e.value=String(n??""):n===!0?e.setAttribute(t,""):n!=null&&n!==!1&&e.setAttribute(t,String(n))}function nt(e,t,n){e.innerHTML="";let o=S(t,n);o instanceof Node?e.appendChild(o):Array.isArray(o)&&o.forEach(r=>e.appendChild(r))}function ie(e){e.node=e.node?e.node.nextSibling:null}function ot(e,t){e.node&&e.node.parentNode?e.node.parentNode.insertBefore(t,e.node):e.parent.appendChild(t)}function rt(e,t){e.node&&e.node.parentNode?(e.node.parentNode.replaceChild(t,e.node),ie(e)):e.parent.appendChild(t)}async function D(e,t,n){if(e==null||typeof e=="boolean")return null;if(typeof e=="string"||typeof e=="number"){let l=String(e);if(n.node&&n.node.nodeType===3)return n.node.textContent!==l&&(n.node.textContent=l),ie(n),n.node;let a=document.createTextNode(l);return ot(n,a),a}if(Array.isArray(e)){let l=null;for(let a of e){let u=await D(a,t,n);u!=null&&!l&&(l=u)}return l}let o=e;if(o.type===N||o.type===W){let l=o.props?.children,a=l==null?[]:Array.isArray(l)?l:[l],u=null;for(let m of a){let y=await D(m,t,n);y!=null&&!u&&(u=y)}return u}if(typeof o.type=="function")return st(o,t,n);let r=o.type,s=o.props??{},i;if(n.node&&n.node.nodeType===1&&n.node.tagName.toLowerCase()===r.toLowerCase()?(i=n.node,ie(n)):(i=re.has(r)?document.createElementNS(oe,r):document.createElement(r),rt(n,i)),o.el=i,te(i,null,s),!("innerHTML"in s)){let l={parent:i,node:i.firstChild},a=se(s.children);for(let u of a){let m=await D(u,t,l);if(m!=null&&m.parentNode!==i&&i.appendChild(m),u&&typeof u=="object"&&typeof u.type=="function"){let y=u;y._parentNode||(y._parentNode=i,y._refNode=m)}}for(;l.node;){let u=l.node;l.node=u.nextSibling,u.parentNode?.removeChild(u)}}return"value"in s&&i instanceof HTMLSelectElement&&(i.value=String(s.value??"")),typeof s.ref=="function"&&s.ref(i),i}async function st(e,t,n){t.ui=t.ui??{},e._id||(e._id=U(),A.set(e._id,e));let o=Object.create(t);o.ui=Object.create(t.ui),o.ui._selfId=e._id,o.ui._selfVNode=e,e._ctxVersion=o.ui._ctxVersion??0;let r=e.type,s;try{let l;I(r)?l=await xe(r,o):l=r;let a=l(e.props??{},o);if(typeof a!="function")throw new Error(`Component ${r.name||"anonymous"} must return a render function. Use (init_props, ctx) => (props) => VNode pattern.`);e._render=a,s=a(e.props??{})}catch(l){let a=t.ui?._errorHandler;a?(a(l),s=null):(console.error(`[weifuwu] Component hydration error in <${r.name||"anonymous"}> (id: ${e._id??"?"})`,l),s=null)}if(s==null)return e._child=null,null;e._child=s;let i=await D(s,o,n);return e._refNode||(e._refNode=i),i}async function ae(e,t,n){let o={parent:e,node:e.firstChild};for(await D(t,n,o);o.node;){let r=o.node;o.node=r.nextSibling,r.parentNode?.removeChild(r)}}function le(e){let t=new WeakMap,n=new Set,o=s=>{if(s===null||typeof s!="object")return s;if(t.has(s))return t.get(s);let i=new Proxy(s,{set(l,a,u){if(Reflect.get(l,a)===u)return!0;Reflect.set(l,a,u),e();for(let y of n)y();return!0},get(l,a){let u=Reflect.get(l,a);return typeof u=="object"&&u!==null?o(u):u},deleteProperty(l,a){if(Reflect.has(l,a)){Reflect.deleteProperty(l,a),e();for(let u of n)u()}return!0}});return t.set(s,i),i},r=o({});return Object.defineProperty(r,"__watch",{value:s=>(n.add(s),()=>{n.delete(s)}),writable:!1,enumerable:!1}),r}function ue(e,t,n){let o=new AbortController,r=n?.signal;r&&(r.aborted?o.abort():r.addEventListener("abort",()=>o.abort(),{once:!0}));let s=n?.traceId??ct(),i=n?.record!==!1,l=[],a=(async()=>{let u;try{u=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json","X-Trace-Id":s,Accept:"text/event-stream",...n?.headers},body:JSON.stringify(t),signal:o.signal})}catch(m){if(o.signal.aborted)return;n?.onError?.({code:"provider_error",message:m instanceof Error?m.message:String(m)});return}if(!u.ok){n?.onError?.({code:ut(u.status),message:`HTTP ${u.status} ${u.statusText}`});return}try{for await(let{name:m,data:y}of at(u.body)){if(o.signal.aborted)return;lt(l,{name:m,data:y},i),it(m,y,n??{})}}catch(m){if(o.signal.aborted)return;n?.onError?.({code:"provider_error",message:m instanceof Error?m.message:String(m)})}})();return{abort:()=>o.abort(),done:a,traceId:s,events:l}}function it(e,t,n){switch(e){case"wf:token":return n.onToken?.(t.text);case"wf:tool_call":return n.onToolCall?.(t);case"wf:tool_result":return n.onToolResult?.(t);case"wf:tool_progress":return n.onToolProgress?.(t);case"wf:step":return n.onStep?.(t);case"wf:approval_request":return n.onApproval?.(t);case"wf:usage":return n.onUsage?.(t);case"wf:done":return n.onDone?.(t);case"wf:error":return n.onError?.(t);default:return n.onEvent?.(e,t)}}async function*at(e){let t=e.getReader(),n=new TextDecoder,o="";try{for(;;){let{done:r,value:s}=await t.read();if(r)break;o+=n.decode(s,{stream:!0});let i=o.split(`
1
+ var xe="__wfAsyncComponent";function Be(e){let t=e;return t[xe]=!0,t}function H(e){return typeof e=="function"&&e?.[xe]===!0}var M=Symbol("Fragment"),W=Symbol("Portal");function te(e,t,n){return{type:e,props:we(t),key:n??void 0}}var Ke=te;function ze(e,t,n){return te(e,t,n)}function Ge(e,t,...n){let o=we(t??{});return n.length>0&&(o.children=n.length===1?n[0]:n),{type:e,props:o,key:t?.key??void 0}}function we(e){if(!e)return{};let t={};for(let n of Object.keys(e))n!=="key"&&(t[n]=e[n]);return t}function Je(e,t){return{type:W,props:{children:e,portalKey:t},key:t??void 0,_placement:"remote"}}var Qe=0,N=new Map,K=[];function be(e){K.push(e)}var z=new WeakMap;function j(){z=new WeakMap}function ne(e,t){let n=z.get(e);if(n)return n;let o={promise:null};return o.promise=Promise.resolve().then(()=>e(t)).then(r=>{if(typeof r!="function")throw new Error(`asyncComponent factory <${e.name||"anonymous"}> must return a Component (initProps, ctx) => (props) => VNode.`);return o.resolved=r,r}),z.set(e,o),o}async function ve(e,t){return ne(e,t).promise}function Te(e){return z.get(e)?.resolved}function Ye(e){let t=e._child;if(t!=null)if(Array.isArray(t))for(let n of t)n&&typeof n=="object"&&E(n);else typeof t=="object"&&E(t)}function E(e){if(e==null||typeof e!="object")return;let t=e;if(t._id){if(t._customId&&N.delete(t._customId),N.delete(t._id),K.length>0){for(let n of K)n(t._id);if(t._customId)for(let n of K)n(t._customId)}t._id=void 0,t._customId=void 0,t._render=void 0,t._parentNode=void 0,t._refNode=void 0}if(t._child!=null){if(Array.isArray(t._child))for(let n of t._child)n&&typeof n=="object"&&E(n);else E(t._child);t._child=void 0}if(t.props?.children&&typeof t.type=="string"){let n=Array.isArray(t.props.children)?t.props.children:[t.props.children];for(let o of n)o&&typeof o=="object"&&E(o)}typeof t.props?.ref=="function"&&t.props.ref(null),t._remoteEl&&(Ye(t),t._remoteEl.remove(),t._remoteEl=void 0)}function D(){return`_wf_${Qe++}`}var _e=new WeakMap;function Xe(e){let t=_e.get(e)??{count:0,warned:!1};t.count++,t.count>=3&&!t.warned&&(t.warned=!0,console.warn("[weifuwu] ref \u51FD\u6570\u6BCF\u6B21\u6E32\u67D3\u90FD\u53D8\u5316\uFF08\u5185\u8054 ref\uFF09\u2014\u2014ref \u56DE\u8C03\u5728\u6BCF\u6B21\u6E32\u67D3\u540E\u91CD\u65B0\u6267\u884C\uFF08\u6027\u80FD\u635F\u8017\uFF09\u3002\u628A ref \u5B9A\u4E49\u5230 mount \u4F5C\u7528\u57DF\uFF08\u7A33\u5B9A\u5F15\u7528\uFF09\uFF1Aconst listRef = (el) => {...}; return h('div', { ref: listRef })")),_e.set(e,t)}function I(e,t,n,o,r){if(n==null){if(o==null)return null;let u=R(o,r);return u==null?null:(t&&t.parentNode?t.parentNode.insertBefore(u,t):e.appendChild(u),u)}if(o==null)return t?(E(n),t.remove()):E(n),null;let s=Se(n),i=Se(o);if(s!==i){E(n);let u=R(o,r);return u==null?null:(t?.parentNode&&t.parentNode.replaceChild(u,t),u)}if(i==="text")return t&&t.textContent!==String(o)&&(t.textContent=String(o)),t;let l=o,a=n;if(typeof l.type=="function"){let u=l.type;a._render&&(l._render=a._render,l._id=a._id,l._id&&N.set(l._id,l)),l._parentNode=e,l._refNode=t;let p=Object.create(r);if(p.ui=Object.create(r.ui),p.ui._selfId=l._id,p.ui._selfVNode=l,l._ctxVersion=a._ctxVersion??p.ui._ctxVersion??0,a._render&&tt(a.props,l.props)&&!p.ui._dirtySet?.has(a._id)&&l._ctxVersion===p.ui._ctxVersion)return l._child=a._child,t;p.ui._dirtySet?.delete(a._id);let m;try{typeof l._render=="function"?m=l._render(l.props):m=se(u,l.props,l,p)}catch(c){let f=r.ui?._errorHandler;f?(f(c),m=null):(console.error(`[weifuwu] Component render error in <${u?.name||"anonymous"}> (id: ${a._id??"?"}, phase: update)`,c),m=null)}let w=a._child;l._child=m;let d=I(e,t,w,m,p);return d||(l._refNode=null),d}if(l.type===M){let u=a._childNodes,p=Ne(e,a,l,r,u);return l._childNodes=p,t}if(typeof l.type=="string"){if(t&&t.nodeType===1){let u=a.props?.ref,p=l.props?.ref;u!==p&&(typeof p=="function"&&p(t),typeof u=="function"&&typeof p=="function"&&Xe(t)),re(t,a.props,l.props),Ne(t,a,l,r)}else if(t){E(n);let u=R(o,r);return u==null?null:(t.parentNode?.replaceChild(u,t),u)}return t}if(l.type===W)return $(a,l,r),null;if(Array.isArray(o)){let u=Array.isArray(n)?n:[];G(u,o);let p=Array.from(e.childNodes),m=t?p.indexOf(t):-1,w=m>=0?q(p.slice(m),u):q(p,u);return J(e,u,o,r,w,t),t}return t}var Ae=new Map;function Ze(e){let t=Ae.get(e);return t||(t=`fn:${e.name||"anon"}`,Ae.set(e,t)),t}function Se(e){if(e==null||typeof e=="boolean")return"null";if(typeof e=="string"||typeof e=="number")return"text";if(Array.isArray(e))return"array";let t=e;return typeof t.type=="function"?Ze(t.type):t.type===M?"fragment":t.type===W?"portal":typeof t.type=="string"?"tag:"+t.type:"unknown"}function re(e,t,n){let o=t?Object.keys(t).filter(i=>i!=="children"&&i!=="key"&&i!=="innerHTML"):[],r=n?Object.keys(n).filter(i=>i!=="children"&&i!=="key"&&i!=="innerHTML"):[],s=new Set(r);for(let i of o)if(!s.has(i)){if(i==="ref")continue;i.startsWith("on")&&typeof t[i]=="function"?e.removeEventListener(i.slice(2).toLowerCase(),t[i]):i==="value"&&(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement)?e.value="":e.removeAttribute(i==="className"?"class":i)}for(let i of r){if(i==="ref")continue;let l=t?.[i],a=n?.[i];if(i==="innerHTML")a!==l&&(e.innerHTML=String(a??""));else if(a!==l)if(i==="class"||i==="className")e instanceof SVGElement?e.setAttribute("class",Ee(a)):e.className=Ee(a);else if(i==="style"&&typeof a=="object"){let u=e.style;for(let p of Object.keys(a)){let m=a[p];m!=null&&(u[p]=typeof m=="number"?m+"px":String(m))}}else if(i.startsWith("on")&&typeof a=="function"){let u=i.slice(2).toLowerCase();typeof l=="function"&&e.removeEventListener(u,l),e.addEventListener(u,a)}else i==="value"&&(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement)?e.value=String(a??""):a===!0?e.setAttribute(i,""):a!=null&&a!==!1?e.setAttribute(i,String(a)):i==="value"&&(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement)?e.value="":e.removeAttribute(i)}}function Ee(e){return typeof e=="string"?e:Array.isArray(e)?e.filter(Boolean).join(" "):e&&typeof e=="object"?Object.entries(e).filter(([,t])=>t).map(([t])=>t).join(" "):""}function oe(e){if(!(e==null||typeof e!="object"))return e.key}function G(e,t){if(!t.some(o=>o&&typeof o=="object"&&o.key!==void 0)){for(let o=0;o<t.length;o++){let r=t[o];r&&typeof r=="object"&&(r.key=o)}for(let o=0;o<e.length;o++){let r=e[o];r&&typeof r=="object"&&(r.key=o)}}}function q(e,t){let n=[],o=0;for(let r of t){if(r==null||typeof r=="boolean"){n.push(null);continue}let s=r;if(s.type===W){n.push(null);continue}if(s.type===M){let i=s._childNodes;Array.isArray(i)&&i.length>0?(n.push(i.slice()),o+=i.length):(n.push(e[o]?[e[o]]:null),o+=1)}else typeof process<"u"&&process.env.DBG&&console.error("[map] idx=",o,"type=",s.type,"sourceLen=",e.length,"hit=",!!e[o]),n.push(e[o]?[e[o]]:null),o+=1}return n}function Ne(e,t,n,o,r){let s=F(t.props?.children),i=F(n.props?.children);G(s,i);let l=r??Array.from(e.childNodes),a=q(l,s),u=J(e,s,i,o,a,r?.[0]??null),p=[];for(let m of u)m&&m.length>0&&p.push(...m);return p}function F(e){if(e==null)return[];if(!Array.isArray(e))return[e];let t=[];for(let n of e)Array.isArray(n)?t.push(...n):t.push(n);return t}function ke(e){return e==null?[]:e instanceof DocumentFragment?Array.from(e.childNodes):[e]}function J(e,t,n,o,r=[],s=null){if(!n.some(c=>c&&typeof c=="object"&&c.key!==void 0)){let c=Math.max(t.length,n.length);for(let f=0;f<c;f++){let y=f<t.length?t[f]:null,g=f<n.length?n[f]:null;if(g==null){if(y!=null){E(y);for(let h of r[f]??[])h.remove()}}else if(y==null){let h=R(g,o);h!=null&&e.appendChild(h)}else{let h=r[f]?.[0]??null;I(e,h,y,g,o)}}return[]}for(let c=0;c<t.length;c++){let f=t[c];if(!(f==null||typeof f=="boolean")&&oe(f)===void 0)for(let y of r[c]??[])y.remove()}let l=new Map,a=0;for(let c=0;c<t.length;c++){let f=oe(t[c]);f!==void 0&&l.set(f,{vnode:t[c],nodes:r[c]??[],index:a++})}let u=n.map(c=>oe(c)),p=new Set(u);for(let c of[...l.keys()])if(!p.has(c)){let f=l.get(c);E(f.vnode);for(let y of f.nodes)y?.remove();l.delete(c)}let m=new Array(n.length).fill(null),w=-1,d=s&&s.parentNode===e?s:e.firstChild;for(let c=0;c<n.length;c++){let f=u[c],y=n[c],g=f!==void 0?l.get(f):void 0,h=y&&typeof y=="object"&&y._placement==="remote";if(g)if(g.nodes.length>0){if(g.index<w)for(let A of g.nodes)e.insertBefore(A,d);w=Math.max(w,g.index),I(e,g.nodes[0],g.vnode,y,o),m[c]=y._childNodes??g.nodes.filter(A=>A.parentNode===e),d=m[c][m[c].length-1]?.nextSibling??null}else if(h)$(g.vnode,y,o),m[c]=[];else{let b=I(e,null,g.vnode,y,o);m[c]=ke(b);for(let x of m[c])e.insertBefore(x,d);d=m[c][m[c].length-1]?.nextSibling??null}else if(h)O(y,o),m[c]=[];else{let b=R(y,o);m[c]=ke(b);for(let x of m[c])e.insertBefore(x,d);d=m[c][m[c].length-1]?.nextSibling??null}}return m}function et(e,t){if(e===t)return!0;if(Array.isArray(e)&&Array.isArray(t)){if(e.length!==t.length)return!1;for(let n=0;n<e.length;n++)if(e[n]!==t[n])return!1;return!0}return e===t}function tt(e,t){if(e===t)return!0;if(!e||!t)return!1;let n=new Set([...Object.keys(e),...Object.keys(t)]);for(let o of n)if(o!=="key"){if(o==="children"){if(!et(e[o],t[o]))return!1}else if(e[o]!==t[o])return!1}return!0}var ie="http://www.w3.org/2000/svg",ae=new Set(["svg","path","circle","line","rect","text","g","polyline","polygon","ellipse","defs","use","clipPath","mask","linearGradient","radialGradient","stop","tspan"]);function Pe(e,t){return R(e,t)}function R(e,t){if(e==null||typeof e=="boolean")return null;if(typeof e=="string"||typeof e=="number")return document.createTextNode(String(e));if(Array.isArray(e))return rt(e,t);let n=e;if(n.type===W)return O(n,t),null;if(n.type===M){let i=document.createDocumentFragment(),l=n.props?.children==null?[]:Array.isArray(n.props.children)?n.props.children:[n.props.children];for(let a of l){let u=R(a,t);u!=null&&i.appendChild(u)}return n._childNodes=Array.from(i.childNodes),i}if(typeof n.type=="function")return ot(n.type,n.props,n,t);let o=n.type,r=ae.has(o)?document.createElementNS(ie,o):document.createElement(o);n.el=r;let s;for(let[i,l]of Object.entries(n.props??{}))i==="children"||i==="key"||i==="value"||i==="innerHTML"||Re(r,i,l);if("value"in(n.props??{})&&r instanceof HTMLSelectElement?s=n.props.value:"value"in(n.props??{})&&Re(r,"value",n.props.value),"innerHTML"in(n.props??{}))r.innerHTML=String(n.props.innerHTML??"");else{let i=le(n.props?.children);for(let l of i){let a=R(l,t);if(a!=null&&(r.appendChild(a),l&&typeof l=="object"&&typeof l.type=="function")){let u=l;u._parentNode||(u._parentNode=r,u._refNode=a)}}}return s!==void 0&&(r.value=String(s)),typeof n.props?.ref=="function"&&n.props.ref(r),r}function nt(e){let t=e.ui;t&&typeof t.render=="function"&&t.render(["_wf_root"])}function se(e,t,n,o){let r;if(H(e)){if(r=Te(e),!r)return ne(e,o).promise.then(()=>nt(o),()=>{}),null}else r=e;let s=r(t,o);if(typeof s!="function")throw new Error(`Component ${e.name||"anonymous"} must return a render function. Use (init_props, ctx) => (props) => VNode pattern.`);return n._render=s,s(t)}function ot(e,t,n,o){o.ui=o.ui??{},n._id||(n._id=D(),N.set(n._id,n));let r=Object.create(o);r.ui=Object.create(o.ui),r.ui._selfId=n._id,r.ui._selfVNode=n,n._ctxVersion=r.ui._ctxVersion??0;let s;try{s=se(e,t,n,r)}catch(l){let a=o.ui?._errorHandler;a?(a(l),s=null):(console.error(`[weifuwu] Component render error in <${e.name||"anonymous"}> (id: ${n._id??"?"}, phase: mount)`,l),s=null)}if(s==null)return n._child=null,null;n._child=s;let i=R(s,r);return n._refNode||(n._refNode=i),i}function rt(e,t){let n=document.createDocumentFragment();for(let o of e){let r=R(o,t);r!=null&&n.appendChild(r)}return n}function st(){let e=document.getElementById("__wf_portal");return e||(e=document.createElement("div"),e.id="__wf_portal",e.style.cssText="position:fixed;inset:0;pointer-events:none;z-index:9999",document.body.appendChild(e)),e}function O(e,t){let n=st(),o=document.createElement("div");o.style.pointerEvents="auto",n.appendChild(o),e._remoteEl=o;let r=F(e.props?.children);e._child=r;for(let s of r){let i=R(s,t);i!=null&&o.appendChild(i)}}function $(e,t,n){let o=e?._remoteEl;if(t._remoteEl=o,!o){O(t,n);return}let r=F(t.props?.children),s=e._child||[];t._child=r,G(s,r);let i=q(Array.from(o.childNodes),s);J(o,s,r,n,i,i[0]?.[0]??null)}function le(e){if(e==null)return[];if(!Array.isArray(e))return[e];let t=[];for(let n of e)Array.isArray(n)?t.push(...n):t.push(n);return t}function Re(e,t,n){if(t==="class"||t==="className")e instanceof SVGElement?e.setAttribute("class",String(n??"")):e.className=String(n??"");else if(t==="style"&&typeof n=="object"&&n!==null){let o=e.style;for(let r of Object.keys(n)){let s=n[r];s!=null&&(o[r]=typeof s=="number"?s+"px":String(s))}}else t.startsWith("on")&&typeof n=="function"?e.addEventListener(t.slice(2).toLowerCase(),n):t==="value"&&(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement)?e.value=String(n??""):n===!0?e.setAttribute(t,""):n!=null&&n!==!1&&e.setAttribute(t,String(n))}function it(e,t,n){e.innerHTML="";let o=R(t,n);o instanceof Node?e.appendChild(o):Array.isArray(o)&&o.forEach(r=>e.appendChild(r))}function ue(e){e.node=e.node?e.node.nextSibling:null}function at(e,t){e.node&&e.node.parentNode?e.node.parentNode.insertBefore(t,e.node):e.parent.appendChild(t)}function lt(e,t){e.node&&e.node.parentNode?(e.node.parentNode.replaceChild(t,e.node),ue(e)):e.parent.appendChild(t)}async function B(e,t,n){if(e==null||typeof e=="boolean")return null;if(typeof e=="string"||typeof e=="number"){let l=String(e);if(n.node&&n.node.nodeType===3)return n.node.textContent!==l&&(n.node.textContent=l),ue(n),n.node;let a=document.createTextNode(l);return at(n,a),a}if(Array.isArray(e)){let l=null;for(let a of e){let u=await B(a,t,n);u!=null&&!l&&(l=u)}return l}let o=e;if(o.type===W||o.type===M){let l=o.props?.children,a=l==null?[]:Array.isArray(l)?l:[l],u=null;for(let p of a){let m=await B(p,t,n);m!=null&&!u&&(u=m)}return u}if(typeof o.type=="function")return ut(o,t,n);let r=o.type,s=o.props??{},i;if(n.node&&n.node.nodeType===1&&n.node.tagName.toLowerCase()===r.toLowerCase()?(i=n.node,ue(n)):(i=ae.has(r)?document.createElementNS(ie,r):document.createElement(r),lt(n,i)),o.el=i,re(i,null,s),!("innerHTML"in s)){let l={parent:i,node:i.firstChild},a=le(s.children);for(let u of a){let p=await B(u,t,l);if(p!=null&&p.parentNode!==i&&i.appendChild(p),u&&typeof u=="object"&&typeof u.type=="function"){let m=u;m._parentNode||(m._parentNode=i,m._refNode=p)}}for(;l.node;){let u=l.node;l.node=u.nextSibling,u.parentNode?.removeChild(u)}}return"value"in s&&i instanceof HTMLSelectElement&&(i.value=String(s.value??"")),typeof s.ref=="function"&&s.ref(i),i}async function ut(e,t,n){t.ui=t.ui??{},e._id||(e._id=D(),N.set(e._id,e));let o=Object.create(t);o.ui=Object.create(t.ui),o.ui._selfId=e._id,o.ui._selfVNode=e,e._ctxVersion=o.ui._ctxVersion??0;let r=e.type,s;try{let l;H(r)?l=await ve(r,o):l=r;let a=l(e.props??{},o);if(typeof a!="function")throw new Error(`Component ${r.name||"anonymous"} must return a render function. Use (init_props, ctx) => (props) => VNode pattern.`);e._render=a,s=a(e.props??{})}catch(l){let a=t.ui?._errorHandler;a?(a(l),s=null):(console.error(`[weifuwu] Component hydration error in <${r.name||"anonymous"}> (id: ${e._id??"?"})`,l),s=null)}if(s==null)return e._child=null,null;e._child=s;let i=await B(s,o,n);return e._refNode||(e._refNode=i),i}async function ce(e,t,n){let o={parent:e,node:e.firstChild};for(await B(t,n,o);o.node;){let r=o.node;o.node=r.nextSibling,r.parentNode?.removeChild(r)}}function fe(e){let t=new WeakMap,n=new Set,o=s=>{if(s===null||typeof s!="object")return s;if(t.has(s))return t.get(s);let i=new Proxy(s,{set(l,a,u){if(Reflect.get(l,a)===u)return!0;Reflect.set(l,a,u),e();for(let m of n)m();return!0},get(l,a){let u=Reflect.get(l,a);return typeof u=="object"&&u!==null?o(u):u},deleteProperty(l,a){if(Reflect.has(l,a)){Reflect.deleteProperty(l,a),e();for(let u of n)u()}return!0}});return t.set(s,i),i},r=o({});return Object.defineProperty(r,"__watch",{value:s=>(n.add(s),()=>{n.delete(s)}),writable:!1,enumerable:!1}),r}function de(e,t,n){let o=new AbortController,r=n?.signal;r&&(r.aborted?o.abort():r.addEventListener("abort",()=>o.abort(),{once:!0}));let s=n?.traceId??mt(),i=n?.record!==!1,l=[],a=(async()=>{let u;try{u=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json","X-Trace-Id":s,Accept:"text/event-stream",...n?.headers},body:JSON.stringify(t),signal:o.signal})}catch(p){if(o.signal.aborted)return;n?.onError?.({code:"provider_error",message:p instanceof Error?p.message:String(p)});return}if(!u.ok){n?.onError?.({code:pt(u.status),message:`HTTP ${u.status} ${u.statusText}`});return}try{for await(let{name:p,data:m}of ft(u.body)){if(o.signal.aborted)return;dt(l,{name:p,data:m},i),ct(p,m,n??{})}}catch(p){if(o.signal.aborted)return;n?.onError?.({code:"provider_error",message:p instanceof Error?p.message:String(p)})}})();return{abort:()=>o.abort(),done:a,traceId:s,events:l}}function ct(e,t,n){switch(e){case"wf:token":return n.onToken?.(t.text);case"wf:tool_call":return n.onToolCall?.(t);case"wf:tool_result":return n.onToolResult?.(t);case"wf:tool_progress":return n.onToolProgress?.(t);case"wf:step":return n.onStep?.(t);case"wf:approval_request":return n.onApproval?.(t);case"wf:usage":return n.onUsage?.(t);case"wf:done":return n.onDone?.(t);case"wf:error":return n.onError?.(t);default:return n.onEvent?.(e,t)}}async function*ft(e){let t=e.getReader(),n=new TextDecoder,o="";try{for(;;){let{done:r,value:s}=await t.read();if(r)break;o+=n.decode(s,{stream:!0});let i=o.split(`
2
2
 
3
- `);o=i.pop()??"";for(let l of i){let a="message",u="";for(let m of l.split(`
4
- `))m.startsWith("event: ")?a=m.slice(7):m.startsWith("data: ")&&(u+=m.slice(6));if(u)try{yield{name:a,data:JSON.parse(u)}}catch{}}}}finally{t.releaseLock()}}function lt(e,t,n){n&&(e.length>=1e3&&e.shift(),e.push(t))}function ut(e){return e===401||e===403?"auth_failed":e===429?"rate_limited":e>=500?"provider_error":"invalid_request"}function ct(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():`trace-${Date.now()}-${Math.random().toString(36).slice(2,10)}`}function Se(e){return e.map(t=>({role:t.role,content:t.content}))}function ce(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():`msg-${Date.now()}-${Math.random().toString(36).slice(2,10)}`}function Ee(e,t,n){n.initialMessages?e.messages=structuredClone(n.initialMessages):e.messages===void 0&&(e.messages=[]),e.input===void 0&&(e.input=""),e.streaming===void 0&&(e.streaming=!1),e.error===void 0&&(e.error=null),e.usage===void 0&&(e.usage=null),e.step===void 0&&(e.step=null);let o=null;function r(){if(!e.streaming)return;let c=e.messages[e.messages.length-1];return c&&c.role==="assistant"&&c.status==="streaming"?c:void 0}function s(c,d,p){let g=r();switch(c){case"wf:token":g&&(g.content+=d.text);break;case"wf:tool_call":{g&&(g.toolCalls||(g.toolCalls=[]),g.toolCalls.push({call:d,status:"running"}));break}case"wf:tool_progress":{let h=d,w=g?.toolCalls?.find(v=>v.call.id===h.toolCallId);w&&(w.progress=h);break}case"wf:tool_result":{let h=d,w=g?.toolCalls?.find(v=>v.call.id===h.id);w&&(w.result=h,w.status=h.ok?"ok":"error");break}case"wf:approval_request":g&&(g.approval=d);break;case"wf:usage":g&&(g.usage=d);break;case"wf:step":e.step=d;break;case"wf:done":g&&(g.status="done",g.approval=void 0),e.streaming=!1,e.step=null;break;case"wf:error":g&&(g.status="error",g.error=d,g.approval=void 0),e.error=d,e.streaming=!1,e.step=null;break;default:p?.(c,d);break}}function i(){let c=n.body?n.body(e.messages):{messages:Se(e.messages)};o=t(n.url,c,{onToken:p=>s("wf:token",{text:p}),onToolCall:p=>s("wf:tool_call",p),onToolProgress:p=>s("wf:tool_progress",p),onToolResult:p=>s("wf:tool_result",p),onApproval:p=>s("wf:approval_request",p),onUsage:p=>s("wf:usage",p),onStep:p=>s("wf:step",p),onDone:p=>s("wf:done",p),onError:p=>s("wf:error",p),onEvent:(p,g)=>s(p,g,n.onEvent)},{signal:n.signal,headers:n.headers}),e.streaming=!0;let d=r();d&&o?.traceId&&(d.id=o.traceId)}function l(){if(e.streaming)return;let c=String(e.input??"").trim();c&&(e.input="",e.error=null,e.usage=null,e.step=null,e.messages.push({id:ce(),role:"user",content:c,status:"done"},{id:ce(),role:"assistant",content:"",status:"streaming",toolCalls:[]}),i())}function a(){o?.abort(),e.streaming=!1,e.step=null;let c=e.messages[e.messages.length-1];c&&c.role==="assistant"&&c.status==="streaming"&&(!c.content&&(!c.toolCalls||c.toolCalls.length===0)?e.messages.pop():c.status="done")}function u(){if(e.streaming)return;let c=-1;for(let d=e.messages.length-1;d>=0;d--)if(e.messages[d].role==="user"){c=d;break}c!==-1&&(e.messages.splice(c+1),e.error=null,e.usage=null,e.step=null,e.messages.push({id:ce(),role:"assistant",content:"",status:"streaming",toolCalls:[]}),i())}function m(){o?.abort(),e.messages=[],e.input="",e.streaming=!1,e.error=null,e.usage=null,e.step=null}async function y(c,d){let p=e.messages[e.messages.length-1],g=p?.role==="assistant"?p.approval:void 0;if(g&&(p.approval=void 0,!!n.approveUrl))try{await fetch(n.approveUrl,{method:"POST",headers:{"Content-Type":"application/json",...n.headers},body:JSON.stringify({id:g.id,decision:c,note:d}),signal:n.signal})}catch(h){if(n.signal?.aborted)return;e.error={code:"provider_error",message:h instanceof Error?h.message:String(h)}}}function f(){o?.abort(),o=null}return{send:l,stop:a,retry:u,clear:m,approve:y,dispose:f}}function Pe(e){let{ctx:t,renderByIds:n,getSelfId:o,dirtyBatch:r,dirtySet:s,mediaRegistry:i,popupTrackers:l,schedulePopupRecompute:a,ensurePopupListeners:u,isRendering:m}=e;return{_selfId:"_wf_root",_ctxVersion:0,_dirtySet:s,bumpCtxVersion:function(){this._ctxVersion++},render:function(f){if(!f||f.length===0){let c=o(this);if(c)f=[c];else return}n(f)},dirty:function(f){if(!m()){if(!f||f.length===0){let c=o(this);if(c)f=[c];else return}for(let c of f)c&&(r.add(c),s.add(c));this._dirtyScheduled||(this._dirtyScheduled=!0,queueMicrotask(()=>{this._dirtyScheduled=!1;let c=[...r];r.clear(),c.length>0&&n(c)}))}},$:function(){let f=this;if(!f._$cache){let c=o(this);f._$cache=le(()=>t.ui.dirty(c?[c]:void 0))}return f._$cache},useChat:function(f){let c=this.$(),d=Ee(c,ue,f);return Object.assign(c,{send:d.send,stop:d.stop,retry:d.retry,clear:d.clear,approve:d.approve,dispose:d.dispose}),c},useMedia:function(f,c){let p=`media:${o(this)}:${f}`;if(!i.has(p)){let g=window.matchMedia(f);c(g.matches);let h=w=>c(w.matches);g.addEventListener("change",h),i.set(p,{mql:g,handler:h})}},useBreakpoint:function(f,c){let d=typeof f=="function"?{mobile:"(max-width: 639px)",tablet:"(min-width: 640px) and (max-width: 1023px)",desktop:"(min-width: 1024px)"}:f,p=typeof f=="function"?f:c,h=`bp:${o(this)}`;function w(){for(let[v,C]of Object.entries(d))if(window.matchMedia(C).matches)return v;return Object.keys(d)[0]??""}if(!i.has(h)){p(w());let v=[];for(let C of Object.values(d)){let b=window.matchMedia(C),x=()=>p(w());b.addEventListener("change",x),v.push({mql:b,handler:x})}i.set(h,{mqls:v})}},usePopupPosition:function(f){let c=o(this),d={top:0,left:0,refresh:()=>{}};if(!c)return d;let p={pos:d,getEl:f.el,isOpen:f.isOpen,compute:f.compute};return l.set(c,p),u(),d.refresh=()=>{let g=p.getEl();g&&Object.assign(d,p.compute(g.getBoundingClientRect()))},d},useAsync:function(f){let c=o(this),d=le(()=>{t.ui&&t.ui.dirty(c?[c]:void 0)});d.loading=!0;let p=()=>{d.loading=!0,d.error=null,Promise.resolve().then(()=>f()).then(g=>{d.data=g,d.loading=!1}).catch(g=>{d.error=g,d.loading=!1})};return p(),d.reload=p,d},selfId:function(f){if(typeof f!="string"||!f)throw new Error(`[weifuwu] selfId requires a non-empty string, got ${typeof f}`);if(A.has(f))throw new Error(`[weifuwu] Duplicate component ID: "${f}". Each component must have a unique custom ID.`);let c=this._selfVNode;c&&(c._customId=f,A.set(f,c))}}}function ft(){let e=[],t={},n=null,o=null,r=null,s=!1,i=new Set,l=!1,a=new Map;function u(C){let b=a.get(C);b&&(b.mql&&b.handler&&b.mql.removeEventListener("change",b.handler),b.mqls?.forEach(({mql:x,handler:k})=>x.removeEventListener("change",k)),a.delete(C))}let m=new Map,y=!1,f=0;function c(){y||(y=!0,window.addEventListener("scroll",p,{capture:!0,passive:!0}),window.addEventListener("resize",p))}function d(){y&&(window.removeEventListener("scroll",p,{capture:!0}),window.removeEventListener("resize",p),y=!1)}function p(){f||(f=requestAnimationFrame(()=>{f=0;let C=[];for(let[b,x]of m){if(!x.isOpen())continue;let k=x.getEl();if(!k)continue;let R=x.compute(k.getBoundingClientRect());Object.assign(x.pos,R),C.push(b)}C.length>0&&t.ui.render(C)}))}function g(C){if(!s){s=!0;for(let b of C){let x=A.get(b);if(!x||!x._render)continue;t.ui._dirtySet?.delete(b);let k=x._child,R=x._render(x.props);if(x._child=R,k&&k._placement==="remote"||R&&R._placement==="remote"){k&&R?q(k,R,t):R?V(R,t):k&&_(k);continue}if(!x._parentNode&&x._refNode&&(x._parentNode=x._refNode.parentNode),x._parentNode){let E=M(x._parentNode,x._refNode??null,k,R,t);E&&E!==x._refNode?x._refNode=E:E||(x._refNode=null)}}s=!1,h()}}function h(){let C=t.ui;i.size>0&&!C._dirtyScheduled&&(C._dirtyScheduled=!0,queueMicrotask(()=>{C._dirtyScheduled=!1;let b=[...i];i.clear(),b.length>0&&g(b)}))}function w(C){return C?._selfId??t.ui?._selfId}let v={get ctx(){return t},use(C){return e.push(C),v},async mount(C,b,x){o=b;for(let T of e)t=await T(t);let k=typeof C=="string"?document.querySelector(C):C;if(!k)throw new Error(`mount target not found: ${C}`);n=k;let R=!!x?.hydrate;R||(n.innerHTML="");let E=new Map,Y=globalThis.__DATA__;if(Y&&typeof Y=="object")for(let[T,P]of Object.entries(Y))E.set(T,{value:P});if(t.data={async get(T,P){let O=E.get(T);if(O&&"value"in O)return O.value;if(O?.promise)return O.promise;if(!P)return;let me=Promise.resolve().then(()=>P()).then(ye=>(E.set(T,{value:ye}),ye));return E.set(T,{promise:me}),me},set(T,P){E.set(T,{value:P})},has(T){return E.has(T)}},Ce(T=>{for(let P of[...a.keys()])(P.startsWith(`media:${T}:`)||P===`bp:${T}`)&&u(P);m.delete(T)}),t.ui=Pe({ctx:t,renderByIds:g,getSelfId:w,dirtyBatch:i,dirtySet:new Set,mediaRegistry:a,popupTrackers:m,schedulePopupRecompute:p,ensurePopupListeners:c,destroyPopupListeners:d,isRendering:()=>s}),s=!0,r=dt(b,t),r._id="_wf_root",r._parentNode=n,r._refNode=R?n.firstChild:null,A.set("_wf_root",r),R)await ae(n,r,t);else{let T=Re(r,t);T instanceof Node&&n.appendChild(T)}r._refNode=n.firstChild,s=!1,h()},destroy(){d(),m.clear();for(let C of[...a.keys()])u(C);A.clear(),n&&(n.innerHTML=""),n=null,t={}}};return v}function dt(e,t){return{type:e,props:{},key:void 0}}function pt(e,t){if(!t||t==="/")return e||"/";let n=e.endsWith("/")?e.slice(0,-1):e,o=t.startsWith("/")?t:"/"+t;return n+o}function mt(e){let t=[],n=e.replace(/:(\w+)/g,(o,r)=>(t.push(r),"([^/]+)")).replace(/\*/g,".*");return{re:new RegExp(`^${n}$`),keys:t}}function fe(e,t="",n=[]){let o=[];for(let r of e){let s=pt(t,r.path),{re:i,keys:l}=mt(s),a=[...n,r];o.push({re:i,keys:l,def:r,chain:a}),r.children&&o.push(...fe(r.children,s,a))}return o}function Ne(e,t){let n=null;for(let o of t)e.match(o.re)&&(!n||o.chain.length>n.chain.length)&&(n=o);return n}function We(e,t){let n={},o=e.match(t.re);if(o)for(let r=0;r<t.keys.length;r++)n[t.keys[r]]=decodeURIComponent(o[r+1]);return n}function yt(e){let t=fe(e.routes),n=e.mode||"history";function o(){return n==="hash"?window.location.hash.replace(/^#/,"")||"/":window.location.pathname}function r(s){let i=Ne(s,t);if(i){let l=i.chain[i.chain.length-1];return{path:i.def.path,params:We(s,i),query:Object.fromEntries(new URLSearchParams(window.location.search)),chain:i.chain,title:l?.title??""}}return{path:s,params:{},query:Object.fromEntries(new URLSearchParams(window.location.search)),chain:e.notFound?[{component:e.notFound,title:"Not Found"}]:[],title:""}}return s=>{let i=r(o());s.route=i,i.title&&(document.title=i.title),s.app||(s.app={}),s.app.navigate=a=>{if(j(),n==="hash"){window.location.hash="#"+a;let u=r(a);s.route=u}else{window.history.pushState({},"",a);let u=r(a);s.route=u}s.route?.title&&(document.title=s.route.title),s.ui?.bumpCtxVersion?.(),s.ui?.render()};let l=()=>{j();let a=r(o());s.route=a,s.route?.title&&(document.title=s.route.title),s.ui?.bumpCtxVersion?.(),s.ui?.render()};return window.addEventListener("popstate",l),n==="hash"&&window.addEventListener("hashchange",l),s}}function gt(e,t){let n=t.route?._rvDepth??0;return()=>{let o=t.route;if(!o?.chain?.length||n>=o.chain.length)return null;let r=o.chain[n],s=r.layout??r.component;return s?(r.layout&&(o._rvDepth=n+1),{type:s,props:{},key:void 0}):null}}function L(e,t){return Object.assign(Object.create(e),t)}function ht(e={}){let t=e.url??"/ws",n=e.reconnectInterval??3e3,o=e.maxReconnect??10,r=e.pingInterval??3e4,s=e.pingTimeout??1e4;return i=>{let l=new Set,a=null,u=0,m=null,y=null,f=null,c=!1,d={isConnected:!1,onMessage:v=>(l.add(v),()=>{l.delete(v)}),send:v=>{a?.readyState===WebSocket.OPEN&&a.send(JSON.stringify(v))},_connect:p,close:()=>{c=!0,w(),a?.close(),a=null,d.isConnected=!1}};async function p(){if(!c)try{a=new WebSocket(t),a.onopen=()=>{d.isConnected=!0,u=0,g()},a.onmessage=v=>{try{let C=JSON.parse(v.data);for(let b of l)b(C)}catch{}h()},a.onclose=()=>{d.isConnected=!1,w(),!c&&u<o&&(u++,m=setTimeout(p,n*Math.min(u,5)))},a.onerror=()=>{a?.close()}}catch{c||(m=setTimeout(p,n))}}function g(){r<=0||(y=setInterval(()=>{a?.readyState===WebSocket.OPEN&&a.send(JSON.stringify({type:"ping"})),f=setTimeout(()=>{a?.close()},s)},r))}function h(){clearTimeout(f)}function w(){clearInterval(y),clearTimeout(f),clearTimeout(m)}return p(),L(i,{ws:d})}}function Ct(e){let t={baseURL:e?.baseURL??"",headers:{"Content-Type":"application/json",...e?.headers}},n=e?.onRequest,o=e?.onResponse,r=e?.timeout??0;async function s(i,l,a,u){let m=t.baseURL+l,y={method:i,headers:{...t.headers,...u?.headers}},f=e?.token?.();f&&!y.headers.Authorization&&(y.headers.Authorization=`Bearer ${f}`);let c=r>0,d=!!u?.signal,p=null,g=null;(c||d)&&(p=new AbortController,y.signal=p.signal,c&&(g=setTimeout(()=>p.abort(new Error("Request timed out")),r)),d&&u.signal.addEventListener("abort",()=>p.abort())),a!==void 0&&i!=="GET"&&i!=="HEAD"&&(y.body=JSON.stringify(a));let h={url:m,init:y};n&&(h=n(h));try{let w=await fetch(h.url,h.init);if(o)return o(w);if(!w.ok){let b=await w.text().catch(()=>"");throw new z(w.status,b||w.statusText)}let v=w.headers.get("content-length");if(w.status===204||v==="0")return;let C=(w.headers.get("content-type")||"").toLowerCase();return C.includes("application/json")||C.includes("json")?w.json():w.text()}finally{g&&clearTimeout(g)}}return i=>L(i,{api:{get:(a,u)=>s("GET",a,void 0,u),post:(a,u,m)=>s("POST",a,u,m),put:(a,u,m)=>s("PUT",a,u,m),patch:(a,u,m)=>s("PATCH",a,u,m),delete:(a,u)=>s("DELETE",a,void 0,u)}})}var z=class extends Error{status;body;constructor(t,n){super(`API Error ${t}: ${n}`),this.name="ApiError",this.status=t,this.body=n}};function xt(e){try{let t=e.split(".");if(t.length!==3)return null;let n=t[1].replace(/-/g,"+").replace(/_/g,"/");return JSON.parse(atob(n))}catch{return null}}function wt(e){let t=xt(e);return t?.exp?t.exp*1e3-3e4<Date.now():!0}function bt(e){let t=e?.storage??localStorage,n=e?.tokenKey??"weifuwu_token",o=e?.userKey??"weifuwu_user",r=e?.refreshTokenKey??"weifuwu_refresh",s=e?.refreshEndpoint??"/api/auth/refresh";return i=>{let l=t.getItem(n),a=t.getItem(o),u={token:l,user:a?JSON.parse(a):null,get isLoggedIn(){return this.token!==null},login(m,y,f){u.token=m,u.user=y,t.setItem(n,m),t.setItem(o,JSON.stringify(y)),f&&t.setItem(r,f)},logout(){u.token=null,u.user=null,t.removeItem(n),t.removeItem(o),t.removeItem(r)},setUser(m){u.user=m,t.setItem(o,JSON.stringify(m))},async refresh(){let m=t.getItem(r);if(!m)return!1;try{let y=await fetch(s,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:m})});if(!y.ok)return u.logout(),!1;let f=await y.json();return u.token=f.token,t.setItem(n,f.token),f.refreshToken&&t.setItem(r,f.refreshToken),!0}catch{return!1}}};return l&&wt(l)&&u.refresh().catch(()=>{}),L(i,{auth:u})}}function vt(e,t){let n=null;return o=>{if(n){let s=o.fallback;return typeof s=="function"?s({error:n}):s??null}t.ui._errorHandler=s=>{n=s,t.ui.render()};let r=o.children;try{return r??null}catch(s){n=s;let i=o.fallback;return typeof i=="function"?i({error:s}):i??null}}}var de={components:{Button:{loading:"\u52A0\u8F7D\u4E2D..."},FileUpload:{placeholder:"\u70B9\u51FB\u6216\u62D6\u62FD\u4E0A\u4F20\u6587\u4EF6",supportedFormats:"\u652F\u6301\u683C\u5F0F: ",maxSize:"\u6700\u5927 ",remove:"\u5220\u9664"},Pagination:{ariaLabel:"\u5206\u9875"},ProgressBar:{ariaLabel:"\u8FDB\u5EA6"},Switch:{ariaLabel:"\u5207\u6362"},Breadcrumb:{ariaLabel:"\u9762\u5305\u5C51"},Modal:{ariaLabel:"\u5F39\u7A97"},Confirm:{confirmText:"\u786E\u5B9A",cancelText:"\u53D6\u6D88"},Drawer:{ariaLabel:"\u4FA7\u8FB9\u9762\u677F"},DatePicker:{w0:"\u65E5",w1:"\u4E00",w2:"\u4E8C",w3:"\u4E09",w4:"\u56DB",w5:"\u4E94",w6:"\u516D",hour:"\u65F6",minute:"\u5206",time:"\u65F6\u95F4",confirm:"\u786E\u5B9A",cancel:"\u53D6\u6D88",placeholder:"\u9009\u62E9\u65E5\u671F"}}};var pe={components:{Button:{loading:"Loading..."},FileUpload:{placeholder:"Click or drag to upload",supportedFormats:"Supported formats: ",maxSize:"Max size: ",remove:"Remove"},Pagination:{ariaLabel:"Pagination"},ProgressBar:{ariaLabel:"Progress"},Switch:{ariaLabel:"Toggle"},Breadcrumb:{ariaLabel:"Breadcrumb"},Modal:{ariaLabel:"Dialog"},Confirm:{confirmText:"OK",cancelText:"Cancel"},Drawer:{ariaLabel:"Panel"},DatePicker:{w0:"Su",w1:"Mo",w2:"Tu",w3:"We",w4:"Th",w5:"Fr",w6:"Sa",hour:"Hour",minute:"Min",time:"Time",confirm:"OK",cancel:"Cancel",placeholder:"Pick a date"}}};var G={"zh-CN":de,"en-US":pe};function Me(e){if(G[e])return e;let t=e.split("-")[0];return Object.keys(G).find(o=>o.startsWith(t))??"zh-CN"}function Tt(e={}){let{locale:t="zh-CN",messages:n={},components:o={}}=e,r=Me(t),s=G[r],i=Le(s,n,o),l={locale:r,t:(a,u)=>i.messages?.[a]??u??a,setLocale:()=>{},components:i.components};return a=>(a.i18n=l,l.setLocale=u=>{let m=Me(u),y=G[m];y&&(i=Le(y,n,o),l.locale=m,l.components=i.components,a?.ui?.bumpCtxVersion?.(),a?.ui?.render())},a)}function Le(e,t,n){return{messages:{...e?.messages,...t},components:_t(e?.components??{},n)}}function _t(e,t){let n={...e};for(let o of Object.keys(t))typeof t[o]=="object"&&t[o]!==null&&typeof n[o]=="object"?n[o]={...n[o],...t[o]}:n[o]=t[o];return n}var J=0,Ve="",Oe="",Ie="",je="",Q=0;function Ue(){return typeof window<"u"&&typeof document<"u"}function At(){if(J++,J>1||!Ue())return;Q=window.scrollY;let e=document.body;Ve=e.style.overflow,Oe=e.style.position,Ie=e.style.top,je=e.style.width,e.style.overflow="hidden",(/iPhone|iPad|iPod/.test(navigator.platform)||/Mac/.test(navigator.platform)&&"ontouchend"in document)&&(e.style.position="fixed",e.style.top=`-${Q}px`,e.style.width="100%")}function kt(){if(J--,J>0||!Ue())return;let e=document.body;e.style.overflow=Ve,e.style.position=Oe,e.style.top=Ie,e.style.width=je,Q>0&&window.scrollTo(0,Q)}var Rt='a[href], button:not([disabled]), input:not([disabled]), textarea:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])';function St(e){let t=e.querySelectorAll(Rt);if(t.length===0)return()=>{};let n=t[0],o=t[t.length-1],r=i=>{i.key==="Tab"&&(i.shiftKey&&document.activeElement===n?(i.preventDefault(),o.focus()):!i.shiftKey&&document.activeElement===o&&(i.preventDefault(),n.focus()))},s=document.activeElement;return queueMicrotask(()=>{n.focus()}),e.addEventListener("keydown",r),()=>{e.removeEventListener("keydown",r),s?.focus()}}function Et(e,t,n=400){let o=!1,r=()=>{o||(o=!0,e.removeEventListener("animationend",r),clearTimeout(s),t())};e.addEventListener("animationend",r);let s=setTimeout(r,n)}function He(e,t="bottom",n=6,o=!0){switch(t){case"bottom":return{top:e.bottom+n,left:o?e.left+e.width/2:e.left};case"top":return{top:e.top-n,left:o?e.left+e.width/2:e.left};case"left":return{top:o?e.top+e.height/2:e.top,left:e.left-n};case"right":return{top:o?e.top+e.height/2:e.top,left:e.right+n}}}function Pt(e,t="bottom",n=6,o=!0){return He(e.getBoundingClientRect(),t,n,o)}export{z as ApiError,vt as ErrorBoundary,W as Fragment,N as Portal,gt as RouteView,ue as aiStream,Et as animateOut,Ct as api,qe as asyncComponent,bt as auth,_ as callRefCleanup,j as clearAsyncComponentCache,Pt as computeFixedPos,He as computeFixedPosRect,ft as createApp,Be as createPortal,pe as enUS,L as extendCtx,$e as h,ae as hydrateVNode,Tt as i18n,I as isAsyncComponent,X as jsx,Fe as jsxDEV,De as jsxs,At as lockScroll,nt as mountVNode,M as patchValue,yt as router,Se as toChatMessages,St as trapFocus,kt as unlockScroll,ht as ws,de as zhCN};
3
+ `);o=i.pop()??"";for(let l of i){let a="message",u="";for(let p of l.split(`
4
+ `))p.startsWith("event: ")?a=p.slice(7):p.startsWith("data: ")&&(u+=p.slice(6));if(u)try{yield{name:a,data:JSON.parse(u)}}catch{}}}}finally{t.releaseLock()}}function dt(e,t,n){n&&(e.length>=1e3&&e.shift(),e.push(t))}function pt(e){return e===401||e===403?"auth_failed":e===429?"rate_limited":e>=500?"provider_error":"invalid_request"}function mt(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():`trace-${Date.now()}-${Math.random().toString(36).slice(2,10)}`}function We(e){return e.map(t=>({role:t.role,content:t.content}))}function pe(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():`msg-${Date.now()}-${Math.random().toString(36).slice(2,10)}`}function Me(e,t,n){n.initialMessages?e.messages=structuredClone(n.initialMessages):e.messages===void 0&&(e.messages=[]),e.input===void 0&&(e.input=""),e.streaming===void 0&&(e.streaming=!1),e.error===void 0&&(e.error=null),e.usage===void 0&&(e.usage=null),e.step===void 0&&(e.step=null);let o=null;function r(){if(!e.streaming)return;let d=e.messages[e.messages.length-1];return d&&d.role==="assistant"&&d.status==="streaming"?d:void 0}function s(d,c,f){let y=r();switch(d){case"wf:token":y&&(y.content+=c.text);break;case"wf:tool_call":{y&&(y.toolCalls||(y.toolCalls=[]),y.toolCalls.push({call:c,status:"running"}));break}case"wf:tool_progress":{let g=c,h=y?.toolCalls?.find(b=>b.call.id===g.toolCallId);h&&(h.progress=g);break}case"wf:tool_result":{let g=c,h=y?.toolCalls?.find(b=>b.call.id===g.id);h&&(h.result=g,h.status=g.ok?"ok":"error");break}case"wf:approval_request":y&&(y.approval=c);break;case"wf:usage":y&&(y.usage=c);break;case"wf:step":e.step=c;break;case"wf:done":y&&(y.status="done",y.approval=void 0),e.streaming=!1,e.step=null;break;case"wf:error":y&&(y.status="error",y.error=c,y.approval=void 0),e.error=c,e.streaming=!1,e.step=null;break;default:f?.(d,c);break}}function i(){let d=n.body?n.body(e.messages):{messages:We(e.messages)};o=t(n.url,d,{onToken:f=>s("wf:token",{text:f}),onToolCall:f=>s("wf:tool_call",f),onToolProgress:f=>s("wf:tool_progress",f),onToolResult:f=>s("wf:tool_result",f),onApproval:f=>s("wf:approval_request",f),onUsage:f=>s("wf:usage",f),onStep:f=>s("wf:step",f),onDone:f=>s("wf:done",f),onError:f=>s("wf:error",f),onEvent:(f,y)=>s(f,y,n.onEvent)},{signal:n.signal,headers:n.headers}),e.streaming=!0;let c=r();c&&o?.traceId&&(c.id=o.traceId)}function l(){if(e.streaming)return;let d=String(e.input??"").trim();d&&(e.input="",e.error=null,e.usage=null,e.step=null,e.messages.push({id:pe(),role:"user",content:d,status:"done"},{id:pe(),role:"assistant",content:"",status:"streaming",toolCalls:[]}),i())}function a(){o?.abort(),e.streaming=!1,e.step=null;let d=e.messages[e.messages.length-1];d&&d.role==="assistant"&&d.status==="streaming"&&(!d.content&&(!d.toolCalls||d.toolCalls.length===0)?e.messages.pop():d.status="done")}function u(){if(e.streaming)return;let d=-1;for(let c=e.messages.length-1;c>=0;c--)if(e.messages[c].role==="user"){d=c;break}d!==-1&&(e.messages.splice(d+1),e.error=null,e.usage=null,e.step=null,e.messages.push({id:pe(),role:"assistant",content:"",status:"streaming",toolCalls:[]}),i())}function p(){o?.abort(),e.messages=[],e.input="",e.streaming=!1,e.error=null,e.usage=null,e.step=null}async function m(d,c){let f=e.messages[e.messages.length-1],y=f?.role==="assistant"?f.approval:void 0;if(y&&(f.approval=void 0,!!n.approveUrl))try{await fetch(n.approveUrl,{method:"POST",headers:{"Content-Type":"application/json",...n.headers},body:JSON.stringify({id:y.id,decision:d,note:c}),signal:n.signal})}catch(g){if(n.signal?.aborted)return;e.error={code:"provider_error",message:g instanceof Error?g.message:String(g)}}}function w(){o?.abort(),o=null}return{send:l,stop:a,retry:u,clear:p,approve:m,dispose:w}}function Le(e,t="bottom",n=6,o=!0){switch(t){case"bottom":return{top:e.bottom+n,left:o?e.left+e.width/2:e.left};case"top":return{top:e.top-n,left:o?e.left+e.width/2:e.left};case"left":return{top:o?e.top+e.height/2:e.top,left:e.left-n};case"right":return{top:o?e.top+e.height/2:e.top,left:e.right+n}}}function yt(e,t="bottom",n=6,o=!0){return Le(e.getBoundingClientRect(),t,n,o)}function Q(e,t,n=8){if(!t)return e;let o=t.getBoundingClientRect();if(o.width===0&&o.height===0)return e;let r=Number.parseFloat(t.style.top)||o.top,s=Number.parseFloat(t.style.left)||o.left,i=e.top-r,l=e.left-s,a={top:o.top+i,bottom:o.bottom+i,left:o.left+l,right:o.right+l},u=window.innerWidth,p=window.innerHeight,m=e.top,w=e.left;return a.bottom>p-n&&(m=Math.max(n,m-(a.bottom-(p-n)))),a.top<n&&(m=Math.max(n,m+(n-a.top))),a.right>u-n&&(w=Math.max(n,w-(a.right-(u-n)))),a.left<n&&(w=Math.max(n,w+(n-a.left))),{top:m,left:w,width:e.width}}function Ie(e){let{ctx:t,renderByIds:n,getSelfId:o,dirtyBatch:r,dirtySet:s,mediaRegistry:i,popupTrackers:l,scrollTrackers:a,schedulePopupRecompute:u,ensurePopupListeners:p,isRendering:m}=e;return{_selfId:"_wf_root",_ctxVersion:0,_dirtySet:s,bumpCtxVersion:function(){this._ctxVersion++},render:function(d){if(!d||d.length===0){let c=o(this);if(c)d=[c];else return}n(d)},dirty:function(d){if(!m()){if(!d||d.length===0){let c=o(this);if(c)d=[c];else return}for(let c of d)c&&(r.add(c),s.add(c));this._dirtyScheduled||(this._dirtyScheduled=!0,queueMicrotask(()=>{this._dirtyScheduled=!1;let c=[...r];r.clear(),c.length>0&&n(c)}))}},$:function(){let d=this;if(!d._$cache){let c=o(this);d._$cache=fe(()=>t.ui.dirty(c?[c]:void 0))}return d._$cache},useChat:function(d){let c=this.$(),f=Me(c,de,d);return Object.assign(c,{send:f.send,stop:f.stop,retry:f.retry,clear:f.clear,approve:f.approve,dispose:f.dispose}),c},useMedia:function(d,c){let y=`media:${o(this)}:${d}`;if(!i.has(y)){let g=window.matchMedia(d);c(g.matches);let h=b=>c(b.matches);g.addEventListener("change",h),i.set(y,{mql:g,handler:h})}},useBreakpoint:function(d,c){let f=typeof d=="function"?{mobile:"(max-width: 639px)",tablet:"(min-width: 640px) and (max-width: 1023px)",desktop:"(min-width: 1024px)"}:d,y=typeof d=="function"?d:c,h=`bp:${o(this)}`;function b(){for(let[A,x]of Object.entries(f))if(window.matchMedia(x).matches)return A;return Object.keys(f)[0]??""}if(!i.has(h)){y(b());let A=[];for(let x of Object.values(f)){let v=window.matchMedia(x),C=()=>y(b());v.addEventListener("change",C),A.push({mql:v,handler:C})}i.set(h,{mqls:A})}},usePopupPosition:function(d){let c=o(this),f={top:0,left:0,refresh:()=>{}};if(!c)return f;let y={pos:f,getEl:d.el,isOpen:d.isOpen,compute:d.compute,panel:d.panel,margin:d.margin??8};return l.set(c,y),p(),f.refresh=()=>{let g=y.getEl();if(!g)return;let h=y.compute(g.getBoundingClientRect());Object.assign(f,Q(h,y.panel?.(),y.margin))},f},useInView:function(d){let c=o(this),f={isIn:!1,ready:!1,observe:A,refresh:x,disconnect:v},y=null,g=null,h=()=>{t.ui&&t.ui.dirty(c?[c]:void 0)};function b(){if(g?.disconnect(),g=null,!y)return;let C=typeof d.rootMargin=="function"?d.rootMargin():d.rootMargin,T=typeof d.threshold=="function"?d.threshold():d.threshold;g=new IntersectionObserver(S=>{let k=S[S.length-1];if(!k)return;let L=k.isIntersecting,_=L!==f.isIn,P=!f.ready;f.isIn=L,f.ready=!0,d.onChange?.(k,L),(_||P)&&h()},{root:d.root?d.root():null,rootMargin:C??"0px",threshold:T??0}),g.observe(y)}function A(C){y=C,C?b():(g?.disconnect(),g=null,f.isIn=!1)}function x(){b()}function v(){g?.disconnect(),g=null}return f},useScrollPosition:function(d){let c=o(this),f={y:0,refresh(){let g=y.getScroller();f.y=g instanceof Window?document.scrollingElement?.scrollTop??g.scrollY??0:g.scrollTop??0}},y={handle:f,getScroller:d.getScroller??(()=>window)};return c?(a.set(c,y),p(),f.refresh(),f):(f.refresh(),f)},useAsync:function(d){let c=o(this),f=fe(()=>{t.ui&&t.ui.dirty(c?[c]:void 0)});f.loading=!0;let y=()=>{f.loading=!0,f.error=null,Promise.resolve().then(()=>d()).then(g=>{f.data=g,f.loading=!1}).catch(g=>{f.error=g,f.loading=!1})};return y(),f.reload=y,f},selfId:function(d){if(typeof d!="string"||!d)throw new Error(`[weifuwu] selfId requires a non-empty string, got ${typeof d}`);if(N.has(d))throw new Error(`[weifuwu] Duplicate component ID: "${d}". Each component must have a unique custom ID.`);let c=this._selfVNode;c&&(c._customId=d,N.set(d,c))}}}function gt(){let e=[],t={},n=null,o=null,r=null,s=!1,i=new Set,l=!1,a=new Map;function u(x){let v=a.get(x);v&&(v.mql&&v.handler&&v.mql.removeEventListener("change",v.handler),v.mqls?.forEach(({mql:C,handler:T})=>C.removeEventListener("change",T)),a.delete(x))}let p=new Map,m=!1,w=0;function d(){m||(m=!0,window.addEventListener("scroll",y,{capture:!0,passive:!0}),window.addEventListener("resize",y))}function c(){m&&(window.removeEventListener("scroll",y,{capture:!0}),window.removeEventListener("resize",y),m=!1)}let f=new Map;function y(){w||(w=requestAnimationFrame(()=>{w=0;let x=[];for(let[v,C]of p){if(!C.isOpen())continue;let T=C.getEl();if(!T)continue;let S=C.compute(T.getBoundingClientRect());Object.assign(C.pos,Q(S,C.panel?.(),C.margin)),x.push(v)}for(let[v,C]of f){let T=C.getScroller(),S=T instanceof Window?document.scrollingElement?.scrollTop??T.scrollY??0:T.scrollTop??0;S!==C.handle.y&&(C.handle.y=S,x.push(v))}x.length>0&&t.ui.render(x)}))}function g(x){if(!s){s=!0;for(let v of x){let C=N.get(v);if(!C||!C._render)continue;t.ui._dirtySet?.delete(v);let T=C._child,S=C._render(C.props);if(C._child=S,T&&T._placement==="remote"||S&&S._placement==="remote"){T&&S?$(T,S,t):S?O(S,t):T&&E(T);continue}if(!C._parentNode&&C._refNode&&(C._parentNode=C._refNode.parentNode),C._parentNode){let k=I(C._parentNode,C._refNode??null,T,S,t);k&&k!==C._refNode?C._refNode=k:k||(C._refNode=null)}}s=!1,h()}}function h(){let x=t.ui;i.size>0&&!x._dirtyScheduled&&(x._dirtyScheduled=!0,queueMicrotask(()=>{x._dirtyScheduled=!1;let v=[...i];i.clear(),v.length>0&&g(v)}))}function b(x){return x?._selfId??t.ui?._selfId}let A={get ctx(){return t},use(x){return e.push(x),A},async mount(x,v,C){o=v;for(let _ of e)t=await _(t);let T=typeof x=="string"?document.querySelector(x):x;if(!T)throw new Error(`mount target not found: ${x}`);n=T;let S=!!C?.hydrate;S||(n.innerHTML="");let k=new Map,L=globalThis.__DATA__;if(L&&typeof L=="object")for(let[_,P]of Object.entries(L))k.set(_,{value:P});if(t.data={async get(_,P){let U=k.get(_);if(U&&"value"in U)return U.value;if(U?.promise)return U.promise;if(!P)return;let he=Promise.resolve().then(()=>P()).then(Ce=>(k.set(_,{value:Ce}),Ce));return k.set(_,{promise:he}),he},set(_,P){k.set(_,{value:P})},has(_){return k.has(_)}},be(_=>{for(let P of[...a.keys()])(P.startsWith(`media:${_}:`)||P===`bp:${_}`)&&u(P);p.delete(_),f.delete(_)}),t.ui=Ie({ctx:t,renderByIds:g,getSelfId:b,dirtyBatch:i,dirtySet:new Set,mediaRegistry:a,popupTrackers:p,scrollTrackers:f,schedulePopupRecompute:y,ensurePopupListeners:d,destroyPopupListeners:c,isRendering:()=>s}),s=!0,r=ht(v,t),r._id="_wf_root",r._parentNode=n,r._refNode=S?n.firstChild:null,N.set("_wf_root",r),S)await ce(n,r,t);else{let _=Pe(r,t);_ instanceof Node&&n.appendChild(_)}r._refNode=n.firstChild,s=!1,h()},destroy(){c(),p.clear(),f.clear();for(let x of[...a.keys()])u(x);N.clear(),n&&(n.innerHTML=""),n=null,t={}}};return A}function ht(e,t){return{type:e,props:{},key:void 0}}function Ct(e,t){if(!t||t==="/")return e||"/";let n=e.endsWith("/")?e.slice(0,-1):e,o=t.startsWith("/")?t:"/"+t;return n+o}function xt(e){let t=[],n=e.replace(/:(\w+)/g,(o,r)=>(t.push(r),"([^/]+)")).replace(/\*/g,".*");return{re:new RegExp(`^${n}$`),keys:t}}function me(e,t="",n=[]){let o=[];for(let r of e){let s=Ct(t,r.path),{re:i,keys:l}=xt(s),a=[...n,r];o.push({re:i,keys:l,def:r,chain:a}),r.children&&o.push(...me(r.children,s,a))}return o}function Ve(e,t){let n=null;for(let o of t)e.match(o.re)&&(!n||o.chain.length>n.chain.length)&&(n=o);return n}function Oe(e,t){let n={},o=e.match(t.re);if(o)for(let r=0;r<t.keys.length;r++)n[t.keys[r]]=decodeURIComponent(o[r+1]);return n}function wt(e){let t=me(e.routes),n=e.mode||"history";function o(){return n==="hash"?window.location.hash.replace(/^#/,"")||"/":window.location.pathname}function r(s){let i=Ve(s,t);if(i){let l=i.chain[i.chain.length-1];return{path:i.def.path,params:Oe(s,i),query:Object.fromEntries(new URLSearchParams(window.location.search)),chain:i.chain,title:l?.title??""}}return{path:s,params:{},query:Object.fromEntries(new URLSearchParams(window.location.search)),chain:e.notFound?[{component:e.notFound,title:"Not Found"}]:[],title:""}}return s=>{let i=r(o());s.route=i,i.title&&(document.title=i.title),s.app||(s.app={}),s.app.navigate=a=>{if(j(),n==="hash"){window.location.hash="#"+a;let u=r(a);s.route=u}else{window.history.pushState({},"",a);let u=r(a);s.route=u}s.route?.title&&(document.title=s.route.title),s.ui?.bumpCtxVersion?.(),s.ui?.render()};let l=()=>{j();let a=r(o());s.route=a,s.route?.title&&(document.title=s.route.title),s.ui?.bumpCtxVersion?.(),s.ui?.render()};return window.addEventListener("popstate",l),n==="hash"&&window.addEventListener("hashchange",l),s}}function bt(e,t){let n=t.route?._rvDepth??0;return()=>{let o=t.route;if(!o?.chain?.length||n>=o.chain.length)return null;let r=o.chain[n],s=r.layout??r.component;return s?(r.layout&&(o._rvDepth=n+1),{type:s,props:{},key:void 0}):null}}function V(e,t){return Object.assign(Object.create(e),t)}function vt(e={}){let t=e.url??"/ws",n=e.reconnectInterval??3e3,o=e.maxReconnect??10,r=e.pingInterval??3e4,s=e.pingTimeout??1e4;return i=>{let l=new Set,a=null,u=0,p=null,m=null,w=null,d=!1,c={isConnected:!1,onMessage:b=>(l.add(b),()=>{l.delete(b)}),send:b=>{a?.readyState===WebSocket.OPEN&&a.send(JSON.stringify(b))},_connect:f,close:()=>{d=!0,h(),a?.close(),a=null,c.isConnected=!1}};async function f(){if(!d)try{a=new WebSocket(t),a.onopen=()=>{c.isConnected=!0,u=0,y()},a.onmessage=b=>{try{let A=JSON.parse(b.data);for(let x of l)x(A)}catch{}g()},a.onclose=()=>{c.isConnected=!1,h(),!d&&u<o&&(u++,p=setTimeout(f,n*Math.min(u,5)))},a.onerror=()=>{a?.close()}}catch{d||(p=setTimeout(f,n))}}function y(){r<=0||(m=setInterval(()=>{a?.readyState===WebSocket.OPEN&&a.send(JSON.stringify({type:"ping"})),w=setTimeout(()=>{a?.close()},s)},r))}function g(){clearTimeout(w)}function h(){clearInterval(m),clearTimeout(w),clearTimeout(p)}return f(),V(i,{ws:c})}}function Tt(e){let t={baseURL:e?.baseURL??"",headers:{"Content-Type":"application/json",...e?.headers}},n=e?.onRequest,o=e?.onResponse,r=e?.timeout??0;async function s(i,l,a,u){let p=t.baseURL+l,m={method:i,headers:{...t.headers,...u?.headers}},w=e?.token?.();w&&!m.headers.Authorization&&(m.headers.Authorization=`Bearer ${w}`);let d=r>0,c=!!u?.signal,f=null,y=null;(d||c)&&(f=new AbortController,m.signal=f.signal,d&&(y=setTimeout(()=>f.abort(new Error("Request timed out")),r)),c&&u.signal.addEventListener("abort",()=>f.abort())),a!==void 0&&i!=="GET"&&i!=="HEAD"&&(m.body=JSON.stringify(a));let g={url:p,init:m};n&&(g=n(g));try{let h=await fetch(g.url,g.init);if(o)return o(h);if(!h.ok){let x=await h.text().catch(()=>"");throw new Y(h.status,x||h.statusText)}let b=h.headers.get("content-length");if(h.status===204||b==="0")return;let A=(h.headers.get("content-type")||"").toLowerCase();return A.includes("application/json")||A.includes("json")?h.json():h.text()}finally{y&&clearTimeout(y)}}return i=>V(i,{api:{get:(a,u)=>s("GET",a,void 0,u),post:(a,u,p)=>s("POST",a,u,p),put:(a,u,p)=>s("PUT",a,u,p),patch:(a,u,p)=>s("PATCH",a,u,p),delete:(a,u)=>s("DELETE",a,void 0,u)}})}var Y=class extends Error{status;body;constructor(t,n){super(`API Error ${t}: ${n}`),this.name="ApiError",this.status=t,this.body=n}};function _t(e){try{let t=e.split(".");if(t.length!==3)return null;let n=t[1].replace(/-/g,"+").replace(/_/g,"/");return JSON.parse(atob(n))}catch{return null}}function At(e){let t=_t(e);return t?.exp?t.exp*1e3-3e4<Date.now():!0}function St(e){let t=e?.storage??localStorage,n=e?.tokenKey??"weifuwu_token",o=e?.userKey??"weifuwu_user",r=e?.refreshTokenKey??"weifuwu_refresh",s=e?.refreshEndpoint??"/api/auth/refresh";return i=>{let l=t.getItem(n),a=t.getItem(o),u={token:l,user:a?JSON.parse(a):null,get isLoggedIn(){return this.token!==null},login(p,m,w){u.token=p,u.user=m,t.setItem(n,p),t.setItem(o,JSON.stringify(m)),w&&t.setItem(r,w)},logout(){u.token=null,u.user=null,t.removeItem(n),t.removeItem(o),t.removeItem(r)},setUser(p){u.user=p,t.setItem(o,JSON.stringify(p))},async refresh(){let p=t.getItem(r);if(!p)return!1;try{let m=await fetch(s,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:p})});if(!m.ok)return u.logout(),!1;let w=await m.json();return u.token=w.token,t.setItem(n,w.token),w.refreshToken&&t.setItem(r,w.refreshToken),!0}catch{return!1}}};return l&&At(l)&&u.refresh().catch(()=>{}),V(i,{auth:u})}}function Et(e,t){let n=null;return o=>{if(n){let s=o.fallback;return typeof s=="function"?s({error:n}):s??null}t.ui._errorHandler=s=>{n=s,t.ui.render()};let r=o.children;try{return r??null}catch(s){n=s;let i=o.fallback;return typeof i=="function"?i({error:s}):i??null}}}var ye={components:{Button:{loading:"\u52A0\u8F7D\u4E2D..."},FileUpload:{placeholder:"\u70B9\u51FB\u6216\u62D6\u62FD\u4E0A\u4F20\u6587\u4EF6",supportedFormats:"\u652F\u6301\u683C\u5F0F: ",maxSize:"\u6700\u5927 ",remove:"\u5220\u9664"},Pagination:{ariaLabel:"\u5206\u9875"},ProgressBar:{ariaLabel:"\u8FDB\u5EA6"},Switch:{ariaLabel:"\u5207\u6362"},Breadcrumb:{ariaLabel:"\u9762\u5305\u5C51"},Modal:{ariaLabel:"\u5F39\u7A97"},Confirm:{confirmText:"\u786E\u5B9A",cancelText:"\u53D6\u6D88"},Drawer:{ariaLabel:"\u4FA7\u8FB9\u9762\u677F"},DatePicker:{w0:"\u65E5",w1:"\u4E00",w2:"\u4E8C",w3:"\u4E09",w4:"\u56DB",w5:"\u4E94",w6:"\u516D",hour:"\u65F6",minute:"\u5206",time:"\u65F6\u95F4",confirm:"\u786E\u5B9A",cancel:"\u53D6\u6D88",placeholder:"\u9009\u62E9\u65E5\u671F"}}};var ge={components:{Button:{loading:"Loading..."},FileUpload:{placeholder:"Click or drag to upload",supportedFormats:"Supported formats: ",maxSize:"Max size: ",remove:"Remove"},Pagination:{ariaLabel:"Pagination"},ProgressBar:{ariaLabel:"Progress"},Switch:{ariaLabel:"Toggle"},Breadcrumb:{ariaLabel:"Breadcrumb"},Modal:{ariaLabel:"Dialog"},Confirm:{confirmText:"OK",cancelText:"Cancel"},Drawer:{ariaLabel:"Panel"},DatePicker:{w0:"Su",w1:"Mo",w2:"Tu",w3:"We",w4:"Th",w5:"Fr",w6:"Sa",hour:"Hour",minute:"Min",time:"Time",confirm:"OK",cancel:"Cancel",placeholder:"Pick a date"}}};var X={"zh-CN":ye,"en-US":ge};function Ue(e){if(X[e])return e;let t=e.split("-")[0];return Object.keys(X).find(o=>o.startsWith(t))??"zh-CN"}function Nt(e={}){let{locale:t="zh-CN",messages:n={},components:o={}}=e,r=Ue(t),s=X[r],i=He(s,n,o),l={locale:r,t:(a,u)=>i.messages?.[a]??u??a,setLocale:()=>{},components:i.components};return a=>(a.i18n=l,l.setLocale=u=>{let p=Ue(u),m=X[p];m&&(i=He(m,n,o),l.locale=p,l.components=i.components,a?.ui?.bumpCtxVersion?.(),a?.ui?.render())},a)}function He(e,t,n){return{messages:{...e?.messages,...t},components:kt(e?.components??{},n)}}function kt(e,t){let n={...e};for(let o of Object.keys(t))typeof t[o]=="object"&&t[o]!==null&&typeof n[o]=="object"?n[o]={...n[o],...t[o]}:n[o]=t[o];return n}var Z=0,je="",De="",qe="",Fe="",ee=0;function $e(){return typeof window<"u"&&typeof document<"u"}function Rt(){if(Z++,Z>1||!$e())return;ee=window.scrollY;let e=document.body;je=e.style.overflow,De=e.style.position,qe=e.style.top,Fe=e.style.width,e.style.overflow="hidden",(/iPhone|iPad|iPod/.test(navigator.platform)||/Mac/.test(navigator.platform)&&"ontouchend"in document)&&(e.style.position="fixed",e.style.top=`-${ee}px`,e.style.width="100%")}function Pt(){if(Z--,Z>0||!$e())return;let e=document.body;e.style.overflow=je,e.style.position=De,e.style.top=qe,e.style.width=Fe,ee>0&&window.scrollTo(0,ee)}var Wt='a[href], button:not([disabled]), input:not([disabled]), textarea:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])';function Mt(e){let t=e.querySelectorAll(Wt);if(t.length===0)return()=>{};let n=t[0],o=t[t.length-1],r=i=>{i.key==="Tab"&&(i.shiftKey&&document.activeElement===n?(i.preventDefault(),o.focus()):!i.shiftKey&&document.activeElement===o&&(i.preventDefault(),n.focus()))},s=document.activeElement;return queueMicrotask(()=>{n.focus()}),e.addEventListener("keydown",r),()=>{e.removeEventListener("keydown",r),s?.focus()}}function Lt(e,t,n=400){let o=!1,r=()=>{o||(o=!0,e.removeEventListener("animationend",r),clearTimeout(s),t())};e.addEventListener("animationend",r);let s=setTimeout(r,n)}export{Y as ApiError,Et as ErrorBoundary,M as Fragment,W as Portal,bt as RouteView,de as aiStream,Lt as animateOut,Tt as api,Be as asyncComponent,St as auth,E as callRefCleanup,j as clearAsyncComponentCache,yt as computeFixedPos,Le as computeFixedPosRect,gt as createApp,Je as createPortal,ge as enUS,V as extendCtx,Ge as h,ce as hydrateVNode,Nt as i18n,H as isAsyncComponent,te as jsx,ze as jsxDEV,Ke as jsxs,Rt as lockScroll,it as mountVNode,I as patchValue,wt as router,We as toChatMessages,Mt as trapFocus,Pt as unlockScroll,vt as ws,ye as zhCN};
@@ -29,3 +29,25 @@ export declare function computeFixedPosRect(rect: DOMRect, placement?: Placement
29
29
  * @param center 是否居中于触发元素,默认 true
30
30
  */
31
31
  export declare function computeFixedPos(el: HTMLElement, placement?: Placement, gap?: number, center?: boolean): FixedPos;
32
+ /**
33
+ * 弹层视口夹紧——fixed 定位弹层超高/超宽时,超出视口部分不可交互。
34
+ *
35
+ * 实测场景:DatePicker datetime/range 面板高约 416px,锚点在页面中部时
36
+ * bottom 超出视口 → 底部“确定/取消”按钮落在窗口外,真实点击不可达。
37
+ *
38
+ * 以面板真实渲染矩形(含 transform 居中偏移)为基准平移坐标,
39
+ * 保证:top/left 不动时面板整体回到视口内(保留 margin 安全边距)。
40
+ *
41
+ * @param pos 计算出的坐标(top/left,可选 width)
42
+ * @param panel 已渲染的面板元素;null/undefined 时不夹紧(调用方未提供)
43
+ * @param margin 视口边缘安全边距(px),默认 8
44
+ */
45
+ export declare function clampToViewport(pos: {
46
+ top: number;
47
+ left: number;
48
+ width?: number;
49
+ }, panel: HTMLElement | null | undefined, margin?: number): {
50
+ top: number;
51
+ left: number;
52
+ width?: number;
53
+ };