@textbus/xnote 0.3.8 → 1.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/ai.service.ts +124 -0
- package/bundles/fonts/textbus.svg +51 -43
- package/bundles/fonts/textbus.ttf +0 -0
- package/bundles/fonts/textbus.woff +0 -0
- package/bundles/index.css +2 -2
- package/bundles/index.esm.css +2 -2
- package/bundles/index.esm.js +640 -378
- package/bundles/index.js +639 -375
- package/bundles/plugins/hooks/popup-position.d.ts +4 -0
- package/bundles/plugins/tools/_api.d.ts +1 -0
- package/bundles/plugins/tools/ai.tool.d.ts +4 -0
- package/bundles/services/_api.d.ts +1 -0
- package/bundles/services/llm.service.d.ts +24 -0
- package/bundles/textbus/components/table/tools/complete.d.ts +1 -1
- package/index.tsx +17 -11
- package/lerna.json +1 -4
- package/package.json +12 -9
package/ai.service.ts
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { Observable } from '@textbus/core'
|
|
2
|
+
|
|
3
|
+
import { LLMService, LLMParams, LLMTranslateParams } from './src/services/llm.service'
|
|
4
|
+
|
|
5
|
+
export class AiService extends LLMService {
|
|
6
|
+
private baseUrl = '/api/llm'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 创建 SSE 流式请求(使用 POST 方法支持长内容)
|
|
10
|
+
*/
|
|
11
|
+
private createSSEStream(endpoint: string, params: LLMParams | LLMTranslateParams): Observable<string> {
|
|
12
|
+
return new Observable<string>(observer => {
|
|
13
|
+
const url = `${this.baseUrl}${endpoint}`
|
|
14
|
+
let isComplete = false
|
|
15
|
+
|
|
16
|
+
// 使用 fetch API 支持 POST 请求和 SSE 流
|
|
17
|
+
fetch(url, {
|
|
18
|
+
method: 'POST',
|
|
19
|
+
headers: {
|
|
20
|
+
'Content-Type': 'application/json',
|
|
21
|
+
'Accept': 'text/event-stream',
|
|
22
|
+
'x-api-key': 'xnote'
|
|
23
|
+
},
|
|
24
|
+
body: JSON.stringify(params)
|
|
25
|
+
})
|
|
26
|
+
.then(response => {
|
|
27
|
+
if (!response.ok) {
|
|
28
|
+
throw new Error(`HTTP error! status: ${response.status}`)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const reader = response.body?.getReader()
|
|
32
|
+
if (!reader) {
|
|
33
|
+
throw new Error('Response body is not readable')
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const decoder = new TextDecoder()
|
|
37
|
+
let buffer = ''
|
|
38
|
+
|
|
39
|
+
const readStream = () => {
|
|
40
|
+
reader.read().then(({ done, value }) => {
|
|
41
|
+
if (done || isComplete) {
|
|
42
|
+
observer.complete()
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// 解码并处理 SSE 数据
|
|
47
|
+
buffer += decoder.decode(value, { stream: true })
|
|
48
|
+
|
|
49
|
+
// 解析 SSE 格式的数据
|
|
50
|
+
const lines = buffer.split('\n')
|
|
51
|
+
buffer = lines.pop() || '' // 保留最后一个不完整的行
|
|
52
|
+
|
|
53
|
+
for (const line of lines) {
|
|
54
|
+
if (line.startsWith('data: ')) {
|
|
55
|
+
const data = line.slice(6)
|
|
56
|
+
// 检查是否是结束标记
|
|
57
|
+
if (data === '[DONE]') {
|
|
58
|
+
isComplete = true
|
|
59
|
+
observer.complete()
|
|
60
|
+
return
|
|
61
|
+
}
|
|
62
|
+
observer.next(data)
|
|
63
|
+
} else if (line.startsWith('event: error')) {
|
|
64
|
+
// 处理错误事件
|
|
65
|
+
const errorLine = lines[lines.indexOf(line) + 1]
|
|
66
|
+
if (errorLine && errorLine.startsWith('data: ')) {
|
|
67
|
+
observer.error(new Error(errorLine.slice(6)))
|
|
68
|
+
}
|
|
69
|
+
isComplete = true
|
|
70
|
+
observer.complete()
|
|
71
|
+
return
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// 继续读取流
|
|
76
|
+
readStream()
|
|
77
|
+
}).catch(error => {
|
|
78
|
+
observer.error(error)
|
|
79
|
+
})
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
readStream()
|
|
83
|
+
})
|
|
84
|
+
.catch(error => {
|
|
85
|
+
observer.error(error)
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
// 返回清理函数
|
|
89
|
+
return () => {
|
|
90
|
+
isComplete = true
|
|
91
|
+
}
|
|
92
|
+
})
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** 续写 */
|
|
96
|
+
continue(params: LLMParams): Observable<string> {
|
|
97
|
+
return this.createSSEStream('/continue', params)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** 润色内容 */
|
|
101
|
+
polish(params: LLMParams): Observable<string> {
|
|
102
|
+
return this.createSSEStream('/polish', params)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** 简化内容 */
|
|
106
|
+
simplify(params: LLMParams): Observable<string> {
|
|
107
|
+
return this.createSSEStream('/simplify', params)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** 丰富内容 */
|
|
111
|
+
enrich(params: LLMParams): Observable<string> {
|
|
112
|
+
return this.createSSEStream('/enrich', params)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** 翻译内容 */
|
|
116
|
+
translate(params: LLMTranslateParams): Observable<string> {
|
|
117
|
+
return this.createSSEStream('/translate', params)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** 总结内容 */
|
|
121
|
+
summarize(params: LLMParams): Observable<string> {
|
|
122
|
+
return this.createSSEStream('/summarize', params)
|
|
123
|
+
}
|
|
124
|
+
}
|