weifuwu 0.74.0 → 0.76.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 (86) hide show
  1. package/README.md +20 -20
  2. package/dist/ai/types.d.ts +3 -1
  3. package/dist/components/AiChat/AiChat.d.ts +5 -1
  4. package/dist/components/ApprovalCard/ApprovalCard.d.ts +5 -2
  5. package/dist/components/Button/Button.d.ts +2 -0
  6. package/dist/components/CitationCard/CitationCard.d.ts +38 -0
  7. package/dist/components/Command/Command.d.ts +1 -1
  8. package/dist/components/JsonSchemaForm/JsonSchemaForm.d.ts +48 -0
  9. package/dist/components/ReasoningBlock/ReasoningBlock.d.ts +25 -0
  10. package/dist/components/Select/Select.d.ts +11 -1
  11. package/dist/components/SessionList/SessionList.d.ts +42 -0
  12. package/dist/components/TreeSelect/TreeSelect.d.ts +3 -2
  13. package/dist/components/index.d.ts +10 -2
  14. package/dist/components/index.js +14 -14
  15. package/dist/components/style.css +608 -20
  16. package/dist/index.d.ts +0 -2
  17. package/dist/index.js +141 -433
  18. package/dist/layout/weifuwu-layout.css +9 -0
  19. package/dist/test/client/setup.d.ts +12 -0
  20. package/dist/ui/index.d.ts +3 -3
  21. package/dist/ui-dom/Confirm.d.ts +5 -41
  22. package/dist/ui-dom/Notification.d.ts +8 -70
  23. package/dist/ui-dom/Toast.d.ts +8 -43
  24. package/dist/ui-dom/ai.d.ts +1 -1
  25. package/dist/ui-dom/browser.d.ts +1 -1
  26. package/dist/ui-dom/focus-trap.d.ts +1 -1
  27. package/dist/ui-dom/hooks/chat.d.ts +11 -0
  28. package/dist/ui-dom/hooks/events.d.ts +30 -0
  29. package/dist/ui-dom/hooks/external.d.ts +20 -0
  30. package/dist/ui-dom/hooks/index.d.ts +31 -0
  31. package/dist/ui-dom/hooks/input.d.ts +33 -0
  32. package/dist/ui-dom/hooks/media.d.ts +17 -0
  33. package/dist/ui-dom/hooks/popup.d.ts +37 -0
  34. package/dist/ui-dom/hooks/stable.d.ts +39 -0
  35. package/dist/ui-dom/hooks/test/hooks.test.d.ts +1 -0
  36. package/dist/ui-dom/hooks/types.d.ts +78 -0
  37. package/dist/ui-dom/index.d.ts +19 -17
  38. package/dist/ui-dom/index.js +12 -10
  39. package/dist/ui-dom/jsx-runtime.js +1 -1
  40. package/dist/ui-dom/middleware/api.d.ts +3 -3
  41. package/dist/ui-dom/middleware/auth.d.ts +1 -1
  42. package/dist/ui-dom/motion.d.ts +1 -1
  43. package/dist/ui-dom/popup.d.ts +1 -1
  44. package/dist/ui-dom/scroll-lock.d.ts +1 -1
  45. package/dist/ui-dom/store.d.ts +24 -0
  46. package/dist/ui-dom/testing.d.ts +74 -0
  47. package/dist/ui-dom/testing.js +1 -0
  48. package/dist/ui-dom/testing.test.d.ts +1 -0
  49. package/dist/ui-dom/types.d.ts +34 -17
  50. package/dist/ui-dom/use-chat.d.ts +19 -14
  51. package/dist/ui-dom/vdom/build.d.ts +34 -0
  52. package/dist/ui-dom/vdom/diff.d.ts +34 -0
  53. package/dist/ui-dom/vdom/hydration.d.ts +17 -0
  54. package/dist/ui-dom/vdom/index.d.ts +23 -0
  55. package/dist/ui-dom/vdom/mount.d.ts +49 -0
  56. package/dist/ui-dom/vdom/registry.d.ts +27 -0
  57. package/dist/ui-dom/vdom/render.d.ts +13 -0
  58. package/dist/ui-dom/vdom/scheduler.d.ts +13 -0
  59. package/dist/ui-dom/vdom/serve.d.ts +30 -0
  60. package/dist/ui-dom/vdom/ssr.d.ts +44 -0
  61. package/dist/ui-dom/vnode.d.ts +11 -44
  62. package/dist/user/token.d.ts +1 -1
  63. package/docs/compat-three-library.md +1 -1
  64. package/docs/components-map.md +19 -2
  65. package/docs/components.md +9 -4
  66. package/docs/custom-components.md +19 -14
  67. package/docs/data.md +16 -33
  68. package/docs/environment.md +1 -1
  69. package/docs/frontend-middleware.md +65 -79
  70. package/docs/frontend-ui-dom.md +4 -2
  71. package/docs/frontend.md +35 -38
  72. package/docs/layout.md +2 -2
  73. package/docs/realtime.md +23 -28
  74. package/docs/saas.md +8 -6
  75. package/package.json +5 -1
  76. package/dist/ui/ssr-page.d.ts +0 -41
  77. package/dist/ui/ssr.d.ts +0 -35
  78. package/dist/ui-dom/diff.d.ts +0 -28
  79. package/dist/ui-dom/hydration.d.ts +0 -13
  80. package/dist/ui-dom/reactive.d.ts +0 -6
  81. package/dist/ui-dom/registry.d.ts +0 -39
  82. package/dist/ui-dom/render.d.ts +0 -46
  83. package/dist/ui-dom/route-match.d.ts +0 -22
  84. package/dist/ui-dom/serve.d.ts +0 -28
  85. package/dist/ui-dom/ssr.d.ts +0 -56
  86. package/dist/ui-dom/ui.d.ts +0 -78
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # weifuwu
2
2
 
