dsh-cait 1.0.3 → 1.0.4
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/CHANGELOG.md +367 -352
- package/LICENSE +201 -201
- package/README.ja.md +4 -3
- package/README.md +424 -423
- package/README.zh-CN.md +391 -390
- package/client/components.js +2377 -2377
- package/client/helpers.js +103 -103
- package/client/locales.js +730 -730
- package/client/rpc.js +93 -93
- package/client/styles.js +258 -258
- package/client.js +3556 -3556
- package/icon.svg +8 -8
- package/index.js +45 -45
- package/lib/api.js +223 -223
- package/lib/docx.js +389 -389
- package/lib/errors.js +8 -8
- package/lib/formats.js +917 -917
- package/lib/glossary.js +178 -178
- package/lib/import-export.js +605 -605
- package/lib/libraries.js +183 -183
- package/lib/markdown.js +28 -28
- package/lib/mt.js +152 -152
- package/lib/persistence.js +321 -321
- package/lib/pptx.js +89 -89
- package/lib/segmenter.js +84 -84
- package/lib/similarity.js +113 -113
- package/lib/store-utils.js +339 -339
- package/lib/store.js +734 -734
- package/lib/tm.js +160 -160
- package/lib/tmx.js +85 -85
- package/lib/tools.js +472 -472
- package/lib/xlsx.js +218 -218
- package/lib/xml.js +31 -31
- package/locale/en.json +11 -11
- package/locale/zh.json +11 -11
- package/package.json +83 -83
- package/scripts/build-client.mjs +13 -13
package/lib/mt.js
CHANGED
|
@@ -1,152 +1,152 @@
|
|
|
1
|
-
export const MOCK_PROVIDER = 'mock'
|
|
2
|
-
export const MOCK_MODEL = 'cait-mock'
|
|
3
|
-
export const NO_ROUTE_MESSAGE = '未配置 DSH 模型路由,当前使用术语替换(离线)。'
|
|
4
|
-
export const NO_MODEL_MESSAGE = '所选 DSH 模型路由没有可用模型,当前使用术语替换(离线)。'
|
|
5
|
-
|
|
6
|
-
function service(ctx, name) {
|
|
7
|
-
try {
|
|
8
|
-
return typeof ctx?.get === 'function' ? ctx.get(name) : ctx?.[name]
|
|
9
|
-
} catch {
|
|
10
|
-
return undefined
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
function configuredProviderIds(loader) {
|
|
15
|
-
const ids = new Set()
|
|
16
|
-
try {
|
|
17
|
-
for (const entry of loader?.entries?.() ?? []) {
|
|
18
|
-
const providers = entry?.options?.config?.providers
|
|
19
|
-
if (!providers || typeof providers !== 'object' || Array.isArray(providers)) continue
|
|
20
|
-
for (const id of Object.keys(providers)) ids.add(id)
|
|
21
|
-
}
|
|
22
|
-
} catch {
|
|
23
|
-
// Loader discovery is best-effort; the llm adapter catalog remains usable.
|
|
24
|
-
}
|
|
25
|
-
return ids
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function normalizeModels(catalog) {
|
|
29
|
-
if (!Array.isArray(catalog)) return []
|
|
30
|
-
const seen = new Set()
|
|
31
|
-
const models = []
|
|
32
|
-
for (const item of catalog) {
|
|
33
|
-
const id = String(item?.id ?? '').trim()
|
|
34
|
-
if (!id || seen.has(id)) continue
|
|
35
|
-
seen.add(id)
|
|
36
|
-
models.push({ id, name: String(item?.name ?? id).trim() || id })
|
|
37
|
-
}
|
|
38
|
-
return models
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
async function discoverRoutes(llm, loader) {
|
|
42
|
-
if (!llm || typeof llm.listProviders !== 'function') {
|
|
43
|
-
return { providers: [], fallback: true, message: NO_ROUTE_MESSAGE }
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
let adapters
|
|
47
|
-
try {
|
|
48
|
-
adapters = await llm.listProviders()
|
|
49
|
-
} catch {
|
|
50
|
-
adapters = []
|
|
51
|
-
}
|
|
52
|
-
if (!Array.isArray(adapters)) adapters = []
|
|
53
|
-
|
|
54
|
-
const configured = configuredProviderIds(loader)
|
|
55
|
-
const hasLoaderRoutes = adapters.some((adapter) => configured.has(String(adapter?.id ?? '')))
|
|
56
|
-
const providers = []
|
|
57
|
-
const seen = new Set()
|
|
58
|
-
|
|
59
|
-
for (const adapter of adapters) {
|
|
60
|
-
const id = String(adapter?.id ?? '').trim()
|
|
61
|
-
if (!id || id === MOCK_PROVIDER || seen.has(id)) continue
|
|
62
|
-
// When the loader exposes provider configs, use it to avoid listing adapters
|
|
63
|
-
// that have no configured route. If loader discovery found nothing, trust the
|
|
64
|
-
// adapter catalog (some providers are registered outside loader entries).
|
|
65
|
-
if (hasLoaderRoutes && !configured.has(id)) continue
|
|
66
|
-
seen.add(id)
|
|
67
|
-
|
|
68
|
-
let models = []
|
|
69
|
-
if (typeof llm.listModels === 'function') {
|
|
70
|
-
try {
|
|
71
|
-
models = normalizeModels(await llm.listModels(id))
|
|
72
|
-
} catch {
|
|
73
|
-
models = []
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
providers.push({
|
|
77
|
-
id,
|
|
78
|
-
name: String(adapter?.name ?? id).trim() || id,
|
|
79
|
-
models,
|
|
80
|
-
})
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
return {
|
|
84
|
-
providers,
|
|
85
|
-
fallback: providers.length === 0,
|
|
86
|
-
message: providers.length ? '' : NO_ROUTE_MESSAGE,
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export function createMtRuntime(ctx) {
|
|
91
|
-
const llm = service(ctx, 'llm')
|
|
92
|
-
const loader = service(ctx, 'loader')
|
|
93
|
-
let cached = null
|
|
94
|
-
let cachedAt = 0
|
|
95
|
-
|
|
96
|
-
async function listRoutes({ refresh = false } = {}) {
|
|
97
|
-
if (!refresh && cached && Date.now() - cachedAt < 30_000) return cached
|
|
98
|
-
cached = await discoverRoutes(llm, loader)
|
|
99
|
-
cachedAt = Date.now()
|
|
100
|
-
return cached
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return {
|
|
104
|
-
available: Boolean(llm && typeof llm.stream === 'function'),
|
|
105
|
-
listRoutes,
|
|
106
|
-
async stream(options) {
|
|
107
|
-
if (!llm || typeof llm.stream !== 'function') {
|
|
108
|
-
const error = new Error('DSH llm service is not available')
|
|
109
|
-
error.code = 'LLM_UNAVAILABLE'
|
|
110
|
-
throw error
|
|
111
|
-
}
|
|
112
|
-
return llm.stream(options)
|
|
113
|
-
},
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
export async function collectStreamText(chunks) {
|
|
118
|
-
if (!chunks || typeof chunks[Symbol.asyncIterator] !== 'function') {
|
|
119
|
-
const error = new Error('DSH 模型路由没有返回可迭代的流')
|
|
120
|
-
error.code = 'MT_STREAM_INVALID'
|
|
121
|
-
throw error
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
let text = ''
|
|
125
|
-
let finish = null
|
|
126
|
-
for await (const chunk of chunks) {
|
|
127
|
-
if (!chunk || typeof chunk !== 'object') continue
|
|
128
|
-
if (chunk.type === 'text-delta') {
|
|
129
|
-
text += String(chunk.text ?? '')
|
|
130
|
-
} else if (chunk.type === 'finish') {
|
|
131
|
-
finish = chunk
|
|
132
|
-
break
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
if (!finish) {
|
|
137
|
-
const error = new Error('DSH 模型路由未返回完成事件')
|
|
138
|
-
error.code = 'MT_STREAM_INCOMPLETE'
|
|
139
|
-
throw error
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
const reason = finish.reason || {}
|
|
143
|
-
if (reason.kind !== 'stop') {
|
|
144
|
-
const failure = reason.failure || {}
|
|
145
|
-
const error = new Error(failure.message || 'DSH 模型路由调用失败')
|
|
146
|
-
error.code = failure.code || (reason.kind === 'aborted' ? 'MT_ABORTED' : 'MT_STREAM_FAILED')
|
|
147
|
-
error.status = failure.status
|
|
148
|
-
throw error
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
return text.trim()
|
|
152
|
-
}
|
|
1
|
+
export const MOCK_PROVIDER = 'mock'
|
|
2
|
+
export const MOCK_MODEL = 'cait-mock'
|
|
3
|
+
export const NO_ROUTE_MESSAGE = '未配置 DSH 模型路由,当前使用术语替换(离线)。'
|
|
4
|
+
export const NO_MODEL_MESSAGE = '所选 DSH 模型路由没有可用模型,当前使用术语替换(离线)。'
|
|
5
|
+
|
|
6
|
+
function service(ctx, name) {
|
|
7
|
+
try {
|
|
8
|
+
return typeof ctx?.get === 'function' ? ctx.get(name) : ctx?.[name]
|
|
9
|
+
} catch {
|
|
10
|
+
return undefined
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function configuredProviderIds(loader) {
|
|
15
|
+
const ids = new Set()
|
|
16
|
+
try {
|
|
17
|
+
for (const entry of loader?.entries?.() ?? []) {
|
|
18
|
+
const providers = entry?.options?.config?.providers
|
|
19
|
+
if (!providers || typeof providers !== 'object' || Array.isArray(providers)) continue
|
|
20
|
+
for (const id of Object.keys(providers)) ids.add(id)
|
|
21
|
+
}
|
|
22
|
+
} catch {
|
|
23
|
+
// Loader discovery is best-effort; the llm adapter catalog remains usable.
|
|
24
|
+
}
|
|
25
|
+
return ids
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function normalizeModels(catalog) {
|
|
29
|
+
if (!Array.isArray(catalog)) return []
|
|
30
|
+
const seen = new Set()
|
|
31
|
+
const models = []
|
|
32
|
+
for (const item of catalog) {
|
|
33
|
+
const id = String(item?.id ?? '').trim()
|
|
34
|
+
if (!id || seen.has(id)) continue
|
|
35
|
+
seen.add(id)
|
|
36
|
+
models.push({ id, name: String(item?.name ?? id).trim() || id })
|
|
37
|
+
}
|
|
38
|
+
return models
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async function discoverRoutes(llm, loader) {
|
|
42
|
+
if (!llm || typeof llm.listProviders !== 'function') {
|
|
43
|
+
return { providers: [], fallback: true, message: NO_ROUTE_MESSAGE }
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
let adapters
|
|
47
|
+
try {
|
|
48
|
+
adapters = await llm.listProviders()
|
|
49
|
+
} catch {
|
|
50
|
+
adapters = []
|
|
51
|
+
}
|
|
52
|
+
if (!Array.isArray(adapters)) adapters = []
|
|
53
|
+
|
|
54
|
+
const configured = configuredProviderIds(loader)
|
|
55
|
+
const hasLoaderRoutes = adapters.some((adapter) => configured.has(String(adapter?.id ?? '')))
|
|
56
|
+
const providers = []
|
|
57
|
+
const seen = new Set()
|
|
58
|
+
|
|
59
|
+
for (const adapter of adapters) {
|
|
60
|
+
const id = String(adapter?.id ?? '').trim()
|
|
61
|
+
if (!id || id === MOCK_PROVIDER || seen.has(id)) continue
|
|
62
|
+
// When the loader exposes provider configs, use it to avoid listing adapters
|
|
63
|
+
// that have no configured route. If loader discovery found nothing, trust the
|
|
64
|
+
// adapter catalog (some providers are registered outside loader entries).
|
|
65
|
+
if (hasLoaderRoutes && !configured.has(id)) continue
|
|
66
|
+
seen.add(id)
|
|
67
|
+
|
|
68
|
+
let models = []
|
|
69
|
+
if (typeof llm.listModels === 'function') {
|
|
70
|
+
try {
|
|
71
|
+
models = normalizeModels(await llm.listModels(id))
|
|
72
|
+
} catch {
|
|
73
|
+
models = []
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
providers.push({
|
|
77
|
+
id,
|
|
78
|
+
name: String(adapter?.name ?? id).trim() || id,
|
|
79
|
+
models,
|
|
80
|
+
})
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return {
|
|
84
|
+
providers,
|
|
85
|
+
fallback: providers.length === 0,
|
|
86
|
+
message: providers.length ? '' : NO_ROUTE_MESSAGE,
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function createMtRuntime(ctx) {
|
|
91
|
+
const llm = service(ctx, 'llm')
|
|
92
|
+
const loader = service(ctx, 'loader')
|
|
93
|
+
let cached = null
|
|
94
|
+
let cachedAt = 0
|
|
95
|
+
|
|
96
|
+
async function listRoutes({ refresh = false } = {}) {
|
|
97
|
+
if (!refresh && cached && Date.now() - cachedAt < 30_000) return cached
|
|
98
|
+
cached = await discoverRoutes(llm, loader)
|
|
99
|
+
cachedAt = Date.now()
|
|
100
|
+
return cached
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
available: Boolean(llm && typeof llm.stream === 'function'),
|
|
105
|
+
listRoutes,
|
|
106
|
+
async stream(options) {
|
|
107
|
+
if (!llm || typeof llm.stream !== 'function') {
|
|
108
|
+
const error = new Error('DSH llm service is not available')
|
|
109
|
+
error.code = 'LLM_UNAVAILABLE'
|
|
110
|
+
throw error
|
|
111
|
+
}
|
|
112
|
+
return llm.stream(options)
|
|
113
|
+
},
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export async function collectStreamText(chunks) {
|
|
118
|
+
if (!chunks || typeof chunks[Symbol.asyncIterator] !== 'function') {
|
|
119
|
+
const error = new Error('DSH 模型路由没有返回可迭代的流')
|
|
120
|
+
error.code = 'MT_STREAM_INVALID'
|
|
121
|
+
throw error
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
let text = ''
|
|
125
|
+
let finish = null
|
|
126
|
+
for await (const chunk of chunks) {
|
|
127
|
+
if (!chunk || typeof chunk !== 'object') continue
|
|
128
|
+
if (chunk.type === 'text-delta') {
|
|
129
|
+
text += String(chunk.text ?? '')
|
|
130
|
+
} else if (chunk.type === 'finish') {
|
|
131
|
+
finish = chunk
|
|
132
|
+
break
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (!finish) {
|
|
137
|
+
const error = new Error('DSH 模型路由未返回完成事件')
|
|
138
|
+
error.code = 'MT_STREAM_INCOMPLETE'
|
|
139
|
+
throw error
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const reason = finish.reason || {}
|
|
143
|
+
if (reason.kind !== 'stop') {
|
|
144
|
+
const failure = reason.failure || {}
|
|
145
|
+
const error = new Error(failure.message || 'DSH 模型路由调用失败')
|
|
146
|
+
error.code = failure.code || (reason.kind === 'aborted' ? 'MT_ABORTED' : 'MT_STREAM_FAILED')
|
|
147
|
+
error.status = failure.status
|
|
148
|
+
throw error
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return text.trim()
|
|
152
|
+
}
|