@krishanjinbo/vue-markdown-stream 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,20 +1,22 @@
1
1
  # vue-markdown-stream
2
2
 
3
- > 流式 Markdown 渲染 + Vue 3 组件块,基于 `markdown-it-container`
3
+ > Agent UI Protocol — LLM 可控的流式 Markdown 渲染 + Vue 交互组件协议
4
4
 
5
5
  [![npm](https://img.shields.io/npm/v/@krishanjinbo/vue-markdown-stream)](https://www.npmjs.com/package/@krishanjinbo/vue-markdown-stream)
6
6
  [![license](https://img.shields.io/badge/license-MIT-blue)](./LICENSE)
7
7
 
8
- 在 AI 流式输出场景中,将 `:::alert`、`:::card` 等 Markdown 容器块实时渲染为真实 Vue 3 组件,支持响应式 props 和 slot 内容。
8
+ 在 AI Agent 场景中,将 `:::confirm`、`:::select`、`:::form` 等 Markdown 容器块实时渲染为 Vue 3 交互组件,用户操作通过事件总线回传给宿主应用。
9
9
 
10
- **📖 [完整文档](https://hanlang123.github.io/vue-markdown-stream/) · [在线演示](https://hanlang123.github.io/vue-markdown-stream/demo)**
10
+ **[完整文档](https://hanlang123.github.io/vue-markdown-stream/) · [在线演示](https://hanlang123.github.io/vue-markdown-stream/demo)**
11
11
 
12
12
  ## 特性
13
13
 
14
- - **流式打字机渲染** — 逐字追加,自动补全未闭合 `:::` 块
15
- - 🧩 **Vue 组件块**`:::alert` / `:::card` 渲染为真实 Vue 组件(响应式 props + slot)
16
- - 🔌 **完全可扩展** 5 行代码注册任意自定义块组件
17
- - 🪶 **轻量**基于 `DOMParser` + `h()` VNode 树,无运行时编译,bundle 增量约 40KB
14
+ - **流式打字机渲染** — 逐字追加,自动补全未闭合 `:::` 块
15
+ - **8 种内置组件块** — alert / card / confirm / select / form / progress / datatable / actions
16
+ - **事件回传**AgentEventBus 将用户交互回传给宿主应用,闭环 Agent 流程
17
+ - **Props 安全校验**白名单 + 黑名单 + 类型转换,防止 LLM 注入
18
+ - **完全可扩展** — 通过 props 传入自定义 componentMap 和 propsSchemas
19
+ - **轻量** — 基于 `DOMParser` + `h()` VNode,无运行时编译
18
20
 
19
21
  ## 安装
20
22
 
@@ -40,6 +42,25 @@ const display = computed(() => isStreaming.value ? text.value + '▍' : text.val
40
42
  </template>
41
43
  ```
42
44
 
45
+ ## Agent 交互用法
46
+
47
+ ```vue
48
+ <script setup lang="ts">
49
+ import { MarkdownRenderer, useAgentEvents } from '@krishanjinbo/vue-markdown-stream'
50
+
51
+ const { createHandler, serializeToMessage } = useAgentEvents()
52
+
53
+ const handleAction = createHandler(async (payload) => {
54
+ const message = serializeToMessage(payload)
55
+ // 发送给 Agent API...
56
+ })
57
+ </script>
58
+
59
+ <template>
60
+ <MarkdownRenderer :content="text" @agent:action="handleAction" />
61
+ </template>
62
+ ```
63
+
43
64
  ## Markdown 语法
44
65
 
45
66
  ```markdown
@@ -47,14 +68,18 @@ const display = computed(() => isStreaming.value ? text.value + '▍' : text.val
47
68
  **提示**:这是一个 Info 告警块。
48
69
  :::
49
70
 
50
- ::: alert warning
51
- 注意:`未闭合的块`在流式中间态会被自动补全。
71
+ ::: confirm action="delete" level=danger
72
+ 确认删除?此操作不可撤销。
73
+ :::
74
+
75
+ ::: progress value=73 max=100 status=active
76
+ 正在处理... 73/100
52
77
  :::
53
78
 
54
- ::: card 数据卡片标题
55
- | 列A | 列B |
56
- |-----|-----|
57
- | 值1 | 值2 |
79
+ ::: actions
80
+ - 查看进度
81
+ - 生成报告
82
+ - 导出数据
58
83
  :::
59
84
  ```
60
85
 
@@ -65,7 +90,9 @@ const display = computed(() => isStreaming.value ? text.value + '▍' : text.val
65
90
  → autoCloseContainers() 补全未闭合 ::: 块
66
91
  → markdown-it + container 输出含 <vue-block> 的 HTML
67
92
  → DOMParser HTML → DOM 树
68
- h() VNode 构建 <vue-block> → Vue 组件 VNode
93
+ PropValidator Props 白名单校验 + 清洗
94
+ → h() VNode 构建 <vue-block> → Vue 组件 VNode + 事件绑定
95
+ → AgentEventBus 组件事件 → 宿主应用回调
69
96
  → MarkdownRenderer 渲染输出
70
97
  ```
71
98
 
@@ -1,17 +1,77 @@
1
1
  import { PropType, VNode } from 'vue';
2
+ import { AgentActionPayload } from '../core/eventBus';
3
+ import { ComponentPropsSchema } from '../core/propValidator';
4
+ import { ComponentMap } from '../types';
5
+ export declare const AGENT_EVENT_BUS_KEY: unique symbol;
2
6
  declare const _default: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
7
+ /** Markdown 内容(支持流式追加) */
3
8
  content: {
4
- type: PropType<string>;
5
- default: string;
9
+ type: StringConstructor;
10
+ required: true;
11
+ };
12
+ /**
13
+ * 自定义组件注册表(与内置组件合并,用户组件优先)
14
+ */
15
+ components: {
16
+ type: PropType<ComponentMap>;
17
+ default: () => {};
18
+ };
19
+ /**
20
+ * [v2 新增] 自定义 Props Schema(与默认 Schema 合并)
21
+ */
22
+ propsSchemas: {
23
+ type: PropType<Record<string, ComponentPropsSchema>>;
24
+ default: () => {};
25
+ };
26
+ /**
27
+ * [v2 新增] 是否启用 Props 安全校验(默认启用)
28
+ */
29
+ enableValidation: {
30
+ type: BooleanConstructor;
31
+ default: boolean;
6
32
  };
7
33
  }>, () => VNode<import('vue').RendererNode, import('vue').RendererElement, {
8
34
  [key: string]: any;
9
- }>, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
35
+ }>, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
36
+ /**
37
+ * [v2 新增] Agent 操作事件
38
+ *
39
+ * 当任何内置或自定义块组件触发用户交互时,
40
+ * 通过此事件通知宿主应用,宿主应用负责将其转发给 Agent
41
+ */
42
+ 'agent:action': (_payload: AgentActionPayload) => true;
43
+ }, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
44
+ /** Markdown 内容(支持流式追加) */
10
45
  content: {
11
- type: PropType<string>;
12
- default: string;
46
+ type: StringConstructor;
47
+ required: true;
48
+ };
49
+ /**
50
+ * 自定义组件注册表(与内置组件合并,用户组件优先)
51
+ */
52
+ components: {
53
+ type: PropType<ComponentMap>;
54
+ default: () => {};
55
+ };
56
+ /**
57
+ * [v2 新增] 自定义 Props Schema(与默认 Schema 合并)
58
+ */
59
+ propsSchemas: {
60
+ type: PropType<Record<string, ComponentPropsSchema>>;
61
+ default: () => {};
62
+ };
63
+ /**
64
+ * [v2 新增] 是否启用 Props 安全校验(默认启用)
65
+ */
66
+ enableValidation: {
67
+ type: BooleanConstructor;
68
+ default: boolean;
13
69
  };
14
- }>> & Readonly<{}>, {
15
- content: string;
70
+ }>> & Readonly<{
71
+ "onAgent:action"?: ((_payload: AgentActionPayload) => any) | undefined;
72
+ }>, {
73
+ components: ComponentMap;
74
+ propsSchemas: Record<string, ComponentPropsSchema>;
75
+ enableValidation: boolean;
16
76
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
17
77
  export default _default;
@@ -0,0 +1,33 @@
1
+ import { AgentEventBus } from '../../core/eventBus';
2
+ type __VLS_Props = {
3
+ layout?: 'inline' | 'wrap';
4
+ blockId?: string;
5
+ eventBus?: AgentEventBus;
6
+ };
7
+ declare function __VLS_template(): {
8
+ attrs: Partial<{}>;
9
+ slots: {
10
+ default?(_: {}): any;
11
+ };
12
+ refs: {
13
+ slotContainer: HTMLDivElement;
14
+ };
15
+ rootEl: HTMLDivElement;
16
+ };
17
+ type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
18
+ declare const __VLS_component: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
19
+ "agent-action": (event: string, data: Record<string, unknown>) => any;
20
+ }, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
21
+ "onAgent-action"?: ((event: string, data: Record<string, unknown>) => any) | undefined;
22
+ }>, {
23
+ layout: "inline" | "wrap";
24
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
25
+ slotContainer: HTMLDivElement;
26
+ }, HTMLDivElement>;
27
+ declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
28
+ export default _default;
29
+ type __VLS_WithTemplateSlots<T, S> = T & {
30
+ new (): {
31
+ $slots: S;
32
+ };
33
+ };
@@ -0,0 +1,35 @@
1
+ import { AgentEventBus } from '../../core/eventBus';
2
+ type __VLS_Props = {
3
+ action?: string;
4
+ level?: 'info' | 'warning' | 'danger';
5
+ confirmText?: string;
6
+ cancelText?: string;
7
+ blockId?: string;
8
+ eventBus?: AgentEventBus;
9
+ };
10
+ declare function __VLS_template(): {
11
+ attrs: Partial<{}>;
12
+ slots: {
13
+ default?(_: {}): any;
14
+ };
15
+ refs: {};
16
+ rootEl: HTMLDivElement;
17
+ };
18
+ type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
19
+ declare const __VLS_component: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
20
+ "agent-action": (event: string, data: Record<string, unknown>) => any;
21
+ }, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
22
+ "onAgent-action"?: ((event: string, data: Record<string, unknown>) => any) | undefined;
23
+ }>, {
24
+ action: string;
25
+ level: "info" | "warning" | "danger";
26
+ confirmText: string;
27
+ cancelText: string;
28
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
29
+ declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
30
+ export default _default;
31
+ type __VLS_WithTemplateSlots<T, S> = T & {
32
+ new (): {
33
+ $slots: S;
34
+ };
35
+ };
@@ -0,0 +1,33 @@
1
+ import { AgentEventBus } from '../../core/eventBus';
2
+ type __VLS_Props = {
3
+ sortable?: boolean;
4
+ filterable?: boolean;
5
+ pageSize?: number;
6
+ blockId?: string;
7
+ eventBus?: AgentEventBus;
8
+ };
9
+ declare function __VLS_template(): {
10
+ attrs: Partial<{}>;
11
+ slots: {
12
+ default?(_: {}): any;
13
+ };
14
+ refs: {
15
+ slotContainer: HTMLDivElement;
16
+ };
17
+ rootEl: HTMLDivElement;
18
+ };
19
+ type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
20
+ declare const __VLS_component: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
21
+ sortable: boolean;
22
+ filterable: boolean;
23
+ pageSize: number;
24
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
25
+ slotContainer: HTMLDivElement;
26
+ }, HTMLDivElement>;
27
+ declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
28
+ export default _default;
29
+ type __VLS_WithTemplateSlots<T, S> = T & {
30
+ new (): {
31
+ $slots: S;
32
+ };
33
+ };
@@ -0,0 +1,37 @@
1
+ import { AgentEventBus } from '../../core/eventBus';
2
+ type __VLS_Props = {
3
+ id?: string;
4
+ submitText?: string;
5
+ layout?: 'vertical' | 'horizontal';
6
+ blockId?: string;
7
+ eventBus?: AgentEventBus;
8
+ };
9
+ declare function __VLS_template(): {
10
+ attrs: Partial<{}>;
11
+ slots: {
12
+ default?(_: {}): any;
13
+ };
14
+ refs: {
15
+ slotContainer: HTMLDivElement;
16
+ };
17
+ rootEl: HTMLDivElement;
18
+ };
19
+ type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
20
+ declare const __VLS_component: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
21
+ "agent-action": (event: string, data: Record<string, unknown>) => any;
22
+ }, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
23
+ "onAgent-action"?: ((event: string, data: Record<string, unknown>) => any) | undefined;
24
+ }>, {
25
+ id: string;
26
+ submitText: string;
27
+ layout: "vertical" | "horizontal";
28
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
29
+ slotContainer: HTMLDivElement;
30
+ }, HTMLDivElement>;
31
+ declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
32
+ export default _default;
33
+ type __VLS_WithTemplateSlots<T, S> = T & {
34
+ new (): {
35
+ $slots: S;
36
+ };
37
+ };
@@ -0,0 +1,30 @@
1
+ import { AgentEventBus } from '../../core/eventBus';
2
+ type __VLS_Props = {
3
+ value?: number;
4
+ max?: number;
5
+ label?: string;
6
+ status?: 'active' | 'success' | 'error';
7
+ blockId?: string;
8
+ eventBus?: AgentEventBus;
9
+ };
10
+ declare function __VLS_template(): {
11
+ attrs: Partial<{}>;
12
+ slots: {
13
+ default?(_: {}): any;
14
+ };
15
+ refs: {};
16
+ rootEl: HTMLDivElement;
17
+ };
18
+ type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
19
+ declare const __VLS_component: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
20
+ value: number;
21
+ max: number;
22
+ status: "active" | "success" | "error";
23
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
24
+ declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
25
+ export default _default;
26
+ type __VLS_WithTemplateSlots<T, S> = T & {
27
+ new (): {
28
+ $slots: S;
29
+ };
30
+ };
@@ -0,0 +1,37 @@
1
+ import { AgentEventBus } from '../../core/eventBus';
2
+ type __VLS_Props = {
3
+ mode?: 'single' | 'multiple';
4
+ columns?: number;
5
+ maxSelect?: number;
6
+ blockId?: string;
7
+ eventBus?: AgentEventBus;
8
+ };
9
+ declare function __VLS_template(): {
10
+ attrs: Partial<{}>;
11
+ slots: {
12
+ default?(_: {}): any;
13
+ };
14
+ refs: {
15
+ slotContainer: HTMLDivElement;
16
+ };
17
+ rootEl: HTMLDivElement;
18
+ };
19
+ type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
20
+ declare const __VLS_component: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
21
+ "agent-action": (event: string, data: Record<string, unknown>) => any;
22
+ }, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
23
+ "onAgent-action"?: ((event: string, data: Record<string, unknown>) => any) | undefined;
24
+ }>, {
25
+ mode: "single" | "multiple";
26
+ columns: number;
27
+ maxSelect: number;
28
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
29
+ slotContainer: HTMLDivElement;
30
+ }, HTMLDivElement>;
31
+ declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
32
+ export default _default;
33
+ type __VLS_WithTemplateSlots<T, S> = T & {
34
+ new (): {
35
+ $slots: S;
36
+ };
37
+ };
@@ -0,0 +1,13 @@
1
+ import { ComponentMap } from '../../types';
2
+ export { default as AlertBlock } from './AlertBlock.vue';
3
+ export { default as DataCard } from './DataCard.vue';
4
+ export { default as ConfirmBlock } from './ConfirmBlock.vue';
5
+ export { default as SelectBlock } from './SelectBlock.vue';
6
+ export { default as FormBlock } from './FormBlock.vue';
7
+ export { default as ProgressBlock } from './ProgressBlock.vue';
8
+ export { default as DataTableBlock } from './DataTableBlock.vue';
9
+ export { default as ActionPills } from './ActionPills.vue';
10
+ /**
11
+ * 默认的内置组件注册表
12
+ */
13
+ export declare const builtinComponentMap: ComponentMap;
@@ -0,0 +1,27 @@
1
+ import { Ref } from 'vue';
2
+ import { AgentActionPayload } from '../core/eventBus';
3
+ /**
4
+ * 便捷的 Agent 事件管理 Composable
5
+ *
6
+ * 使用方式:
7
+ * ```vue
8
+ * <script setup>
9
+ * const { createHandler, serializeToMessage } = useAgentEvents()
10
+ *
11
+ * const handleAction = createHandler(async (payload) => {
12
+ * await sendToAgent(payload)
13
+ * })
14
+ * </script>
15
+ *
16
+ * <template>
17
+ * <MarkdownRenderer :content="text" @agent:action="handleAction" />
18
+ * </template>
19
+ * ```
20
+ */
21
+ export declare function useAgentEvents(): {
22
+ lastAction: Ref<AgentActionPayload | null, AgentActionPayload | null>;
23
+ actionHistory: Ref<AgentActionPayload[], AgentActionPayload[]>;
24
+ isProcessing: Ref<boolean, boolean>;
25
+ createHandler: (handler: (payload: AgentActionPayload) => void | Promise<void>) => (payload: AgentActionPayload) => Promise<void>;
26
+ serializeToMessage: (payload: AgentActionPayload) => string;
27
+ };
@@ -1,5 +1,9 @@
1
+ import { default as MarkdownIt } from 'markdown-it';
1
2
  /**
2
- * markdown 字符串渲染为 HTML
3
- * 流式场景下会自动补全未闭合的容器块
3
+ * 创建 Markdown 解析器(增强版)
4
4
  */