3
- **自托管全栈框架** — 一个 npm 包 = 后端 HTTP + 前端 VDOM + 109 组件 + CSS 设计系统 + SaaS 地基(认证 / 消息 / 队列 / AI)。全自研、零构建、消灭样板。
3
+ **自托管全栈框架** — 一个 npm 包 = 后端 HTTP + 前端 VDOM + 113 组件 + CSS 设计系统 + SaaS 地基(认证 / 消息 / 队列 / AI)。全自研、零构建、消灭样板。
4
4
 
5
5
  ```bash
6
6
  npm install weifuwu # 一个依赖,完整应用栈
@@ -24,8 +24,8 @@ npm install weifuwu # 一个依赖,完整应用栈
24
24
  |----|------|------|
25
25
  | 后端 | `weifuwu` | Trie 路由 / 中间件链 / serve / 自研 PG+Redis / SSR / GraphQL / WebSocket |
26
26
  | 前端 | `weifuwu/ui-dom` | **UIRouter(纯路由 + ctx 注入链)+ uiServe(渲染运行时)+ SSR/hydration**——handler=异步组件 / 中间件两阶段 / ctx.params 对齐后端;**weifuwu/components 直接复用**(VNode 契约唯一来源 ui-dom,见 `docs/frontend-ui-dom.md`) |
27
- | 组件 | `weifuwu/components` | 109 个 HTML 原语组件(表单/表格/弹层/AiChat…),引用 `--wf-*` 主题变量 |
28
- | 样式 | `weifuwu/layout` | 57 布局原语 + 136 工具类 + 167 主题 Token,零自定义 CSS 文件 |
27
+ | 组件 | `weifuwu/components` | 113 个 HTML 原语组件(表单/表格/弹层/AiChat…),引用 `--wf-*` 主题变量 |
28
+ | 样式 | `weifuwu/layout` | 58 布局原语 + 136 工具类 + 167 主题 Token,零自定义 CSS 文件 |
29
29
  | SaaS 地基 | 随包内置 | rateLimit / email / userSystem / messager / queue / ai → `ctx.*` 一行接入 |
30
30
 
31
31
  > ⚠️ **注意:前后端都有 `ctx.ui`,但用途完全不同**
@@ -109,7 +109,7 @@ npm install weifuwu # 一个依赖,完整应用栈
109
109
 
110
110
  **自研数据层** — `ctx.sql`(PG v3 协议)与 `ctx.redis`(RESP2 协议)为**自研客户端**:确定性输出、行为可预测、统一错误模型。jsonb 自动解码、TTL 安全 API、schema 写前校验——高频痛点(双重编码/parseRow 样板/`'EX'` 参数顺序)从根上消除。
111
111
 
112
- > **实践验证**:多租户 AI 平台(`apps/agent-platform`——14 页 + 部门聊天 + 知识库 + HITL 审批)已完全运行在框架上:auth(userSystem)/ AI 引擎(ai)/ 实时消息(messager)/ UI(109 组件)/ 数据管道(ctx.api)零自研替代。框架哲学(中间件注入、诚实裁剪、机制与策略分离)经受住了真实复杂应用的检验——这也是我们确定「哪些进框架、哪些留应用层」的依据。
112
+ > **实践验证**:多租户 AI 平台(`apps/agent-platform`——14 页 + 部门聊天 + 知识库 + HITL 审批)已完全运行在框架上:auth(userSystem)/ AI 引擎(ai)/ 实时消息(messager)/ UI(113 组件)/ 数据管道(ctx.api)零自研替代。框架哲学(中间件注入、诚实裁剪、机制与策略分离)经受住了真实复杂应用的检验——这也是我们确定「哪些进框架、哪些留应用层」的依据。
113
113
 
114
114
  ---
115
115
 
@@ -191,7 +191,7 @@ router.use(ui())
191
191
  // → 完整 HTML + __DATA__ + bundle/styles 引用(无需手写页面 handler)
192
192
  router.get('*', async (req, ctx) => {
193
193
  const { page } = await ssrPage(app, { url: req.url ?? '/' })
194
- return ctx.ui.html(page)
194
+ return ctx.ui.html.unsafe(page) // page 是完整 HTML(ssrPage 已序列化 __DATA__)——unsafe 防二次转义
195
195
  })
196
196
 
197
197
  router.get('/static/app.js', (req, ctx) => ctx.ui.js('./src/client.ts'))
@@ -225,7 +225,7 @@ uiServe(app, { root: '#root', hydrate: true })
225
225
  ### 30 秒体验(跑现有 demo)
226
226
 
227
227
  ```bash
