@lobehub/lobehub 2.0.0-next.75 → 2.0.0-next.77
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 +50 -0
- package/changelog/v1.json +18 -0
- package/package.json +1 -1
- package/packages/model-runtime/src/core/contextBuilders/openai.ts +2 -0
- package/packages/model-runtime/src/core/streams/openai/__snapshots__/responsesStream.test.ts.snap +1007 -0
- package/packages/model-runtime/src/core/streams/openai/openai.test.ts +310 -0
- package/packages/model-runtime/src/core/streams/openai/openai.ts +67 -0
- package/packages/model-runtime/src/providers/minimax/index.ts +36 -6
- package/packages/model-runtime/src/providers/novita/__snapshots__/index.test.ts.snap +584 -0
- package/packages/model-runtime/src/providers/openai/__snapshots__/index.test.ts.snap +517 -0
- package/packages/model-runtime/src/providers/ppio/__snapshots__/index.test.ts.snap +27 -0
- package/packages/utils/src/colorUtils.test.ts +167 -0
- package/src/app/[variants]/(main)/settings/provider/detail/index.tsx +4 -0
- package/src/locales/default/error.ts +2 -2
- /package/src/app/[variants]/(main)/settings/provider/detail/newapi/{page.tsx → index.tsx} +0 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { convertAlphaToSolid } from './colorUtils';
|
|
4
|
+
|
|
5
|
+
describe('colorUtils', () => {
|
|
6
|
+
describe('convertAlphaToSolid', () => {
|
|
7
|
+
it('should convert fully opaque color to same color', () => {
|
|
8
|
+
// Fully opaque (alpha = 1.0)
|
|
9
|
+
const result = convertAlphaToSolid('rgba(255, 0, 0, 1.0)', '#ffffff');
|
|
10
|
+
|
|
11
|
+
expect(result).toBe('#ff0000');
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it('should convert fully transparent color to background color', () => {
|
|
15
|
+
// Fully transparent (alpha = 0.0)
|
|
16
|
+
const result = convertAlphaToSolid('rgba(255, 0, 0, 0.0)', '#0000ff');
|
|
17
|
+
|
|
18
|
+
expect(result).toBe('#0000ff');
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('should blend semi-transparent red over white background', () => {
|
|
22
|
+
// 50% transparent red over white
|
|
23
|
+
const result = convertAlphaToSolid('rgba(255, 0, 0, 0.5)', '#ffffff');
|
|
24
|
+
|
|
25
|
+
// Expected: (255*0.5 + 255*0.5, 0*0.5 + 255*0.5, 0*0.5 + 255*0.5) = (255, 127.5, 127.5)
|
|
26
|
+
expect(result).toBe('#ff8080');
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('should blend semi-transparent blue over black background', () => {
|
|
30
|
+
// 50% transparent blue over black
|
|
31
|
+
const result = convertAlphaToSolid('rgba(0, 0, 255, 0.5)', '#000000');
|
|
32
|
+
|
|
33
|
+
// Expected: (0*0.5 + 0*0.5, 0*0.5 + 0*0.5, 255*0.5 + 0*0.5) = (0, 0, 127.5)
|
|
34
|
+
expect(result).toBe('#000080');
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('should handle hex color format for foreground', () => {
|
|
38
|
+
// Using hex with alpha
|
|
39
|
+
const result = convertAlphaToSolid('#ff000080', '#ffffff');
|
|
40
|
+
|
|
41
|
+
// #ff000080 is red with 50% opacity (80 in hex = 128/255 ≈ 0.5)
|
|
42
|
+
expect(result).toBe('#ff8080');
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('should handle named colors', () => {
|
|
46
|
+
const result = convertAlphaToSolid('rgba(255, 0, 0, 0.5)', 'white');
|
|
47
|
+
|
|
48
|
+
expect(result).toBe('#ff8080');
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('should blend with 25% opacity', () => {
|
|
52
|
+
// 25% opacity red over white
|
|
53
|
+
const result = convertAlphaToSolid('rgba(255, 0, 0, 0.25)', '#ffffff');
|
|
54
|
+
|
|
55
|
+
// Expected: (255*0.25 + 255*0.75, 0*0.25 + 255*0.75, 0*0.25 + 255*0.75) = (255, 191.25, 191.25)
|
|
56
|
+
expect(result).toBe('#ffbfbf');
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('should blend with 75% opacity', () => {
|
|
60
|
+
// 75% opacity red over white
|
|
61
|
+
const result = convertAlphaToSolid('rgba(255, 0, 0, 0.75)', '#ffffff');
|
|
62
|
+
|
|
63
|
+
// Expected: (255*0.75 + 255*0.25, 0*0.75 + 255*0.25, 0*0.75 + 255*0.25) = (255, 63.75, 63.75)
|
|
64
|
+
expect(result).toBe('#ff4040');
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('should handle complex color blending', () => {
|
|
68
|
+
// Green with 60% opacity over blue
|
|
69
|
+
const result = convertAlphaToSolid('rgba(0, 255, 0, 0.6)', '#0000ff');
|
|
70
|
+
|
|
71
|
+
// Expected: (0*0.6 + 0*0.4, 255*0.6 + 0*0.4, 0*0.6 + 255*0.4) = (0, 153, 102)
|
|
72
|
+
expect(result).toBe('#009966');
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('should blend gray colors', () => {
|
|
76
|
+
// 50% gray over black
|
|
77
|
+
const result = convertAlphaToSolid('rgba(128, 128, 128, 0.5)', '#000000');
|
|
78
|
+
|
|
79
|
+
// Expected: (128*0.5 + 0*0.5, 128*0.5 + 0*0.5, 128*0.5 + 0*0.5) = (64, 64, 64)
|
|
80
|
+
expect(result).toBe('#404040');
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('should handle white foreground over colored background', () => {
|
|
84
|
+
// 30% white over red
|
|
85
|
+
const result = convertAlphaToSolid('rgba(255, 255, 255, 0.3)', '#ff0000');
|
|
86
|
+
|
|
87
|
+
// Expected: (255*0.3 + 255*0.7, 255*0.3 + 0*0.7, 255*0.3 + 0*0.7) = (255, 76.5, 76.5)
|
|
88
|
+
expect(result).toBe('#ff4d4d');
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('should handle both colors with uppercase hex format', () => {
|
|
92
|
+
const result = convertAlphaToSolid('rgba(255, 0, 0, 0.5)', '#FFFFFF');
|
|
93
|
+
|
|
94
|
+
expect(result).toBe('#ff8080');
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('should handle RGB format for background', () => {
|
|
98
|
+
const result = convertAlphaToSolid('rgba(0, 255, 0, 0.5)', 'rgb(0, 0, 255)');
|
|
99
|
+
|
|
100
|
+
expect(result).toBe('#008080');
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('should blend dark color over light background', () => {
|
|
104
|
+
// Dark gray (20, 20, 20) with 80% opacity over white
|
|
105
|
+
const result = convertAlphaToSolid('rgba(20, 20, 20, 0.8)', '#ffffff');
|
|
106
|
+
|
|
107
|
+
// Expected: (20*0.8 + 255*0.2, 20*0.8 + 255*0.2, 20*0.8 + 255*0.2) = (67, 67, 67)
|
|
108
|
+
expect(result).toBe('#434343');
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('should blend light color over dark background', () => {
|
|
112
|
+
// Light gray (200, 200, 200) with 20% opacity over black
|
|
113
|
+
const result = convertAlphaToSolid('rgba(200, 200, 200, 0.2)', '#000000');
|
|
114
|
+
|
|
115
|
+
// Expected: (200*0.2 + 0*0.8, 200*0.2 + 0*0.8, 200*0.2 + 0*0.8) = (40, 40, 40)
|
|
116
|
+
expect(result).toBe('#282828');
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('should handle three-digit hex codes', () => {
|
|
120
|
+
// #f00 is red, expanded to #ff0000
|
|
121
|
+
const result = convertAlphaToSolid('rgba(255, 0, 0, 0.5)', '#fff');
|
|
122
|
+
|
|
123
|
+
expect(result).toBe('#ff8080');
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('should return lowercase hex format', () => {
|
|
127
|
+
const result = convertAlphaToSolid('rgba(255, 165, 0, 1.0)', '#000000');
|
|
128
|
+
|
|
129
|
+
// Orange color
|
|
130
|
+
expect(result).toMatch(/^#[0-9a-f]{6}$/);
|
|
131
|
+
expect(result).toBe('#ffa500');
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('should handle edge case with very low alpha value', () => {
|
|
135
|
+
// Nearly transparent
|
|
136
|
+
const result = convertAlphaToSolid('rgba(255, 0, 0, 0.01)', '#0000ff');
|
|
137
|
+
|
|
138
|
+
// Should be very close to blue background
|
|
139
|
+
expect(result).toBe('#0300fc');
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('should handle edge case with very high alpha value', () => {
|
|
143
|
+
// Nearly opaque
|
|
144
|
+
const result = convertAlphaToSolid('rgba(255, 0, 0, 0.99)', '#0000ff');
|
|
145
|
+
|
|
146
|
+
// Should be very close to red foreground
|
|
147
|
+
expect(result).toBe('#fc0003');
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it('should handle blending complementary colors', () => {
|
|
151
|
+
// Cyan with 50% opacity over red
|
|
152
|
+
const result = convertAlphaToSolid('rgba(0, 255, 255, 0.5)', '#ff0000');
|
|
153
|
+
|
|
154
|
+
// Expected: (0*0.5 + 255*0.5, 255*0.5 + 0*0.5, 255*0.5 + 0*0.5) = (127.5, 127.5, 127.5)
|
|
155
|
+
expect(result).toBe('#808080');
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('should produce same result regardless of input color format', () => {
|
|
159
|
+
const result1 = convertAlphaToSolid('#ff000080', '#ffffff');
|
|
160
|
+
const result2 = convertAlphaToSolid('rgba(255, 0, 0, 0.5)', 'white');
|
|
161
|
+
const result3 = convertAlphaToSolid('rgba(255, 0, 0, 0.5)', '#fff');
|
|
162
|
+
|
|
163
|
+
expect(result1).toBe(result2);
|
|
164
|
+
expect(result2).toBe(result3);
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
});
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import NewAPI from './newapi';
|
|
1
2
|
import ProviderGrid from '../(list)/ProviderGrid';
|
|
2
3
|
import Azure from './azure';
|
|
3
4
|
import AzureAI from './azureai';
|
|
@@ -38,6 +39,9 @@ const ProviderDetailPage = (props: { id?: string | null }) => {
|
|
|
38
39
|
case 'ollama': {
|
|
39
40
|
return <Ollama />;
|
|
40
41
|
}
|
|
42
|
+
case 'newapi': {
|
|
43
|
+
return <NewAPI />;
|
|
44
|
+
}
|
|
41
45
|
case 'openai': {
|
|
42
46
|
return <OpenAI />;
|
|
43
47
|
}
|
|
@@ -111,12 +111,12 @@ export default {
|
|
|
111
111
|
LocationNotSupportError:
|
|
112
112
|
'很抱歉,你的所在地区不支持此模型服务,可能是由于区域限制或服务未开通。请确认当前地区是否支持使用此服务,或尝试使用切换到其他地区后重试。',
|
|
113
113
|
InsufficientQuota:
|
|
114
|
-
'很抱歉,该密钥的配额(quota)已达上限,请检查账户余额是否充足,或增大密钥配额后再试',
|
|
114
|
+
'很抱歉,该密钥的配额 (quota) 已达上限,请检查账户余额是否充足,或增大密钥配额后再试',
|
|
115
115
|
ModelNotFound:
|
|
116
116
|
'很抱歉,无法请求到相应的模型,可能是模型不存在或者没有访问权限导致,请更换 API Key 或调整访问权限后重试',
|
|
117
117
|
ExceededContextWindow: '当前请求内容超出模型可处理的长度,请减少内容量后重试',
|
|
118
118
|
QuotaLimitReached:
|
|
119
|
-
'很抱歉,当前 Token 用量或请求次数已达该密钥的配额(quota)上限,请增加该密钥的配额或稍后再试',
|
|
119
|
+
'很抱歉,当前 Token 用量或请求次数已达该密钥的配额 (quota) 上限,请增加该密钥的配额或稍后再试',
|
|
120
120
|
PermissionDenied: '很抱歉,你没有权限访问该服务,请检查你的密钥是否有访问权限',
|
|
121
121
|
InvalidProviderAPIKey: '{{provider}} API Key 不正确或为空,请检查 {{provider}} API Key 后重试',
|
|
122
122
|
ProviderBizError: '请求 {{provider}} 服务出错,请根据以下信息排查或重试',
|
|
File without changes
|