5
+ export declare function useMarkdownParser(): {
6
+ parse: (content: string) => string;
7
+ md: MarkdownIt;
8
+ };
5
9
  export declare function renderMarkdown(raw: string): string;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * 自动补全未闭合的 ::: 容器块
3
+ *
4
+ * 增强点(v2):
5
+ * - 支持嵌套容器块的正确补全
6
+ * - 支持 ::: 后带属性参数的容器
7
+ */
8
+ export declare function autoCloseContainers(content: string): string;
@@ -0,0 +1,73 @@
1
+ import { Ref } from 'vue';
2
+ /**
3
+ * Agent 事件载荷
4
+ */
5
+ export interface AgentActionPayload {
6
+ /** 触发事件的组件块 ID(自动生成或 data-id 指定) */
7
+ blockId: string;
8
+ /** 事件类型:confirm / cancel / submit / select / click 等 */
9
+ event: string;
10
+ /** 组件类型:ConfirmBlock / SelectBlock / FormBlock 等 */
11
+ componentType: string;
12
+ /** 事件携带的数据 */
13
+ data: Record<string, unknown>;
14
+ /** 事件时间戳 */
15
+ timestamp: number;
16
+ }
17
+ /**
18
+ * Agent 事件历史记录
19
+ */
20
+ export interface AgentEventRecord extends AgentActionPayload {
21
+ /** 是否已被宿主应用消费 */
22
+ consumed: boolean;
23
+ }
24
+ export type AgentActionHandler = (payload: AgentActionPayload) => void | Promise<void>;
25
+ /**
26
+ * 创建 Agent 事件总线实例
27
+ *
28
+ * 设计为工厂函数而非单例,支持多个 MarkdownRenderer 实例
29
+ * 各自拥有独立的事件空间
30
+ */
31
+ export declare function createAgentEventBus(): {
32
+ emit: (payload: Omit<AgentActionPayload, "timestamp">) => void;
33
+ on: (handler: AgentActionHandler) => () => boolean;
34
+ clearHistory: () => void;
35
+ destroy: () => void;
36
+ history: Readonly<Ref<readonly {
37
+ readonly consumed: boolean;
38
+ readonly blockId: string;
39
+ readonly event: string;
40
+ readonly componentType: string;
41
+ readonly data: {
42
+ readonly [x: string]: Readonly<unknown>;
43
+ };
44
+ readonly timestamp: number;
45
+ }[], readonly {
46
+ readonly consumed: boolean;
47
+ readonly blockId: string;
48
+ readonly event: string;
49
+ readonly componentType: string;
50
+ readonly data: {
51
+ readonly [x: string]: Readonly<unknown>;
52
+ };
53
+ readonly timestamp: number;
54
+ }[]>>;
55
+ lastEvent: Readonly<Ref<{
56
+ readonly blockId: string;
57
+ readonly event: string;
58
+ readonly componentType: string;
59
+ readonly data: {
60
+ readonly [x: string]: Readonly<unknown>;
61
+ };
62
+ readonly timestamp: number;
63
+ } | null, {
64
+ readonly blockId: string;
65
+ readonly event: string;
66
+ readonly componentType: string;
67
+ readonly data: {
68
+ readonly [x: string]: Readonly<unknown>;
69
+ };
70
+ readonly timestamp: number;
71
+ } | null>>;
72
+ };
73
+ export type AgentEventBus = ReturnType<typeof createAgentEventBus>;
@@ -0,0 +1,38 @@
1
+ /**
2
+ * 单个 prop 的校验规则
3
+ */
4
+ export interface PropRule {
5
+ type: 'string' | 'number' | 'boolean' | 'enum';
6
+ required?: boolean;
7
+ default?: unknown;
8
+ enum?: string[];
9
+ maxLength?: number;
10
+ min?: number;
11
+ max?: number;
12
+ }
13
+ /**
14
+ * 组件的 Props Schema 定义
15
+ */
16
+ export interface ComponentPropsSchema {
17
+ /** 允许的 props 白名单 */
18
+ allowed: Record<string, PropRule>;
19
+ /** 全局黑名单(会覆盖 allowed 中同名属性) */
20
+ blocked?: string[];
21
+ }
22
+ /**
23
+ * 默认的内置组件 Schema 注册表
24
+ */
25
+ export declare const defaultSchemas: Record<string, ComponentPropsSchema>;
26
+ /**
27
+ * 校验并清洗从 data-* 属性提取的 props
28
+ *
29
+ * @param componentName - 组件名称
30
+ * @param rawProps - 从 data-* 提取的原始 props(全部为 string 类型)
31
+ * @param schemas - Schema 注册表(可自定义扩展)
32
+ * @returns 校验通过的 props 对象
33
+ */
34
+ export declare function validateProps(componentName: string, rawProps: Record<string, string>, schemas?: Record<string, ComponentPropsSchema>): Record<string, unknown>;
35
+ /**
36
+ * 清洗事件 payload —— 防止原型链污染和函数注入
37
+ */
38
+ export declare function sanitizePayload(payload: unknown): Record<string, unknown>;
package/dist/index.d.ts CHANGED
@@ -1,8 +1,19 @@
1
1
  export { default as MarkdownRenderer } from './components/MarkdownRenderer';