228
- # ① 组件 cheatsheet——102 组件全部可交互预览(零依赖,5 秒起)
228
+ # ① 组件 cheatsheet——113 组件全部可交互预览(零依赖,5 秒起)
229
229
  cd apps/components-demo && node server.ts
230
230
  # 打开 http://localhost:3000
231
231
 
@@ -314,8 +314,8 @@ cd apps/agent-platform && npm run seed && npm run dev
314
314
  | 资源 | CDN 地址 | 说明 |
315
315
  |------|---------|------|
316
316
  | `weifuwu/ui-dom` | `https://unpkg.com/weifuwu@latest/dist/ui-dom/index.js` | 前端运行时(UIRouter, uiServe, h, 状态管理等) |
317
- | `weifuwu/components` | `https://unpkg.com/weifuwu@latest/dist/components/index.js` | 102 个 UI 组件(Button, Card, Table, Modal, Icon 等) |
318
- | `weifuwu/components` | `https://unpkg.com/weifuwu@latest/dist/components/style.css` | 组件 CSS + 167 个主题 Token + 57 个布局原语 + 136 个工具类 |
317
+ | `weifuwu/components` | `https://unpkg.com/weifuwu@latest/dist/components/index.js` | 113 个 UI 组件(Button, Card, Table, Modal, Icon 等) |
318
+ | `weifuwu/components` | `https://unpkg.com/weifuwu@latest/dist/components/style.css` | 组件 CSS + 167 个主题 Token + 58 个布局原语 + 136 个工具类 |
319
319
  | 独立布局系统 | `https://unpkg.com/weifuwu@latest/dist/layout/weifuwu-layout.css` | 仅 CSS 布局,不依赖 JS |
320
320
 
321
321
 
@@ -358,7 +358,7 @@ cd apps/agent-platform && npm run seed && npm run dev
358
358
  | `weifuwu/ui-dom` | **useChat / AiChat 原语** | AI 会话(流式/工具调用/HITL) | — |
359
359
  | `weifuwu/ui-dom` | **事件原语** | `usePopup` / `useDialog` / `usePresence` / `useInView` / `useScrollPosition` / `useGlobalKey` / `useDrag` / `useDragDrop` / `useAnimationEnd` / `useTween` / `useReducedMotion`(浏览器事件/动画统一入口,见 [docs/mobile.md](docs/mobile.md)) | — |
360
360
  | `weifuwu/components` | **113 个组件** | Button/Table/Modal/Confirm/Toast/... + `confirm()` / `toast()` 命令式中间件 | weifuwu/ui-dom |
361
- | `weifuwu/layout` | **CSS 布局** | 57 个布局原语 + 136 个工具类 + 167 个主题 Token(也支持 `weifuwu/layout/style.css`) | — |
361
+ | `weifuwu/layout` | **CSS 布局** | 58 个布局原语 + 136 个工具类 + 167 个主题 Token(也支持 `weifuwu/layout/style.css`) | — |
362
362
 
363
363
  ---
364
364
 
@@ -380,7 +380,7 @@ cd apps/agent-platform && npm run seed && npm run dev
380
380
  | 后台任务/定时 | `queue()` → `ctx.queue` · `scheduler()` → `ctx.schedule/cron` | [docs/saas.md](docs/saas.md) |
381
381
  | AI 对话 / Agent / HITL 审批 | `ai()` → `ctx.ai` + `ctx.ui.useChat()` + `AiChat` | [docs/saas.md](docs/saas.md) |
382
382
  | GraphQL / WebSocket | `app.graphql(handler)` · `app.ws(path, handler)` | [docs/realtime.md](docs/realtime.md) |
383
- | 前端 UI 组件 | `weifuwu/components`(102 个:Button/Table/Modal/AiChat/...) | [docs/components.md](docs/components.md) |
383
+ | 前端 UI 组件 | `weifuwu/components`(113 个:Button/Table/Modal/AiChat/...) | [docs/components.md](docs/components.md) |
384
384
  | 布局/主题/暗色 | `weifuwu/layout`(57 原语 + 136 工具类 + 167 Token) | [docs/layout.md](docs/layout.md) |
