@lobehub/chat 1.104.0 β†’ 1.104.1

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.
Files changed (23) hide show
  1. package/.cursor/rules/code-review.mdc +2 -0
  2. package/.cursor/rules/typescript.mdc +3 -1
  3. package/CHANGELOG.md +25 -0
  4. package/changelog/v1.json +9 -0
  5. package/package.json +1 -1
  6. package/src/app/[variants]/(main)/image/features/GenerationFeed/BatchItem.tsx +6 -1
  7. package/src/app/[variants]/(main)/image/features/GenerationFeed/GenerationItem/ErrorState.tsx +3 -2
  8. package/src/app/[variants]/(main)/image/features/GenerationFeed/GenerationItem/LoadingState.tsx +27 -24
  9. package/src/app/[variants]/(main)/image/features/GenerationFeed/GenerationItem/SuccessState.tsx +14 -3
  10. package/src/app/[variants]/(main)/image/features/GenerationFeed/GenerationItem/index.tsx +4 -7
  11. package/src/app/[variants]/(main)/image/features/GenerationFeed/GenerationItem/types.ts +3 -0
  12. package/src/app/[variants]/(main)/image/features/GenerationFeed/GenerationItem/utils.test.ts +600 -0
  13. package/src/app/[variants]/(main)/image/features/GenerationFeed/GenerationItem/utils.ts +126 -7
  14. package/src/const/imageGeneration.ts +18 -0
  15. package/src/libs/model-runtime/utils/openaiCompatibleFactory/index.test.ts +3 -0
  16. package/src/libs/model-runtime/utils/openaiCompatibleFactory/index.ts +7 -5
  17. package/src/libs/model-runtime/utils/streams/openai/openai.ts +8 -4
  18. package/src/libs/model-runtime/utils/usageConverter.test.ts +45 -1
  19. package/src/libs/model-runtime/utils/usageConverter.ts +6 -2
  20. package/src/server/services/generation/index.test.ts +848 -0
  21. package/src/server/services/generation/index.ts +90 -69
  22. package/src/utils/number.test.ts +101 -1
  23. package/src/utils/number.ts +42 -0
@@ -26,6 +26,8 @@ Gather the modified code and context. Please strictly follow the process below:
26
26
 
27
27
  ### Code Style
28
28
 
29
+ read [typescript.mdc](mdc:.cursor/rules/typescript.mdc) to learn the project's code style.
30
+
29
31
  - Ensure JSDoc comments accurately reflect the implementation; update them when needed.
30
32
  - Look for opportunities to simplify or modernize code with the latest JavaScript/TypeScript features.
31
33
  - Prefer `async`/`await` over callbacks or chained `.then` promises.
@@ -16,4 +16,6 @@ TypeScript Code Style Guide:
16
16
  - Always refactor repeated logic into a reusable function
17
17
  - Don't remove meaningful code comments, be sure to keep original comments when providing applied code
18
18
  - Update the code comments when needed after you modify the related code