2
2
  export { default as AlertBlock } from './components/blocks/AlertBlock.vue';
3
3
  export { default as DataCard } from './components/blocks/DataCard.vue';
4
- export { renderMarkdown } from './composables/useMarkdownParser';
4
+ export { default as ConfirmBlock } from './components/blocks/ConfirmBlock.vue';
5
+ export { default as SelectBlock } from './components/blocks/SelectBlock.vue';
6
+ export { default as FormBlock } from './components/blocks/FormBlock.vue';
7
+ export { default as ProgressBlock } from './components/blocks/ProgressBlock.vue';
8
+ export { default as DataTableBlock } from './components/blocks/DataTableBlock.vue';
9
+ export { default as ActionPills } from './components/blocks/ActionPills.vue';
5
10
  export { useStreamingText } from './composables/useStreamingText';
6
- export { autoCloseContainers } from './utils/autoClose';
7
- export { htmlToVnodes } from './utils/htmlToVnodes';
8
- export type { ComponentMap } from './utils/htmlToVnodes';
11
+ export { useMarkdownParser, renderMarkdown } from './composables/useMarkdownParser';
12
+ export { useAgentEvents } from './composables/useAgentEvents';
13
+ export { createAgentEventBus } from './core/eventBus';
14
+ export { validateProps, sanitizePayload, defaultSchemas } from './core/propValidator';
15
+ export { autoCloseContainers } from './core/autoCloseContainers';
16
+ export type { AgentActionPayload, AgentEventBus, AgentActionHandler } from './core/eventBus';
17
+ export type { ComponentPropsSchema, PropRule } from './core/propValidator';
18
+ export type { ComponentMap, BlockBaseProps } from './types';
19
+ export { PROTOCOL_VERSION, SUPPORTED_BLOCKS } from './types/protocol';
@@ -0,0 +1,16 @@
1
+ import { Component } from 'vue';
2
+ import { AgentEventBus } from '../core/eventBus';
3
+ /**
4
+ * 组件注册表类型
5
+ */
6
+ export type ComponentMap = Record<string, Component>;
7
+ /**
8
+ * 块组件 Props 基础接口
9
+ * 所有内置块组件都继承此接口
10
+ */
11
+ export interface BlockBaseProps {
12
+ /** 块实例唯一 ID(自动生成或 data-id 指定) */
13
+ blockId?: string;
14
+ /** 事件总线引用(由 MarkdownRenderer 注入) */
15
+ eventBus?: AgentEventBus;
16
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Agent UI Protocol 版本
3
+ */
4
+ export declare const PROTOCOL_VERSION = "2.0.0";
5
+ /**
6
+ * 支持的容器块类型
7
+ */
8
+ export declare const SUPPORTED_BLOCKS: readonly ["alert", "card", "confirm", "select", "form", "progress", "datatable", "actions"];
9
+ export type SupportedBlock = typeof SUPPORTED_BLOCKS[number];