385
385
  | 样式定制(零自定义 CSS) | `--wf-*` 变量覆盖 + 组件定制钩子 | [docs/styling.md](docs/styling.md) |
386
386
  | 移动端适配(tap/长按/键盘/弹层) | `usePopup` / `useHoverCapable` / `useLongPress` / `useVisualViewport` | [docs/mobile.md](docs/mobile.md) |
@@ -390,16 +390,15 @@ cd apps/agent-platform && npm run seed && npm run dev
390
390
 
391
391
  ## 核心概念
392
392
 
393
- ### 三层形态(路由 / 组件 / 异步工厂)
393
+ ### 三层形态(路由 / 同步组件 / async 组件)
394
394
 
395
395
  | 层 | 签名 | 异步 | 生命周期 |
396
396
  |----|------|------|---------|
397
397
  | **UIHandler**(路由) | `async (location, ctx) => VNode` | ✅ 整体 | 每次路由变化执行 |
398
- | **Component**(组件) | `(initProps, ctx) => (props) => VNode` | ❌ 同步 | mount 一次 + render 每次 |
399
- | **AsyncFactory**(异步组件) | `async (ctx) => (initProps, ctx) => (props) => VNode` | ✅ 只工厂 | 工厂一次(WeakMap 缓存) |
400
-
401
- 异步只出现在两个边界——路由 handler(整页)和组件工厂(数据声明);**mount/render 永远同步**(SSR/hydration 两端一致性的根基)。`async (initProps, ctx) => ...` 是混合错形——渲染器不 await 同步组件,Promise 会被当 render 函数调用。
398
+ | **Component**(同步组件) | `(initProps, ctx) => (props) => VNode` | ❌ 同步 | mount 一次 + render 每次 |
399
+ | **AsyncComponent**(async 组件) | `async (initProps, ctx) => (props) => VNode` | ✅ 只工厂 | 工厂按实例(diff 传递 `_asyncDef`,补全不重跑) |
402
400
 
401
+ 异步只出现在两个边界——路由 handler(整页)和 async 组件工厂(数据声明);async 组件与同步组件**同签名**(唯一差别是 `async` 关键字)。渲染器按「返回值 instanceof Promise」统一判别:主路径 `buildVNode` async 预构建(await 全部工厂,兄弟并行)→ 落地零占位;动态挂载兑底占位 + 局部补全;骨架屏 `uiServe({ loading })` + `handle.ready`。
403
402
  ### 两阶段组件(新手必读:为什么是两层)
404
403
 
405
404
  组件 = `(initProps, ctx) => (props) => VNode`——**外层 = 初始化(只执行一次),内层 = 渲染(每次状态/props 变化时执行)**。类比:外层是对象的构造函数,内层是它的 render 方法。