19
- - Please respect my prettier preferences when you provide code
19
+ - Please respect my prettier preferences when you provide code
20
+ - Prefer object destructuring when accessing and using properties
21
+ - Prefer async version api than sync version, eg: use readFile from 'fs/promises' instead of 'fs'
package/CHANGELOG.md CHANGED
@@ -2,6 +2,31 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ### [Version 1.104.1](https://github.com/lobehub/lobe-chat/compare/v1.104.0...v1.104.1)
6
+
7
+ <sup>Released on **2025-07-25**</sup>
8
+
9
+ #### πŸ› Bug Fixes
10
+
11
+ - **misc**: Update convertUsage to handle XAI provider and adjust OpenAIStream to pass provider.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### What's fixed
19
+
20
+ - **misc**: Update convertUsage to handle XAI provider and adjust OpenAIStream to pass provider, closes [#8557](https://github.com/lobehub/lobe-chat/issues/8557) ([d1e4a54](https://github.com/lobehub/lobe-chat/commit/d1e4a54))
21
+
22
+ </details>
23
+
24
+ <div align="right">
25
+
26
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
27
+
28
+ </div>
29
+
5
30
  ## [Version 1.104.0](https://github.com/lobehub/lobe-chat/compare/v1.103.2...v1.104.0)
6
31
 
7
32
  <sup>Released on **2025-07-24**</sup>
package/changelog/v1.json CHANGED
@@ -1,4 +1,13 @@
1
1
  [
2
+ {
3
+ "children": {
4
+ "fixes": [
5
+ "Update convertUsage to handle XAI provider and adjust OpenAIStream to pass provider."
6
+ ]
7
+ },
8
+ "date": "2025-07-25",
9
+ "version": "1.104.1"
10
+ },
2
11
  {
3
12
  "children": {
4
13
  "features": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "1.104.0",
3
+ "version": "1.104.1",
4
4
  "description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
5
5
  "keywords": [
6
6
  "framework",
@@ -20,6 +20,7 @@ import { AsyncTaskErrorType } from '@/types/asyncTask';
20
20
  import { GenerationBatch } from '@/types/generation';
21
21
 
22
22
  import { GenerationItem } from './GenerationItem';
23
+ import { DEFAULT_MAX_ITEM_WIDTH } from './GenerationItem/utils';
23
24
  import { ReferenceImages } from './ReferenceImages';
24
25
 
25
26
  const useStyles = createStyles(({ cx, css, token }) => ({
@@ -182,7 +183,11 @@ export const GenerationBatchItem = memo<GenerationBatchItemProps>(({ batch }) =>
182
183
  {promptAndMetadata}
183
184
  </>
184
185
  )}
185
- <Grid maxItemWidth={200} ref={imageGridRef} rows={batch.generations.length || 4}>
186
+ <Grid
187
+ maxItemWidth={DEFAULT_MAX_ITEM_WIDTH}
188
+ ref={imageGridRef}
189
+ rows={batch.generations.length}
190
+ >
186
191
  {batch.generations.map((generation) => (
187
192
  <GenerationItem
188
193
  generation={generation}
@@ -9,10 +9,11 @@ import { Center } from 'react-layout-kit';
9
9
  import { ActionButtons } from './ActionButtons';
10
10
  import { useStyles } from './styles';
11
11
  import { ErrorStateProps } from './types';
12
+ import { getThumbnailMaxWidth } from './utils';
12
13
 
13
14
  // ι”™θ――ηŠΆζ€η»„δ»Ά
14
15
  export const ErrorState = memo<ErrorStateProps>(
15
- ({ generation, aspectRatio, onDelete, onCopyError }) => {
16
+ ({ generation, generationBatch, aspectRatio, onDelete, onCopyError }) => {
16
17
  const { styles, theme } = useStyles();
17
18
  const { t } = useTranslation('image');
18
19
 
@@ -32,7 +33,7 @@ export const ErrorState = memo<ErrorStateProps>(
32
33
  style={{
33
34
  aspectRatio,
34
35
  cursor: 'pointer',
35
- maxWidth: generation.asset?.width ? generation.asset.width / 2 : 'unset',
36
+ maxWidth: getThumbnailMaxWidth(generation, generationBatch),
36
37
  }}
37
38
  variant={'filled'}
38
39
  >
@@ -12,33 +12,36 @@ import { ActionButtons } from './ActionButtons';
12
12
  import { ElapsedTime } from './ElapsedTime';
13
13
  import { useStyles } from './styles';
14
14
  import { LoadingStateProps } from './types';
15
+ import { getThumbnailMaxWidth } from './utils';
15
16
 
16
17
  // εŠ θ½½ηŠΆζ€η»„δ»Ά
17
- export const LoadingState = memo<LoadingStateProps>(({ generation, aspectRatio, onDelete }) => {
18
- const { styles } = useStyles();
18
+ export const LoadingState = memo<LoadingStateProps>(
19
+ ({ generation, generationBatch, aspectRatio, onDelete }) => {
20
+ const { styles } = useStyles();
19
21
 
20
- const isGenerating =
21
- generation.task.status === AsyncTaskStatus.Processing ||
22
- generation.task.status === AsyncTaskStatus.Pending;
22
+ const isGenerating =
23
+ generation.task.status === AsyncTaskStatus.Processing ||
24
+ generation.task.status === AsyncTaskStatus.Pending;
23
25
 
24
- return (
25
- <Block
26
- align={'center'}
27
- className={styles.placeholderContainer}
28
- justify={'center'}
29
- style={{
30
- aspectRatio,
31
- maxWidth: generation.asset?.width ? generation.asset.width / 2 : 'unset',
32
- }}
33
- variant={'filled'}
34
- >
35
- <Center gap={8}>
36
- <Spin indicator={<LoadingOutlined spin />} />
37
- <ElapsedTime generationId={generation.id} isActive={isGenerating} />
38
- </Center>
39
- <ActionButtons onDelete={onDelete} />
40
- </Block>
41
- );
42
- });
26
+ return (
27
+ <Block
28
+ align={'center'}
29
+ className={styles.placeholderContainer}
30
+ justify={'center'}
31
+ style={{
32
+ aspectRatio,
33
+ maxWidth: getThumbnailMaxWidth(generation, generationBatch),
34
+ }}
35
+ variant={'filled'}
36
+ >
37
+ <Center gap={8}>
38
+ <Spin indicator={<LoadingOutlined spin />} />
39
+ <ElapsedTime generationId={generation.id} isActive={isGenerating} />
40
+ </Center>
41
+ <ActionButtons onDelete={onDelete} />
42
+ </Block>
43
+ );
44
+ },
45
+ );
43
46
 
44
47
  LoadingState.displayName = 'LoadingState';
@@ -8,10 +8,20 @@ import ImageItem from '@/components/ImageItem';
8
8
  import { ActionButtons } from './ActionButtons';
9
9
  import { useStyles } from './styles';
10
10
  import { SuccessStateProps } from './types';
11
+ import { getThumbnailMaxWidth } from './utils';
11
12
 
12
13
  // ζˆεŠŸηŠΆζ€η»„δ»Ά
13
14
  export const SuccessState = memo<SuccessStateProps>(
14
- ({ generation, prompt, aspectRatio, onDelete, onDownload, onCopySeed, seedTooltip }) => {
15
+ ({
16
+ generation,
17
+ generationBatch,
18
+ prompt,
19
+ aspectRatio,
20
+ onDelete,
21
+ onDownload,
22
+ onCopySeed,
23
+ seedTooltip,
24
+ }) => {
15
25
  const { styles } = useStyles();
16
26
 
17
27
  return (
@@ -21,7 +31,7 @@ export const SuccessState = memo<SuccessStateProps>(
21
31
  justify={'center'}
22
32
  style={{
23
33
  aspectRatio,
24
- maxWidth: generation.asset?.width ? generation.asset.width / 2 : 'unset',
34
+ maxWidth: getThumbnailMaxWidth(generation, generationBatch),
25
35
  }}
26
36
  variant={'filled'}
27
37
  >
@@ -31,7 +41,8 @@ export const SuccessState = memo<SuccessStateProps>(
31
41
  src: generation.asset!.url,
32
42
  }}
33
43
  style={{ height: '100%', width: '100%' }}
34
- url={generation.asset!.thumbnailUrl}
44
+ // Thumbnail quality is too bad
45
+ url={generation.asset!.url}
35
46
  />
36
47
  <ActionButtons
37
48
  onCopySeed={onCopySeed}
@@ -37,13 +37,7 @@ export const GenerationItem = memo<GenerationItemProps>(
37
37
  const shouldPoll = !isFinalized;
38
38
  useCheckGenerationStatus(generation.id, generation.task.id, activeTopicId!, shouldPoll);
39
39
 
40
- const aspectRatio = getAspectRatio(
41
- generation.asset ?? {
42
- height: generationBatch.config?.height,
43
- type: 'image',
44
- width: generationBatch.config?.width,
45
- },
46
- );
40
+ const aspectRatio = getAspectRatio(generation, generationBatch);
47
41
 
48
42
  // 事仢倄理函数
49
43
  const handleDeleteGeneration = async () => {
@@ -120,6 +114,7 @@ export const GenerationItem = memo<GenerationItemProps>(
120
114
  <SuccessState
121
115
  aspectRatio={aspectRatio}
122
116
  generation={generation}
117
+ generationBatch={generationBatch}
123
118
  onCopySeed={handleCopySeed}
124
119
  onDelete={handleDeleteGeneration}
125
120
  onDownload={handleDownloadImage}
@@ -134,6 +129,7 @@ export const GenerationItem = memo<GenerationItemProps>(
134
129
  <ErrorState
135
130
  aspectRatio={aspectRatio}
136
131
  generation={generation}
132
+ generationBatch={generationBatch}
137
133
  onCopyError={handleCopyError}
138
134
  onDelete={handleDeleteGeneration}
139
135
  />
@@ -145,6 +141,7 @@ export const GenerationItem = memo<GenerationItemProps>(
145
141
  <LoadingState
146
142
  aspectRatio={aspectRatio}
147
143
  generation={generation}
144
+ generationBatch={generationBatch}
148
145
  onDelete={handleDeleteGeneration}
149
146
  />
150
147
  );
@@ -18,6 +18,7 @@ export interface ActionButtonsProps {
18
18
  export interface SuccessStateProps {
19
19
  aspectRatio: string;
20
20
  generation: Generation;
21
+ generationBatch: GenerationBatch;
21
22
  onCopySeed?: () => void;
22
23
  onDelete: () => void;
23
24
  onDownload: () => void;
@@ -28,6 +29,7 @@ export interface SuccessStateProps {
28
29
  export interface ErrorStateProps {
29
30
  aspectRatio: string;
30
31
  generation: Generation;
32
+ generationBatch: GenerationBatch;
31
33
  onCopyError: () => void;
32
34
  onDelete: () => void;
33
35
  }
@@ -35,5 +37,6 @@ export interface ErrorStateProps {
35
37
  export interface LoadingStateProps {
36
38
  aspectRatio: string;
37
39
  generation: Generation;
40
+ generationBatch: GenerationBatch;
38
41
  onDelete: () => void;
39
42
  }