wtfai 1.6.5 → 1.6.7

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
@@ -511,6 +511,7 @@ const url = await IframeBridge.uploadFile(file, {
511
511
  在指定集合中创建一条记录。可以通过 `options.entityId` 字段进行二级分类归属(如老师 ID、学生 ID),后续查询时利用此字段能大幅提升检索性能。
512
512
 
513
513
  ```javascript
514
+ // options = { entityId?: string }
514
515
  const id = await IframeBridge.createRecord('notes', {
515
516
  title: 'My Note',
516
517
  content: 'Hello World',
@@ -524,6 +525,7 @@ console.log('创建成功, ID:', id);
524
525
  批量在指定集合中创建多条记录。支持传入可选的配置项如 `entityId`。
525
526
 
526
527
  ```javascript
528
+ // options = { entityId?: string }
527
529
  const ids = await IframeBridge.createRecords('logs', [
528
530
  { level: 'info', message: 'Task started' },
529
531
  { level: 'success', message: 'Task finished' }
@@ -569,6 +571,7 @@ await IframeBridge.deleteRecord('notes', id);
569
571
  分页查询集合中的记录。可以通过传入 `entityId` 来极速筛选归属于特定实体的数据。
570
572
 
571
573
  ```javascript
574
+ // options = { page?: number, pageSize?: number, order?: 'ASC' | 'DESC', entityId?: string }
572
575
  const result = await IframeBridge.listRecords('notes', {
573
576
  page: 1,
574
577
  pageSize: 10,
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Wtfai } from "./client.js";
2
- import { WorkflowSession } from "./session.js";
3
- import { UploadService } from "./upload.js";
4
- import { Markdown, WorkflowRegistry } from "./ui/markdown.js";
5
2
  const src = Wtfai;
6
- export { Markdown, UploadService, WorkflowRegistry, WorkflowSession, src as default };
3
+ export { WorkflowSession } from "./session.js";
4
+ export { UploadService } from "./upload.js";
5
+ export { Markdown, WorkflowRegistry } from "./ui/markdown.js";
6
+ export default src;
package/dist/session.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { SimpleMessage } from '@our-llm/shared/types';
2
- import type { SessionOptions, SessionState, SessionEventListeners, SendInput } from './types';
2
+ import type { SessionOptions, SessionState, SessionEventListeners, SendInput, ListRecordsOptions, ListRecordsResult } from './types';
3
3
  import { UploadService } from './upload';
4
4
  /**
5
5
  * 工作流会话
@@ -114,18 +114,7 @@ export declare class WorkflowSession {
114
114
  * @param id 记录 ID
115
115
  */
116
116
  deleteRecord(collection: string, id: string): Promise<void>;
117
- listRecords(collection: string, options?: {
118
- page?: number;
119
- pageSize?: number;
120
- order?: 'ASC' | 'DESC';
121
- entityId?: string;
122
- }): Promise<{
123
- records: Array<{
124
- id: string;
125
- data: Record<string, unknown>;
126
- }>;
127
- total: number;
128
- }>;
117
+ listRecords(collection: string, options?: ListRecordsOptions): Promise<ListRecordsResult>;
129
118
  /**
130
119
  * 清空集合中的所有数据
131
120
  * @param collection 集合名称
package/dist/types.d.ts CHANGED
@@ -193,3 +193,26 @@ export interface WorkflowInfo {
193
193
  name: string;
194
194
  description: string;
195
195
  }
196
+ /**
197
+ * 分页与过滤选项
198
+ */
199
+ export interface ListRecordsOptions {
200
+ page?: number;
201
+ pageSize?: number;
202
+ order?: 'ASC' | 'DESC';
203
+ entityId?: string;
204
+ }
205
+ /**
206
+ * 数据记录基类
207
+ */
208
+ export interface BaseRecord {
209
+ id: string;
210
+ data: Record<string, unknown>;
211
+ }
212
+ /**
213
+ * 列表查询返回结构
214
+ */
215
+ export interface ListRecordsResult {
216
+ records: BaseRecord[];
217
+ total: number;
218
+ }
package/dist/ui/code.css CHANGED
@@ -1,7 +1,61 @@
1
1
  .iframe-code {
2
2
  aspect-ratio: 16 / 9;
3
+ background: #f9fafb;
4
+ border: 1px solid #e5e7eb;
5
+ border-radius: 12px;
6
+ width: 100%;
7
+ min-width: min(800px, 100%);
8
+ transition: all .2s;
9
+ display: block;
10
+ box-shadow: 0 4px 6px -1px #0000001a;
11
+ }
12
+
13
+ .iframe-code:hover {
14
+ border-color: #d1d5db;
15
+ box-shadow: 0 10px 15px -3px #0000001a;
16
+ }
17
+
18
+ .html-preview-container {
19
+ background: #fff;
20
+ border: 1px solid #e5e7eb;
21
+ border-radius: 12px;
22
+ width: 100%;
23
+ min-width: min(900px, 100%);
24
+ margin: 20px 0;
25
+ transition: all .3s cubic-bezier(.4, 0, .2, 1);
26
+ overflow: hidden;
27
+ box-shadow: 0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;
28
+ }
29
+
30
+ .html-preview-container:hover {
31
+ transform: translateY(-2px);
32
+ box-shadow: 0 20px 25px -5px #0000001a, 0 8px 10px -6px #0000001a;
33
+ }
34
+
35
+ .html-preview-header {
36
+ color: #374151;
37
+ background: #fdfdfd;
38
+ border-bottom: 1px solid #f3f4f6;
39
+ justify-content: space-between;
40
+ align-items: center;
41
+ padding: 10px 16px;
42
+ font-size: 13px;
43
+ font-weight: 600;
44
+ display: flex;
45
+ }
46
+
47
+ .html-preview-header .preview-label {
48
+ color: #2563eb;
49
+ align-items: center;
50
+ gap: 8px;
51
+ display: flex;
52
+ }
53
+
54
+ .html-preview-iframe {
55
+ background: #fff;
3
56
  border: none;
4
- min-width: 50vw;
57
+ width: 100%;
58
+ min-height: 500px;
5
59
  display: block;
6
60
  }
7
61
 
package/dist/ui/code.js CHANGED
@@ -1,14 +1,16 @@
1
- import { jsx } from "react/jsx-runtime";
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useEffect, useRef } from "react";
3
3
  import { CodeHighlighter, Mermaid } from "@ant-design/x";
4
+ import { EyeOutlined, LoadingOutlined } from "@ant-design/icons";
4
5
  import { jsonrepair } from "jsonrepair";
5
6
  import { useWorkflowSession } from "./context.js";
6
7
  import { IframeBridgeHost } from "../iframe-bridge.js";
7
8
  import "./code.css";
8
9
  const Code = (props)=>{
9
10
  var _className_match;
10
- const { className, children } = props;
11
- const lang = (null == className ? void 0 : null == (_className_match = className.match(/language-(\w+)/)) ? void 0 : _className_match[1]) || '';
11
+ const { className, children, streamStatus, lang: infoString } = props;
12
+ const fullLang = infoString || (null == className ? void 0 : null == (_className_match = className.match(/language-([\w:-]+)/)) ? void 0 : _className_match[1]) || '';
13
+ const lang = fullLang.split(':')[0];
12
14
  const session = useWorkflowSession();
13
15
  const iframeRef = useRef(null);
14
16
  const bridgeRef = useRef(null);
@@ -38,6 +40,41 @@ const Code = (props)=>{
38
40
  allow: "clipboard-read; clipboard-write; camera; microphone"
39
41
  });
40
42
  } catch {}
43
+ if ('html:run' === fullLang) {
44
+ const isLoading = 'loading' === streamStatus;
45
+ return /*#__PURE__*/ jsxs("div", {
46
+ className: "html-preview-container",
47
+ children: [
48
+ /*#__PURE__*/ jsxs("div", {
49
+ className: "html-preview-header",
50
+ children: [
51
+ /*#__PURE__*/ jsxs("div", {
52
+ className: "preview-label",
53
+ children: [
54
+ /*#__PURE__*/ jsx(EyeOutlined, {}),
55
+ /*#__PURE__*/ jsx("span", {
56
+ children: "预览"
57
+ })
58
+ ]
59
+ }),
60
+ isLoading && /*#__PURE__*/ jsx(LoadingOutlined, {
61
+ spin: true,
62
+ className: "loading-icon",
63
+ style: {
64
+ color: '#3b82f6'
65
+ }
66
+ })
67
+ ]
68
+ }),
69
+ /*#__PURE__*/ jsx("iframe", {
70
+ srcDoc: children,
71
+ className: "html-preview-iframe",
72
+ title: "HTML Preview",
73
+ sandbox: "allow-scripts allow-forms allow-popups"
74
+ })
75
+ ]
76
+ });
77
+ }
41
78
  return /*#__PURE__*/ jsx(CodeHighlighter, {
42
79
  lang: lang,
43
80
  children: children
@@ -7,5 +7,11 @@ export interface WorkflowInfoMapping {
7
7
  }
8
8
  export declare const SessionContext: import("react").Context<WorkflowSession | null>;
9
9
  export declare const WorkflowRegistryContext: import("react").Context<Record<string, WorkflowInfoMapping>>;
10
+ export declare const MarkdownContext: import("react").Context<{
11
+ isStreaming?: boolean;
12
+ }>;
10
13
  export declare const useWorkflowSession: () => WorkflowSession | null;
11
14
  export declare const useWorkflowRegistry: () => Record<string, WorkflowInfoMapping>;
15
+ export declare const useMarkdownContext: () => {
16
+ isStreaming?: boolean;
17
+ };
@@ -1,6 +1,10 @@
1
1
  import { createContext, useContext } from "react";
2
2
  const SessionContext = createContext(null);
3
3
  const WorkflowRegistryContext = createContext({});
4
+ const MarkdownContext = createContext({
5
+ isStreaming: false
6
+ });
4
7
  const useWorkflowSession = ()=>useContext(SessionContext);
5
8
  const useWorkflowRegistry = ()=>useContext(WorkflowRegistryContext);
6
- export { SessionContext, WorkflowRegistryContext, useWorkflowRegistry, useWorkflowSession };
9
+ const useMarkdownContext = ()=>useContext(MarkdownContext);
10
+ export { MarkdownContext, SessionContext, WorkflowRegistryContext, useMarkdownContext, useWorkflowRegistry, useWorkflowSession };
@@ -8,7 +8,7 @@ import clsx from "clsx";
8
8
  import { Code } from "./code.js";
9
9
  import { XProvider } from "@ant-design/x";
10
10
  import "./markdown.css";
11
- import { SessionContext, WorkflowRegistryContext, useWorkflowRegistry } from "./context.js";
11
+ import { MarkdownContext, SessionContext, WorkflowRegistryContext, useWorkflowRegistry } from "./context.js";
12
12
  const WorkflowRegistry = ({ children, mapping })=>{
13
13
  const parentRegistry = useWorkflowRegistry();
14
14
  const mergedRegistry = {
@@ -29,47 +29,52 @@ const Markdown = ({ className, streaming, config, components, session, ...props
29
29
  locale: zh_CN,
30
30
  children: /*#__PURE__*/ jsx(SessionContext.Provider, {
31
31
  value: session || null,
32
- children: /*#__PURE__*/ jsx(XMarkdown, {
33
- className: clsx(className, 'x-markdown-light'),
34
- streaming: {
35
- ...streaming,
36
- enableAnimation: true
32
+ children: /*#__PURE__*/ jsx(MarkdownContext.Provider, {
33
+ value: {
34
+ isStreaming: !!(null == streaming ? void 0 : streaming.hasNextChunk)
37
35
  },
38
- config: {
39
- ...config,
40
- extensions: Latex()
41
- },
42
- components: {
43
- ...components,
44
- code: Code,
45
- workflow: (props)=>{
46
- const { id, children } = props;
47
- const info = id ? globalRegistry[id] : void 0;
48
- const displayContent = (null == info ? void 0 : info.name) || (Children.count(children) > 0 ? children : id);
49
- return /*#__PURE__*/ jsxs("a", {
50
- onClick: (e)=>{
51
- e.preventDefault();
52
- e.stopPropagation();
53
- null == session || session.emitContentAction({
54
- type: 'workflow',
55
- payload: {
56
- workflowId: id,
57
- extra: null == info ? void 0 : info.extra
58
- }
59
- });
60
- },
61
- className: "workflow-link",
62
- children: [
63
- (null == info ? void 0 : info.icon) && /*#__PURE__*/ jsx("span", {
64
- className: "workflow-link-icon",
65
- children: info.icon
66
- }),
67
- displayContent
68
- ]
69
- });
70
- }
71
- },
72
- ...props
36
+ children: /*#__PURE__*/ jsx(XMarkdown, {
37
+ className: clsx(className, 'x-markdown-light'),
38
+ streaming: {
39
+ ...streaming,
40
+ enableAnimation: true
41
+ },
42
+ config: {
43
+ ...config,
44
+ extensions: Latex()
45
+ },
46
+ components: {
47
+ ...components,
48
+ code: Code,
49
+ workflow: (props)=>{
50
+ const { id, children } = props;
51
+ const info = id ? globalRegistry[id] : void 0;
52
+ const displayContent = (null == info ? void 0 : info.name) || (Children.count(children) > 0 ? children : id);
53
+ return /*#__PURE__*/ jsxs("a", {
54
+ onClick: (e)=>{
55
+ e.preventDefault();
56
+ e.stopPropagation();
57
+ null == session || session.emitContentAction({
58
+ type: 'workflow',
59
+ payload: {
60
+ workflowId: id,
61
+ extra: null == info ? void 0 : info.extra
62
+ }
63
+ });
64
+ },
65
+ className: "workflow-link",
66
+ children: [
67
+ (null == info ? void 0 : info.icon) && /*#__PURE__*/ jsx("span", {
68
+ className: "workflow-link-icon",
69
+ children: info.icon
70
+ }),
71
+ displayContent
72
+ ]
73
+ });
74
+ }
75
+ },
76
+ ...props
77
+ })
73
78
  })
74
79
  })
75
80
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wtfai",
3
- "version": "1.6.5",
3
+ "version": "1.6.7",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -13,36 +13,38 @@
13
13
  "dist"
14
14
  ],
15
15
  "devDependencies": {
16
- "@eslint/js": "^9.39.3",
17
- "@rsbuild/plugin-react": "^1.4.5",
18
- "@rslib/core": "^0.19.6",
16
+ "@eslint/js": "^9.39.4",
17
+ "@rsbuild/plugin-react": "^1.4.6",
18
+ "@rslib/core": "^0.20.0",
19
19
  "@types/react": "^19.2.14",
20
- "eslint": "^9.39.3",
20
+ "eslint": "^9.39.4",
21
21
  "eslint-config-prettier": "^10.1.8",
22
22
  "eslint-plugin-prettier": "^5.5.5",
23
23
  "globals": "^17.4.0",
24
24
  "prettier": "^3.8.1",
25
25
  "react": "^19.2.4",
26
26
  "typescript": "^5.9.3",
27
- "typescript-eslint": "^8.56.1"
27
+ "typescript-eslint": "^8.57.0"
28
28
  },
29
29
  "peerDependencies": {
30
30
  "react": ">=16.9.0",
31
31
  "react-dom": ">=16.9.0"
32
32
  },
33
33
  "dependencies": {
34
+ "@ant-design/icons": "^6.1.0",
34
35
  "@ant-design/x": "^2.3.0",
35
36
  "@ant-design/x-markdown": "^2.3.0",
36
37
  "@microsoft/fetch-event-source": "^2.0.1",
37
38
  "clsx": "^2.1.1",
38
39
  "compressorjs": "^1.2.1",
39
40
  "cos-js-sdk-v5": "^1.10.1",
40
- "jsonrepair": "^3.13.2",
41
+ "jsonrepair": "^3.13.3",
41
42
  "uuid": "^13.0.0",
42
43
  "@our-llm/shared": "3.0.1"
43
44
  },
44
45
  "scripts": {
45
46
  "build": "rslib build",
47
+ "build:sdk": "rslib build -c rslib.config.sdk.ts",
46
48
  "dev": "rslib build --watch",
47
49
  "format": "prettier --write .",
48
50
  "lint": "eslint ."