@@ -446,7 +445,7 @@ const Counter = (_init, ctx) => {
446
445
 
447
446
  ### async 组件(三条纪律)
448
447
 
449
- async 组件让"拿数据渲染页面"像写同步代码——签名与同步组件一致,唯一差别是 `async` 关键字(**无需 asyncComponent 包装**):`async (initProps, ctx) => renderFn`。异步只在工厂边界:
448
+ async 组件让"拿数据渲染页面"像写同步代码——签名与同步组件一致,唯一差别是 `async` 关键字:`async (initProps, ctx) => renderFn`。异步只在工厂边界:
450
449
 
451
450
  ```tsx
452
451
  const UserProfile = async (_init, ctx) => {
@@ -469,9 +468,10 @@ const UserProfile = async (_init, ctx) => {
469
468
  | ③ 初始状态必须确定性 | `$.w = window.innerWidth`——SSR/hydration mismatch | 用服务端数据 seed,交互后再测 |
470
469
 
471
470
  **常见坑**:
472
- - 工厂**拿不到 props**——数据维度从 `ctx.params` / `ctx.data`
473
- - 闭包数据是页面加载时的**快照**——路由参数变化靠工厂重跑刷新(key 变 → 缓存 miss → 重新取数);工厂缓存绑定页面上下文,路由导航/登录登出时自动失效
471
+ - 工厂按**实例**执行(N 处实例 = N 次工厂调用)——数据必须走 `ctx.data`(自带缓存 + 并发合并,重复执行零成本);禁止副作用/昂贵操作裸写工厂
472
+ - 闭包数据是页面加载时的**快照**——路由参数变化靠工厂重跑刷新(key 变 → 缓存 miss → 重新取数)
474
473
  - **个性化数据不进 `ctx.data`**——SSR 会把工厂取数结果序列化给所有客户端,会话/用户相关数据留在 `$` + fetch
474
+ - **占位显示**:async 组件未 resolve 时渲染 `Placeholder`——无边界显示 null;`<Suspense fallback={...}>` 边界内占位处显示 fallback(可选,子树内任意深度 async 组件共享)
475
475
 
476
476
  ### 渲染策略:SPA 还是 SSR?
477
477
 
@@ -511,11 +511,11 @@ README 只保留入门内容(设计理念 / 快速开始 / 核心概念 / 模
511
511
 
512
512
  | 文档 | 内容 |
513
513
  |------|------|
514
- | [docs/frontend.md](docs/frontend.md) | 前端核心:UIRouter / 组件模型 / 状态管理 / 条件与列表 / ref / 类型(历史 client 版见 docs/frontend.md) |
514
+ | [docs/frontend.md](docs/frontend.md) | 前端核心:应用引导(UIRouter+uiServe)/ 组件模型 / 异步组件 / 状态管理 / 条件与列表 / ref / 类型(weifuwu/client 已并入 ui-dom) |
515
515
  | [docs/frontend-ui-dom.md](docs/frontend-ui-dom.md) | **ui-dom**:UIRouter 纯路由 + uiServe 渲染运行时 + ctx 注入链 + components 复用 + SSR/hydration(前端唯一运行时——weifuwu/client 已删除) |
516
516
  | [docs/frontend-middleware.md](docs/frontend-middleware.md) | 前端中间件:router / api / auth / ws / i18n / ErrorBoundary / confirm / toast / ScrollLock / extendCtx |
517
517
  | [docs/components.md](docs/components.md) | 组件库(113 个组件 + 使用示例 + 组件列表) |
518
- | [docs/layout.md](docs/layout.md) | 布局系统:57 个布局原语 + 136 个工具类 + 167 个主题 Token |
518
+ | [docs/layout.md](docs/layout.md) | 布局系统:58 个布局原语 + 136 个工具类 + 167 个主题 Token |
519
519
  | [docs/styling.md](docs/styling.md) | 样式定制指南:零自定义 CSS 模式 / 暗色 / 组件级覆盖 / 作用域主题 |
520
520
 
521
521
  ### 通用
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * 纯类型,零运行时成本。两端同源:
5
5
  * - 后端:从 weifuwu 主包导入(src/index.ts re-export)
6
- * - 前端:从 weifuwu/client 导入(src/client/index.ts re-export)
6
+ * - 前端:从 weifuwu/ui-dom 导入(src/ui-dom/index.ts re-export)
7
7
  *
8
8
  * 修改本文件 = 修改协议,需同步更新 design/ai-contract.md。
9
9
  */
@@ -22,6 +22,8 @@ export interface WfUsage {
22
22
  export interface WfDone {
23
23
  content: string;
24
24
  usage?: WfUsage;
25
+ /** thinking 模式的推理过程(reasoning_content),收尾时一次性下发(v1 不进流式) */
26
+ reasoning?: string;
25
27
  }
26
28
  export type WfErrorCode = 'auth_failed' | 'rate_limited' | 'context_length' | 'timeout' | 'provider_error' | 'invalid_request' | 'unsupported' | 'aborted';
27
29
  export interface WfError {
@@ -20,7 +20,8 @@
20
20
  */
21
21
  import type { Component } from '../../ui-dom/vnode.ts';
22
22
  import type { UseChatHandle, UiMessage } from '../../ui-dom/use-chat.ts';
23
- import type { WfError, WfUsage } from '../../ai/types.ts';
23
+ import type { WfError, WfUsage, WfApprovalRequest } from '../../ai/types.ts';
24
+ import type { JsonSchema } from '../JsonSchemaForm/JsonSchemaForm.ts';
24
25
  export interface AiChatLabels {
25
26
  send: string;
26
27
  stop: string;
@@ -43,6 +44,9 @@ export interface AiChatProps {
43
44
  renderMessage?: (msg: UiMessage) => any;
44
45
  /** 工具参数渲染(透传 ToolCallCard) */
45
46
  renderToolArgs?: (args: Record<string, unknown>) => any;
47
+ /** 审批修改参数:按审批请求返回工具参数 schema(返回 undefined 则审批卡无修改入口;
48
+ * 提交修改后参数 → chat.approve('modified', …)——后端按 modifiedArgs 执行) */
49
+ approveSchema?: (request: WfApprovalRequest) => JsonSchema | undefined;
46
50
  /** 键盘弹起时输入区 fixed 抬升(全屏 chat 布局用;内联卡片默认 false——原生聚焦滚动已够) */
47
51
  raiseOnKeyboard?: boolean;
48
52
  }
@@ -1,4 +1,5 @@
1
1
  import type { Component } from '../../ui-dom/vnode.ts';
2
+ import { type JsonSchema } from '../JsonSchemaForm/JsonSchemaForm.ts';
2
3
  import type { WfApprovalRequest } from '../../ai/types.ts';
3
4
  /**
4
5
  * ApprovalCard — 人工审批卡片(wf: 协议 §4.5 交互原语)
@@ -20,13 +21,15 @@ export interface ApprovalCardProps {
20
21
  request: WfApprovalRequest;
21
22
  /** 卡片状态(默认 pending) */
22
23
  status?: ApprovalStatus;
23
- /** 用户点"允许" */
24
- onApprove?: () => void;
24
+ /** 用户点"允许"(modified 决策时带修改后参数——父层据此选 decision) */
25
+ onApprove?: (modifiedArgs?: Record<string, unknown>) => void;
25
26
  /** 用户点"拒绝",note 为可选备注(进 agent 上下文) */
26
27
  onReject?: (note?: string) => void;
27
28
  /** 自定义详情渲染(默认显示 name + args) */
28
29
  renderDetail?: (request: WfApprovalRequest) => any;
29
30
  /** 提交中(按钮禁用 + 文案反馈,防连点) */
30
31
  loading?: boolean;
32
+ /** 工具参数 schema——提供时渲染「修改参数」入口(JsonSchemaForm,预填 request.args),提交带修改后参数 */
33
+ argsSchema?: JsonSchema;
31
34
  }
32
35
  export declare const ApprovalCard: Component<ApprovalCardProps>;
@@ -7,6 +7,8 @@ export interface ButtonProps {
7
7
  disabled?: boolean;
8
8
  type?: 'button' | 'submit';
9
9
  title?: string;
10
+ /** 透传 DOM id(测试定位/锚点) */
11
+ id?: string;
10
12
  /** 透传原生 class(覆盖默认 wf-btn 组合) */
11
13
  class?: string;
12
14
  onClick?: (e: MouseEvent) => void;
@@ -0,0 +1,38 @@
1
+ import type { Component } from '../../ui-dom/vnode.ts';
2
+ import type { WfuiContext } from '../../ui-dom/types.ts';
3
+ /**
4
+ * CitationCard — RAG 检索引用展示(AI 差异化)
5
+ *
6
+ * AI 回复的引用来源列表:折叠「引用 N 条」头部 + 展开条目列表
7
+ * (序号 + 标题 + 来源 + 片段 + 可选链接)。手动优先(let + render())。
8
+ *
9
+ * ```tsx
10
+ * <CitationCard
11
+ * items={[{ id, title, source, snippet, url? }]}
12
+ * maxVisible={3}
13
+ * onOpen={(c) => openDoc(c.id)}
14
+ * />
15
+ * ```
16
+ */
17
+ export interface Citation {
18
+ id: string;
19
+ title: string;
20
+ /** 来源元信息(文档路径/域名等) */
21
+ source?: string;
22
+ /** 原文片段(裁剪:不做全文展开——片段即展示) */
23
+ snippet: string;
24
+ /** 可点击链接(无 onOpen 时新窗口打开) */
25
+ url?: string;
26
+ }
27
+ export interface CitationCardProps {
28
+ items: Citation[];
29
+ /** 折叠头文案(默认「引用来源」) */
30
+ label?: string;
31
+ /** 折叠时最多显示条数(默认 3;溢出显示 +N 汇总条目) */
32
+ maxVisible?: number;
33
+ /** 初始展开(默认折叠) */
34
+ defaultExpanded?: boolean;
35
+ /** 点击条目回调(提供时不渲染链接,由调用方处理跳转/打开) */
36
+ onOpen?: (citation: Citation) => void;
37
+ }
38
+ export declare const CitationCard: Component<CitationCardProps, WfuiContext>;
@@ -18,5 +18,5 @@ export interface CommandProps {
18
18
  /** 全局快捷键,如 'mod+k'(cmd/ctrl + k);null 关闭全局监听 */
19
19
  globalShortcut?: string | null;
20
20
  }
21
- /** 命令面板(对应 shadcn Command):全屏 overlay + 搜索 + 键盘流(↑↓ Enter Escape)+ Cmd+K 全局快捷键 */
21
+ /** 命令面板(对应 shadcn Command):usePopup mask 全屏遮罩 + 搜索 + 键盘流(↑↓ Enter Escape)+ Cmd+K 全局快捷键 */
22
22
  export declare const Command: Component<CommandProps>;
@@ -0,0 +1,48 @@
1
+ import type { Component } from '../../ui-dom/vnode.ts';
2
+ import type { WfuiContext } from '../../ui-dom/types.ts';
3
+ /**
4
+ * JsonSchemaForm — JSON Schema(对象子集)→ 参数输入表单(零依赖)
5
+ *
6
+ * AI 场景参数输入面:工具调用参数(ToolCallCard 只展示,本组件负责输入)、
7
+ * 审批 modified 决策的取参来源、Agent 配置页 schema 驱动表单。
8
+ *
9
+ * 类型映射:string→Input / number|integer→InputNumber / boolean→Switch /
10
+ * string+enum→Select / object→嵌套折叠区(递归)/ array→列表 + 添加/删除。
11
+ *
12
+ * 值管理:内部 state(非受控),`value` 仅作初始值——输入回流来自内部,
13
+ * 无受控回流焦点问题(§5.3);`onChange` 每次编辑通知(不回流控制)。
14
+ * 校验(submit 时):required / enum / min-max / minLength-maxLength,
15
+ * 错误展示在字段 error,不触发 onSubmit。
16
+ *
17
+ * ```tsx
18
+ * <JsonSchemaForm schema={tool.parameters} value={args} onSubmit={run} submitLabel="执行" />
19
+ * ```
20
+ */
21
+ export interface JsonSchema {
22
+ type?: 'object' | 'string' | 'number' | 'integer' | 'boolean' | 'array' | 'null';
23
+ title?: string;
24
+ description?: string;
25
+ properties?: Record<string, JsonSchema>;
26
+ required?: string[];
27
+ enum?: (string | number)[];
28
+ items?: JsonSchema;
29
+ default?: unknown;
30
+ minimum?: number;
31
+ maximum?: number;
32
+ minLength?: number;
33
+ maxLength?: number;
34
+ /** 不支持的 schema 关键字($ref 等)——诚实裁剪:告警 + 降级文本输入 */
35
+ $ref?: string;
36
+ }
37
+ export interface JsonSchemaFormProps {
38
+ /** 顶层对象 schema(type: 'object' + properties) */
39
+ schema: JsonSchema;
40
+ /** 初始值(非受控语义);内部状态由编辑驱动 */
41
+ value?: Record<string, any>;
42
+ /** 每次编辑通知(父层可读最新值;不回流控制) */
43
+ onChange?: (values: Record<string, any>) => void;
44
+ /** 提交(校验通过才触发);不传则不渲染提交按钮 */
45
+ onSubmit?: (values: Record<string, any>) => void;
46
+ submitLabel?: string;
47
+ }
48
+ export declare const JsonSchemaForm: Component<JsonSchemaFormProps, WfuiContext>;
@@ -0,0 +1,25 @@
1
+ import type { Component } from '../../ui-dom/vnode.ts';
2
+ import type { WfuiContext } from '../../ui-dom/types.ts';
3
+ /**
4
+ * ReasoningBlock — CoT 推理过程折叠展示(AI 差异化)
5
+ *
6
+ * DeepSeek thinking 模式的 reasoning_content 展示层:折叠「已思考」头部,
7
+ * 点击展开推理文本。流式(streaming)时头部带脉冲指示。
8
+ *
9
+ * 手动优先(组件库纪律):let expanded + render(),无 $。
10
+ *
11
+ * ```tsx
12
+ * <ReasoningBlock content={m.reasoning} streaming={m.status === 'streaming'} />
13
+ * ```
14
+ */
15
+ export interface ReasoningBlockProps {
16
+ /** 推理文本(reasoning_content) */
17
+ content: string;
18
+ /** 初始展开(默认折叠) */
19
+ defaultExpanded?: boolean;
20
+ /** 折叠头部文案(默认「已思考」) */
21
+ label?: string;
22
+ /** 流式中(头部脉冲指示) */
23
+ streaming?: boolean;
24
+ }
25
+ export declare const ReasoningBlock: Component<ReasoningBlockProps, WfuiContext>;
@@ -4,10 +4,20 @@ export interface SelectOption {
4
4
  label: string;
5
5
  disabled?: boolean;
6
6
  }
7
+ /** 选项组(optgroup):label + 组内选项 */
8
+ export interface SelectOptionGroup {
9
+ label: string;
10
+ options: SelectOption[];
11
+ }
12
+ /** 选项列表:平铺项与分组可混用 */
13
+ export type SelectOptions = (SelectOption | SelectOptionGroup)[];
14
+ export declare function isOptionGroup(o: SelectOption | SelectOptionGroup): o is SelectOptionGroup;
15
+ /** 展平(键盘索引 / 选中查找用);保持顺序 */
16
+ export declare function flattenOptions(opts: SelectOptions | undefined): SelectOption[];
7
17
  export interface SelectProps {
8
18
  label?: string;
9
19
  value?: string | string[];
10
- options?: SelectOption[];
20
+ options?: SelectOptions;
11
21
  placeholder?: string;
12
22
  required?: boolean;
13
23
  disabled?: boolean;
@@ -0,0 +1,42 @@
1
+ import type { Component } from '../../ui-dom/vnode.ts';
2
+ import type { WfuiContext } from '../../ui-dom/types.ts';
3
+ /**
4
+ * SessionList — 侧栏会话管理列表(AI 差异化)
5
+ *
6
+ * 会话分组(今天/昨天/更早)+ 选中高亮 + 搜索过滤 + 重命名/删除/新建。
7
+ * 手动优先(let + render()):
8
+ * - 重命名:行内编辑按钮 → 输入框(预填原标题)→ Enter 确认 / Escape 取消
9
+ * - 删除:悬停行内删除按钮(裁剪:不做右键菜单)
10
+ * - 键盘:方向键移动焦点 + Enter 激活(列表容器 onKeyDown)
11
+ *
12
+ * ```tsx
13
+ * <SessionList sessions={sessions} activeId={cur} onSelect={setCur}
14
+ * onNew={createSession} onRename={renameSession} onDelete={deleteSession} searchable />
15
+ * ```
16
+ */
17
+ export interface Session {
18
+ id: string;
19
+ title: string;
20
+ /** 更新时间戳(ms)——分组(今天/昨天/更早);缺省进「更早」 */
21
+ updatedAt?: number;
22
+ }
23
+ export interface SessionListProps {
24
+ sessions: Session[];
25
+ /** 当前选中会话 id(高亮 + aria-selected) */
26
+ activeId?: string;
27
+ /** 点击会话(键盘 Enter 同) */
28
+ onSelect?: (id: string) => void;
29
+ /** 新建按钮(渲染条件:onNew 提供) */
30
+ onNew?: () => void;
31
+ /** 重命名(行内编辑 Enter 确认) */
32
+ onRename?: (id: string, title: string) => void;
33
+ /** 删除(行内悬停按钮) */
34
+ onDelete?: (id: string) => void;
35
+ /** 顶部搜索框(按标题过滤) */
36
+ searchable?: boolean;
37
+ /** 新建按钮文案(默认「新建会话」) */
38
+ newLabel?: string;
39
+ }
40
+ /** 分组标签:今天 / 昨天 / 更早(确定性:now 可注入) */
41
+ export declare function groupKey(t: number, now?: number): 'today' | 'yesterday' | 'earlier';
42
+ export declare const SessionList: Component<SessionListProps, WfuiContext>;
@@ -16,8 +16,9 @@ export interface TreeSelectProps {
16
16
  export declare function findLabel(nodes: TreeNode[], key: string): string | undefined;
17
17
  /**
18
18
  * TreeSelect — 树形选择(Tree + 下拉组合)。
19
- * 下拉经 createPortal + position:fixed(usePopupPosition 定位/跟随/夹紧)——
20
- * DatePicker 同模式:父容器 overflow/transform 不影响弹出层。
19
+ * 弹层经 ctx.ui.usePopup(§5.4 弹窗纪律统一组合器):portal #__wf_portal +
20
+ * fixed 定位/视口夹紧 + 外部点击关闭 + Escape 关闭 + ref 稳定——不再手写
21
+ * usePopupPosition/createPortal/panelRef(此前缺外部点击关闭的真实 bug)。
21
22
  * 单选 selectedKeys / 多选 checkable checkedKeys(父子联动)。
22
23
  * 受控纪律:value 受控无 onChange → warn。
23
24
  */
@@ -13,8 +13,8 @@ export { Input } from './Input/Input.ts';
13
13
  export type { InputProps } from './Input/Input.ts';
14
14
  export { Textarea } from './Textarea/Textarea.ts';
15
15
  export type { TextareaProps } from './Textarea/Textarea.ts';
16
- export { Select } from './Select/Select.ts';
17
- export type { SelectProps, SelectOption } from './Select/Select.ts';
16
+ export { Select, flattenOptions } from './Select/Select.ts';
17
+ export type { SelectProps, SelectOption, SelectOptionGroup, SelectOptions } from './Select/Select.ts';
18
18
  export { Checkbox } from './Checkbox/Checkbox.ts';
19
19
  export type { CheckboxProps } from './Checkbox/Checkbox.ts';
20
20
  export { Switch } from './Switch/Switch.ts';
@@ -223,3 +223,11 @@ export { Scrollbar } from './Scrollbar/Scrollbar.ts';
223
223
  export type { ScrollbarProps } from './Scrollbar/Scrollbar.ts';
224
224
  export { AlertGroup } from './AlertGroup/AlertGroup.ts';
225
225
  export type { AlertGroupProps, AlertGroupItem } from './AlertGroup/AlertGroup.ts';
226
+ export { JsonSchemaForm } from './JsonSchemaForm/JsonSchemaForm.ts';
227
+ export type { JsonSchemaFormProps, JsonSchema } from './JsonSchemaForm/JsonSchemaForm.ts';
228
+ export { ReasoningBlock } from './ReasoningBlock/ReasoningBlock.ts';
229
+ export type { ReasoningBlockProps } from './ReasoningBlock/ReasoningBlock.ts';
230
+ export { CitationCard } from './CitationCard/CitationCard.ts';
231
+ export type { CitationCardProps, Citation } from './CitationCard/CitationCard.ts';
232
+ export { SessionList, groupKey } from './SessionList/SessionList.ts';
233
+ export type { SessionListProps, Session } from './SessionList/SessionList.ts';