mirror of
https://github.com/lobehub/lobe-chat.git
synced 2026-06-13 19:20:04 +00:00
💄 style: batch fix eslint violations across packages (#12601)
This commit is contained in:
@@ -41,7 +41,7 @@ describe('UsageCounter', () => {
|
||||
const { usage } = UsageCounter.accumulateLLM({
|
||||
cost: state.cost,
|
||||
model: 'gpt-4',
|
||||
modelUsage: modelUsage,
|
||||
modelUsage,
|
||||
provider: 'openai',
|
||||
usage: state.usage,
|
||||
});
|
||||
@@ -63,7 +63,7 @@ describe('UsageCounter', () => {
|
||||
const { cost } = UsageCounter.accumulateLLM({
|
||||
cost: state.cost,
|
||||
model: 'gpt-4',
|
||||
modelUsage: modelUsage,
|
||||
modelUsage,
|
||||
provider: 'openai',
|
||||
usage: state.usage,
|
||||
});
|
||||
@@ -183,7 +183,7 @@ describe('UsageCounter', () => {
|
||||
const { cost } = UsageCounter.accumulateLLM({
|
||||
cost: state.cost,
|
||||
model: 'claude-3-5-sonnet-20241022',
|
||||
modelUsage: modelUsage,
|
||||
modelUsage,
|
||||
provider: 'anthropic',
|
||||
usage: state.usage,
|
||||
});
|
||||
@@ -248,7 +248,7 @@ describe('UsageCounter', () => {
|
||||
const { cost } = UsageCounter.accumulateLLM({
|
||||
cost: state.cost,
|
||||
model: 'gpt-4',
|
||||
modelUsage: modelUsage,
|
||||
modelUsage,
|
||||
provider: 'openai',
|
||||
usage: state.usage,
|
||||
});
|
||||
@@ -270,21 +270,21 @@ describe('UsageCounter', () => {
|
||||
const result1 = UsageCounter.accumulateLLM({
|
||||
cost: state.cost,
|
||||
model: 'gpt-4',
|
||||
modelUsage: modelUsage,
|
||||
modelUsage,
|
||||
provider: 'openai',
|
||||
usage: state.usage,
|
||||
});
|
||||
const result2 = UsageCounter.accumulateLLM({
|
||||
cost: result1.cost,
|
||||
model: 'gpt-4',
|
||||
modelUsage: modelUsage,
|
||||
modelUsage,
|
||||
provider: 'openai',
|
||||
usage: result1.usage,
|
||||
});
|
||||
const result3 = UsageCounter.accumulateLLM({
|
||||
cost: result2.cost,
|
||||
model: 'claude-3-5-sonnet-20241022',
|
||||
modelUsage: modelUsage,
|
||||
modelUsage,
|
||||
provider: 'anthropic',
|
||||
usage: result2.usage,
|
||||
});
|
||||
|
||||
@@ -56,10 +56,10 @@ export const CallAgentInspector = memo<BuiltinInspectorProps<CallAgentParams>>(
|
||||
|
||||
return (
|
||||
<Flexbox
|
||||
horizontal
|
||||
align={'center'}
|
||||
className={cx(styles.root, isArgumentsStreaming && shinyTextStyles.shinyText)}
|
||||
gap={8}
|
||||
horizontal
|
||||
>
|
||||
<span className={styles.title}>{t(titleKey)}</span>
|
||||
{agentMeta && (
|
||||
|
||||
@@ -44,10 +44,10 @@ export const CreateAgentInspector = memo<BuiltinInspectorProps<CreateAgentParams
|
||||
|
||||
return (
|
||||
<Flexbox
|
||||
horizontal
|
||||
align={'center'}
|
||||
className={cx(styles.root, isArgumentsStreaming && shinyTextStyles.shinyText)}
|
||||
gap={8}
|
||||
horizontal
|
||||
>
|
||||
<span className={styles.title}>
|
||||
{t('builtins.lobe-agent-management.inspector.createAgent.title')}
|
||||
|
||||
@@ -57,10 +57,10 @@ export const SearchAgentInspector = memo<BuiltinInspectorProps<SearchAgentParams
|
||||
|
||||
return (
|
||||
<Flexbox
|
||||
horizontal
|
||||
align={'center'}
|
||||
className={cx(styles.root, isArgumentsStreaming && shinyTextStyles.shinyText)}
|
||||
gap={8}
|
||||
horizontal
|
||||
>
|
||||
<span className={styles.title}>{t(titleKey)}</span>
|
||||
{keyword && <span className={highlightTextStyles.primary}>{keyword}</span>}
|
||||
|
||||
@@ -40,10 +40,10 @@ export const UpdateAgentInspector = memo<BuiltinInspectorProps<UpdateAgentParams
|
||||
|
||||
return (
|
||||
<Flexbox
|
||||
horizontal
|
||||
align={'center'}
|
||||
className={cx(styles.root, isArgumentsStreaming && shinyTextStyles.shinyText)}
|
||||
gap={8}
|
||||
horizontal
|
||||
>
|
||||
<span className={styles.title}>
|
||||
{t('builtins.lobe-agent-management.inspector.updateAgent.title')}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import type { BuiltinRenderProps } from '@lobechat/types';
|
||||
import { Block, Markdown, Tag , Flexbox } from '@lobehub/ui';
|
||||
import { Block, Flexbox,Markdown, Tag } from '@lobehub/ui';
|
||||
import { createStaticStyles } from 'antd-style';
|
||||
import { memo } from 'react';
|
||||
|
||||
@@ -62,7 +62,7 @@ export const CreateAgentRender = memo<BuiltinRenderProps<CreateAgentParams>>(({
|
||||
{plugins && plugins.length > 0 && (
|
||||
<div className={styles.field}>
|
||||
<div className={styles.label}>Plugins</div>
|
||||
<Flexbox gap={4} horizontal wrap={'wrap'}>
|
||||
<Flexbox horizontal gap={4} wrap={'wrap'}>
|
||||
{plugins.map((plugin) => (
|
||||
<Tag key={plugin}>{plugin}</Tag>
|
||||
))}
|
||||
|
||||
@@ -73,7 +73,7 @@ export const SearchAgentRender = memo<BuiltinRenderProps<SearchAgentParams, Sear
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
{agents.map((agent: AgentSearchItem) => (
|
||||
<Flexbox align={'center'} className={styles.agentItem} gap={12} horizontal key={agent.id}>
|
||||
<Flexbox horizontal align={'center'} className={styles.agentItem} gap={12} key={agent.id}>
|
||||
<Avatar
|
||||
avatar={agent.avatar || DEFAULT_AVATAR}
|
||||
background={agent.backgroundColor || theme.colorBgContainer}
|
||||
@@ -82,7 +82,7 @@ export const SearchAgentRender = memo<BuiltinRenderProps<SearchAgentParams, Sear
|
||||
title={agent.title || undefined}
|
||||
/>
|
||||
<Flexbox flex={1} gap={2}>
|
||||
<Flexbox align={'center'} gap={8} horizontal>
|
||||
<Flexbox horizontal align={'center'} gap={8}>
|
||||
<span className={styles.agentTitle}>{agent.title || agent.id}</span>
|
||||
{agent.isMarket && <span className={styles.marketBadge}>Market</span>}
|
||||
</Flexbox>
|
||||
|
||||
@@ -59,7 +59,7 @@ export const CreateAgentStreaming = memo<BuiltinStreamingProps<CreateAgentParams
|
||||
{plugins && plugins.length > 0 && (
|
||||
<div className={styles.field}>
|
||||
<div className={styles.label}>Plugins</div>
|
||||
<Flexbox gap={4} horizontal wrap={'wrap'}>
|
||||
<Flexbox horizontal gap={4} wrap={'wrap'}>
|
||||
{plugins.map((plugin) => (
|
||||
<Tag key={plugin}>{plugin}</Tag>
|
||||
))}
|
||||
|
||||
@@ -194,7 +194,7 @@ class AgentManagementExecutor extends BaseExecutor<typeof AgentManagementApiName
|
||||
// The message.agentId will still be current agent, but metadata stores subAgentId + scope
|
||||
await get().internal_execAgentRuntime({
|
||||
context: { ...conversationContext, subAgentId: agentId, scope: 'sub_agent' },
|
||||
messages: messages,
|
||||
messages,
|
||||
parentMessageId: ctx.messageId,
|
||||
parentMessageType: 'tool',
|
||||
});
|
||||
|
||||
@@ -265,6 +265,11 @@ export interface CallAgentParams {
|
||||
* If true, execute as an async background task
|
||||
*/
|
||||
runAsTask?: boolean;
|
||||
/**
|
||||
* If true (and in a group context), skip calling supervisor after agent responds.
|
||||
* Only relevant when used within agent groups. Default: false
|
||||
*/
|
||||
skipCallSupervisor?: boolean;
|
||||
/**
|
||||
* Task title (required when runAsTask is true)
|
||||
*/
|
||||
@@ -273,11 +278,6 @@ export interface CallAgentParams {
|
||||
* Timeout in milliseconds for task execution (default: 1800000 = 30 minutes)
|
||||
*/
|
||||
timeout?: number;
|
||||
/**
|
||||
* If true (and in a group context), skip calling supervisor after agent responds.
|
||||
* Only relevant when used within agent groups. Default: false
|
||||
*/
|
||||
skipCallSupervisor?: boolean;
|
||||
}
|
||||
|
||||
export interface CallAgentState {
|
||||
@@ -293,12 +293,12 @@ export interface CallAgentState {
|
||||
* Execution mode
|
||||
*/
|
||||
mode: 'speak' | 'task';
|
||||
/**
|
||||
* Task ID if running as background task
|
||||
*/
|
||||
taskId?: string;
|
||||
/**
|
||||
* Whether to skip calling supervisor after agent responds (only relevant in group context)
|
||||
*/
|
||||
skipCallSupervisor?: boolean;
|
||||
/**
|
||||
* Task ID if running as background task
|
||||
*/
|
||||
taskId?: string;
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@ import {
|
||||
Avatar,
|
||||
Flexbox,
|
||||
Icon,
|
||||
Tooltip,
|
||||
stopPropagation,
|
||||
Tooltip,
|
||||
} from '@lobehub/ui';
|
||||
import { Input, InputNumber } from 'antd';
|
||||
import { createStaticStyles, useTheme } from 'antd-style';
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ const RenameLocalFile = memo<BuiltinInterventionProps<RenameLocalFileParams>>(({
|
||||
<Icon icon={ChevronRight} />
|
||||
<LocalFile name={base} path={filePath} />
|
||||
</Flexbox>
|
||||
<Flexbox align="center" gap={8} horizontal>
|
||||
<Flexbox horizontal align="center" gap={8}>
|
||||
<Text type="secondary">{base}</Text>
|
||||
<Icon icon={ArrowRight} />
|
||||
<Text>{newName}</Text>
|
||||
|
||||
@@ -22,16 +22,16 @@ const ExecScript = memo<BuiltinRenderProps<ExecScriptParams, ExecScriptState>>(
|
||||
<Flexbox className={styles.container} gap={8}>
|
||||
<Block gap={8} padding={8} variant={'outlined'}>
|
||||
<Highlighter
|
||||
wrap
|
||||
language={'sh'}
|
||||
showLanguage={false}
|
||||
style={{ paddingInline: 8 }}
|
||||
variant={'borderless'}
|
||||
wrap
|
||||
>
|
||||
{args?.command || command || ''}
|
||||
</Highlighter>
|
||||
{content && (
|
||||
<Highlighter language={'text'} showLanguage={false} variant={'filled'} wrap>
|
||||
<Highlighter wrap language={'text'} showLanguage={false} variant={'filled'}>
|
||||
{content}
|
||||
</Highlighter>
|
||||
)}
|
||||
|
||||
@@ -64,12 +64,12 @@ const ReadReference = memo<BuiltinRenderProps<ReadReferenceParams, ReadReference
|
||||
|
||||
return (
|
||||
<Flexbox className={styles.container} gap={8}>
|
||||
<Flexbox align={'center'} horizontal justify={'space-between'}>
|
||||
<Text as={'span'} code ellipsis fontSize={12}>
|
||||
<Flexbox horizontal align={'center'} justify={'space-between'}>
|
||||
<Text code ellipsis as={'span'} fontSize={12}>
|
||||
{path}
|
||||
</Text>
|
||||
{sizeText && (
|
||||
<Text as={'span'} code fontSize={12} type={'secondary'}>
|
||||
<Text code as={'span'} fontSize={12} type={'secondary'}>
|
||||
{sizeText}
|
||||
</Text>
|
||||
)}
|
||||
@@ -90,11 +90,11 @@ const ReadReference = memo<BuiltinRenderProps<ReadReferenceParams, ReadReference
|
||||
) : (
|
||||
<Block padding={0} variant={'outlined'}>
|
||||
<Highlighter
|
||||
language={getLanguage(ext)}
|
||||
showLanguage
|
||||
wrap
|
||||
language={getLanguage(ext)}
|
||||
style={{ maxHeight: 400, overflow: 'auto' }}
|
||||
variant={'borderless'}
|
||||
wrap
|
||||
>
|
||||
{content}
|
||||
</Highlighter>
|
||||
|
||||
@@ -71,7 +71,7 @@ export interface ReadReferenceParams {
|
||||
}
|
||||
|
||||
export interface ReadReferenceState {
|
||||
encoding: 'base64' | 'utf-8';
|
||||
encoding: 'base64' | 'utf8';
|
||||
fileType: string;
|
||||
path: string;
|
||||
size: number;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { AgentBuilderManifest } from '@lobechat/builtin-tool-agent-builder';
|
||||
import { CalculatorManifest } from '@lobechat/builtin-tool-calculator';
|
||||
import { AgentManagementManifest } from '@lobechat/builtin-tool-agent-management';
|
||||
import { CalculatorManifest } from '@lobechat/builtin-tool-calculator';
|
||||
import { CloudSandboxManifest } from '@lobechat/builtin-tool-cloud-sandbox';
|
||||
import { GroupAgentBuilderManifest } from '@lobechat/builtin-tool-group-agent-builder';
|
||||
import { GroupManagementManifest } from '@lobechat/builtin-tool-group-management';
|
||||
|
||||
@@ -62,7 +62,9 @@ export class ToolNameResolver {
|
||||
): ChatToolPayload[] {
|
||||
return toolCalls
|
||||
.map((toolCall): ChatToolPayload | null => {
|
||||
let [identifier, apiName, type] = toolCall.function.name.split(PLUGIN_SCHEMA_SEPARATOR);
|
||||
const [initialIdentifier, apiName, type] =
|
||||
toolCall.function.name.split(PLUGIN_SCHEMA_SEPARATOR);
|
||||
let identifier = initialIdentifier;
|
||||
|
||||
if (!apiName) return null;
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ export class TaskMessageProcessor extends BaseProcessor {
|
||||
if (!instruction) {
|
||||
clonedContext.messages[i] = {
|
||||
...message,
|
||||
content: content,
|
||||
content,
|
||||
role: 'assistant',
|
||||
};
|
||||
processedCount++;
|
||||
|
||||
@@ -143,7 +143,7 @@ describe('MessageCleanupProcessor', () => {
|
||||
content: 'Here is the answer',
|
||||
extraField: 'remove',
|
||||
id: 'msg5',
|
||||
reasoning: reasoning,
|
||||
reasoning,
|
||||
role: 'assistant',
|
||||
timestamp: Date.now(),
|
||||
},
|
||||
@@ -154,7 +154,7 @@ describe('MessageCleanupProcessor', () => {
|
||||
expect(result.messages).toHaveLength(1);
|
||||
expect(result.messages[0]).toEqual({
|
||||
content: 'Here is the answer',
|
||||
reasoning: reasoning,
|
||||
reasoning,
|
||||
role: 'assistant',
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,7 +5,7 @@ import type { PipelineContext } from '../../types';
|
||||
import { MessageContentProcessor } from '../MessageContent';
|
||||
|
||||
vi.mock('@lobechat/utils/imageToBase64', async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import('@lobechat/utils/imageToBase64')>();
|
||||
const actual = await importOriginal<Record<string, unknown>>();
|
||||
return {
|
||||
...actual,
|
||||
imageUrlToBase64: vi.fn().mockResolvedValue({
|
||||
|
||||
@@ -18,9 +18,9 @@ export {
|
||||
PlaceholderVariablesProcessor,
|
||||
renderPlaceholderTemplate,
|
||||
} from './PlaceholderVariables';
|
||||
export { ReactionFeedbackProcessor } from './ReactionFeedback';
|
||||
export { SupervisorRoleRestoreProcessor } from './SupervisorRoleRestore';
|
||||
export { TaskMessageProcessor } from './TaskMessage';
|
||||
export { ReactionFeedbackProcessor } from './ReactionFeedback';
|
||||
export { TasksFlattenProcessor } from './TasksFlatten';
|
||||
export { ToolCallProcessor } from './ToolCall';
|
||||
export { ToolMessageReorder } from './ToolMessageReorder';
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import type { PipelineContext } from '../../types';
|
||||
import { SkillContextProvider } from '../SkillContextProvider';
|
||||
import type { SkillMeta } from '../SkillContextProvider';
|
||||
import { SkillContextProvider } from '../SkillContextProvider';
|
||||
|
||||
const createContext = (messages: any[]): PipelineContext => ({
|
||||
initialState: { messages: [] } as any,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
// @vitest-environment node
|
||||
import { SkillManifest } from '@lobechat/types';
|
||||
import type { SkillManifest } from '@lobechat/types';
|
||||
import { eq } from 'drizzle-orm';
|
||||
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
||||
|
||||
import { getTestDB } from '../../core/getTestDB';
|
||||
import { agentSkills, users } from '../../schemas';
|
||||
import { LobeChatDatabase } from '../../type';
|
||||
import type { LobeChatDatabase } from '../../type';
|
||||
import { AgentSkillModel } from '../agentSkill';
|
||||
|
||||
const serverDB: LobeChatDatabase = await getTestDB();
|
||||
|
||||
@@ -4,7 +4,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import { getTestDB } from '../../core/getTestDB';
|
||||
import { apiKeys, users } from '../../schemas';
|
||||
import { LobeChatDatabase } from '../../type';
|
||||
import type { LobeChatDatabase } from '../../type';
|
||||
import { ApiKeyModel } from '../apiKey';
|
||||
|
||||
const serverDB: LobeChatDatabase = await getTestDB();
|
||||
|
||||
@@ -50,7 +50,7 @@ beforeEach(async () => {
|
||||
]);
|
||||
await trx.insert(files).values({
|
||||
id: 'f1',
|
||||
userId: userId,
|
||||
userId,
|
||||
url: 'abc',
|
||||
name: 'file-1',
|
||||
fileType: 'image/png',
|
||||
|
||||
@@ -27,7 +27,7 @@ beforeEach(async () => {
|
||||
await trx.insert(sessions).values([{ id: '1', userId }]);
|
||||
await trx.insert(files).values({
|
||||
id: 'f1',
|
||||
userId: userId,
|
||||
userId,
|
||||
url: 'abc',
|
||||
name: 'file-1',
|
||||
fileType: 'image/png',
|
||||
|
||||
@@ -40,7 +40,7 @@ beforeEach(async () => {
|
||||
]);
|
||||
await trx.insert(files).values({
|
||||
id: 'f1',
|
||||
userId: userId,
|
||||
userId,
|
||||
url: 'abc',
|
||||
name: 'file-1',
|
||||
fileType: 'image/png',
|
||||
|
||||
@@ -72,7 +72,7 @@ describe('MessageModel - queryWithWhere with task messages', () => {
|
||||
expect(taskMessage.taskDetail).toEqual({
|
||||
duration: 5000,
|
||||
status: ThreadStatus.Completed,
|
||||
threadId: threadId,
|
||||
threadId,
|
||||
title: 'Agent Task Execution',
|
||||
totalCost: 0.05,
|
||||
totalMessages: 10,
|
||||
@@ -348,7 +348,7 @@ describe('MessageModel - queryWithWhere with task messages', () => {
|
||||
expect(taskMessage.taskDetail).toEqual({
|
||||
duration: undefined,
|
||||
status: ThreadStatus.Active,
|
||||
threadId: threadId,
|
||||
threadId,
|
||||
title: 'Partial Metadata Thread',
|
||||
totalCost: undefined,
|
||||
totalMessages: undefined,
|
||||
@@ -387,7 +387,7 @@ describe('MessageModel - queryWithWhere with task messages', () => {
|
||||
expect(taskMessage.taskDetail).toEqual({
|
||||
duration: undefined,
|
||||
status: ThreadStatus.Pending,
|
||||
threadId: threadId,
|
||||
threadId,
|
||||
title: undefined,
|
||||
totalCost: undefined,
|
||||
totalMessages: undefined,
|
||||
|
||||
@@ -47,8 +47,8 @@ describe('TopicModel - Delete', () => {
|
||||
{ id: 'topic2', sessionId: 'session2', userId: '345' },
|
||||
]);
|
||||
await tx.insert(messages).values([
|
||||
{ id: 'message1', role: 'user', topicId: topicId, userId },
|
||||
{ id: 'message2', role: 'assistant', topicId: topicId, userId },
|
||||
{ id: 'message1', role: 'user', topicId, userId },
|
||||
{ id: 'message2', role: 'assistant', topicId, userId },
|
||||
{ id: 'message3', role: 'user', topicId: 'topic2', userId: '345' },
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
} from '../../../schemas';
|
||||
import { AgentEvalRunModel } from '../run';
|
||||
|
||||
let serverDB = await getTestDB();
|
||||
const serverDB = await getTestDB();
|
||||
|
||||
const userId = 'run-test-user';
|
||||
const userId2 = 'run-test-user-2';
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { SkillItem, SkillListItem } from '@lobechat/types';
|
||||
import type { SkillItem, SkillListItem } from '@lobechat/types';
|
||||
import { merge } from '@lobechat/utils';
|
||||
import { and, desc, eq, ilike, inArray, or } from 'drizzle-orm';
|
||||
|
||||
import { NewAgentSkill, agentSkills } from '../schemas';
|
||||
import { LobeChatDatabase } from '../type';
|
||||
import type {NewAgentSkill } from '../schemas';
|
||||
import { agentSkills } from '../schemas';
|
||||
import type { LobeChatDatabase } from '../type';
|
||||
|
||||
const skillItemColumns = {
|
||||
content: agentSkills.content,
|
||||
|
||||
@@ -2,8 +2,9 @@ import { and, desc, eq } from 'drizzle-orm';
|
||||
|
||||
import { generateApiKey, isApiKeyExpired, validateApiKeyFormat } from '@/utils/apiKey';
|
||||
|
||||
import { ApiKeyItem, NewApiKeyItem, apiKeys } from '../schemas';
|
||||
import { LobeChatDatabase } from '../type';
|
||||
import type { ApiKeyItem,NewApiKeyItem } from '../schemas';
|
||||
import { apiKeys } from '../schemas';
|
||||
import type { LobeChatDatabase } from '../type';
|
||||
|
||||
type EncryptAPIKeyVaults = (keyVaults: string) => Promise<string>;
|
||||
type DecryptAPIKeyVaults = (keyVaults: string) => Promise<{ plaintext: string }>;
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import type { RAGEvalDataSetItem } from '@lobechat/types';
|
||||
import { and, desc, eq } from 'drizzle-orm';
|
||||
|
||||
import { NewEvalDatasetsItem, evalDatasets } from '../../schemas';
|
||||
import { LobeChatDatabase } from '../../type';
|
||||
import type {NewEvalDatasetsItem } from '../../schemas';
|
||||
import { evalDatasets } from '../../schemas';
|
||||
import type { LobeChatDatabase } from '../../type';
|
||||
|
||||
export class EvalDatasetModel {
|
||||
private userId: string;
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import type { EvalDatasetRecordRefFile } from '@lobechat/types';
|
||||
import { and, eq, inArray } from 'drizzle-orm';
|
||||
|
||||
import { NewEvalDatasetRecordsItem, evalDatasetRecords, files } from '../../schemas';
|
||||
import { LobeChatDatabase } from '../../type';
|
||||
import type {NewEvalDatasetRecordsItem } from '../../schemas';
|
||||
import { evalDatasetRecords, files } from '../../schemas';
|
||||
import type { LobeChatDatabase } from '../../type';
|
||||
|
||||
export class EvalDatasetRecordModel {
|
||||
private userId: string;
|
||||
|
||||
@@ -3,13 +3,14 @@ import { EvalEvaluationStatus } from '@lobechat/types';
|
||||
import type { SQL } from 'drizzle-orm';
|
||||
import { and, count, desc, eq, inArray } from 'drizzle-orm';
|
||||
|
||||
import type {
|
||||
NewEvalEvaluationItem} from '../../schemas';
|
||||
import {
|
||||
NewEvalEvaluationItem,
|
||||
evalDatasets,
|
||||
evalEvaluation,
|
||||
evaluationRecords,
|
||||
evaluationRecords
|
||||
} from '../../schemas';
|
||||
import { LobeChatDatabase } from '../../type';
|
||||
import type { LobeChatDatabase } from '../../type';
|
||||
|
||||
export class EvalEvaluationModel {
|
||||
private userId: string;
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { and, eq } from 'drizzle-orm';
|
||||
|
||||
import { NewEvaluationRecordsItem, evaluationRecords } from '../../schemas';
|
||||
import { LobeChatDatabase } from '../../type';
|
||||
import type {NewEvaluationRecordsItem } from '../../schemas';
|
||||
import { evaluationRecords } from '../../schemas';
|
||||
import type { LobeChatDatabase } from '../../type';
|
||||
|
||||
export class EvaluationRecordModel {
|
||||
private userId: string;
|
||||
|
||||
@@ -366,7 +366,7 @@ export class SessionModel {
|
||||
const { id: _, slug: __, ...config } = agent;
|
||||
|
||||
return this.create({
|
||||
config: config,
|
||||
config,
|
||||
id: sessionId,
|
||||
session: {
|
||||
...session,
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
import { beforeEach, describe, expect, it } from 'vitest';
|
||||
|
||||
import { getTestDB } from '../../core/getTestDB';
|
||||
import { NewAgent, agents } from '../../schemas/agent';
|
||||
import { NewChatGroup, chatGroups, chatGroupsAgents } from '../../schemas/chatGroup';
|
||||
import { agents } from '../../schemas/agent';
|
||||
import { chatGroups, chatGroupsAgents } from '../../schemas/chatGroup';
|
||||
import { agentsToSessions } from '../../schemas/relations';
|
||||
import { NewSession, NewSessionGroup, sessionGroups, sessions } from '../../schemas/session';
|
||||
import { sessionGroups, sessions } from '../../schemas/session';
|
||||
import { users } from '../../schemas/user';
|
||||
import { LobeChatDatabase } from '../../type';
|
||||
import type { LobeChatDatabase } from '../../type';
|
||||
import { HomeRepository } from './index';
|
||||
|
||||
const userId = 'home-test-user';
|
||||
|
||||
@@ -63,7 +63,7 @@ describe('TopicImporterRepo.importTopic', () => {
|
||||
it('should restore parentId chain from real exported data', async () => {
|
||||
const repo = new TopicImporterRepo(serverDB, userId);
|
||||
const jsonPath = path.join(__dirname, 'fixtures/exported-topic.json');
|
||||
const fileContent = readFileSync(jsonPath, 'utf-8');
|
||||
const fileContent = readFileSync(jsonPath, 'utf8');
|
||||
const exportedData = JSON.parse(fileContent) as ExportedTopic;
|
||||
|
||||
const result = await repo.importTopic({
|
||||
@@ -117,7 +117,7 @@ describe('TopicImporterRepo.importTopic', () => {
|
||||
it('should preserve plugin and pluginState fields in message_plugins table', async () => {
|
||||
const repo = new TopicImporterRepo(serverDB, userId);
|
||||
const jsonPath = path.join(__dirname, 'fixtures/exported-topic.json');
|
||||
const fileContent = readFileSync(jsonPath, 'utf-8');
|
||||
const fileContent = readFileSync(jsonPath, 'utf8');
|
||||
const exportedData = JSON.parse(fileContent) as ExportedTopic;
|
||||
|
||||
const result = await repo.importTopic({
|
||||
@@ -172,7 +172,7 @@ describe('TopicImporterRepo.importTopic', () => {
|
||||
it('should preserve tools array on assistant messages', async () => {
|
||||
const repo = new TopicImporterRepo(serverDB, userId);
|
||||
const jsonPath = path.join(__dirname, 'fixtures/exported-topic.json');
|
||||
const fileContent = readFileSync(jsonPath, 'utf-8');
|
||||
const fileContent = readFileSync(jsonPath, 'utf8');
|
||||
const exportedData = JSON.parse(fileContent) as ExportedTopic;
|
||||
|
||||
const result = await repo.importTopic({
|
||||
@@ -206,7 +206,7 @@ describe('TopicImporterRepo.importTopic', () => {
|
||||
it('should preserve model and provider fields', async () => {
|
||||
const repo = new TopicImporterRepo(serverDB, userId);
|
||||
const jsonPath = path.join(__dirname, 'fixtures/exported-topic.json');
|
||||
const fileContent = readFileSync(jsonPath, 'utf-8');
|
||||
const fileContent = readFileSync(jsonPath, 'utf8');
|
||||
const exportedData = JSON.parse(fileContent) as ExportedTopic;
|
||||
|
||||
const result = await repo.importTopic({
|
||||
@@ -231,7 +231,7 @@ describe('TopicImporterRepo.importTopic', () => {
|
||||
it('should verify branching is preserved (2 children for root)', async () => {
|
||||
const repo = new TopicImporterRepo(serverDB, userId);
|
||||
const jsonPath = path.join(__dirname, 'fixtures/exported-topic.json');
|
||||
const fileContent = readFileSync(jsonPath, 'utf-8');
|
||||
const fileContent = readFileSync(jsonPath, 'utf8');
|
||||
const exportedData = JSON.parse(fileContent) as ExportedTopic;
|
||||
|
||||
const result = await repo.importTopic({
|
||||
|
||||
@@ -196,8 +196,6 @@ export class ElectronIpcClient {
|
||||
const request = { id, method, params };
|
||||
log('Created request with ID: %s', id);
|
||||
|
||||
let requestTimeoutId: NodeJS.Timeout;
|
||||
|
||||
const cleanupAndResolve = (value: T) => {
|
||||
clearTimeout(requestTimeoutId);
|
||||
this.requestQueue.delete(id);
|
||||
@@ -222,7 +220,7 @@ export class ElectronIpcClient {
|
||||
this.requestQueue.set(id, { reject: cleanupAndReject, resolve: cleanupAndResolve });
|
||||
log('Added request to queue, current queue size: %d', this.requestQueue.size);
|
||||
|
||||
requestTimeoutId = setTimeout(() => {
|
||||
const requestTimeoutId: NodeJS.Timeout = setTimeout(() => {
|
||||
const pendingRequest = this.requestQueue.get(id);
|
||||
if (pendingRequest) {
|
||||
// Request is still in queue, indicating timeout
|
||||
|
||||
@@ -8,7 +8,7 @@ import { parseDataset } from '../src';
|
||||
const fixtures = resolve(__dirname, 'fixtures');
|
||||
|
||||
describe('parseDataset - CSV', () => {
|
||||
const csv = readFileSync(resolve(fixtures, 'sample.csv'), 'utf-8');
|
||||
const csv = readFileSync(resolve(fixtures, 'sample.csv'), 'utf8');
|
||||
|
||||
it('should parse CSV with headers', () => {
|
||||
const result = parseDataset(csv, { format: 'csv' });
|
||||
@@ -26,7 +26,7 @@ describe('parseDataset - CSV', () => {
|
||||
});
|
||||
|
||||
describe('parseDataset - JSONL', () => {
|
||||
const jsonl = readFileSync(resolve(fixtures, 'sample.jsonl'), 'utf-8');
|
||||
const jsonl = readFileSync(resolve(fixtures, 'sample.jsonl'), 'utf8');
|
||||
|
||||
it('should parse JSONL', () => {
|
||||
const result = parseDataset(jsonl, { format: 'jsonl' });
|
||||
@@ -47,7 +47,7 @@ describe('parseDataset - JSONL', () => {
|
||||
});
|
||||
|
||||
describe('parseDataset - JSON', () => {
|
||||
const json = readFileSync(resolve(fixtures, 'sample.json'), 'utf-8');
|
||||
const json = readFileSync(resolve(fixtures, 'sample.json'), 'utf8');
|
||||
|
||||
it('should parse JSON array', () => {
|
||||
const result = parseDataset(json, { format: 'json' });
|
||||
@@ -65,20 +65,20 @@ describe('parseDataset - JSON', () => {
|
||||
|
||||
describe('parseDataset - auto detection', () => {
|
||||
it('should auto-detect CSV by filename', () => {
|
||||
const csv = readFileSync(resolve(fixtures, 'sample.csv'), 'utf-8');
|
||||
const csv = readFileSync(resolve(fixtures, 'sample.csv'), 'utf8');
|
||||
const result = parseDataset(csv, { filename: 'sample.csv' });
|
||||
expect(result.format).toBe('csv');
|
||||
expect(result.headers).toContain('prompt');
|
||||
});
|
||||
|
||||
it('should auto-detect JSONL by filename', () => {
|
||||
const jsonl = readFileSync(resolve(fixtures, 'sample.jsonl'), 'utf-8');
|
||||
const jsonl = readFileSync(resolve(fixtures, 'sample.jsonl'), 'utf8');
|
||||
const result = parseDataset(jsonl, { filename: 'sample.jsonl' });
|
||||
expect(result.format).toBe('jsonl');
|
||||
});
|
||||
|
||||
it('should auto-detect JSON by content', () => {
|
||||
const json = readFileSync(resolve(fixtures, 'sample.json'), 'utf-8');
|
||||
const json = readFileSync(resolve(fixtures, 'sample.json'), 'utf8');
|
||||
const result = parseDataset(json);
|
||||
expect(result.format).toBe('json');
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { DatasetFormat } from './types';
|
||||
|
||||
const XLSX_MAGIC = [0x50, 0x4b, 0x03, 0x04]; // PK\x03\x04 (ZIP header)
|
||||
const XLSX_MAGIC = [0x50, 0x4B, 0x03, 0x04]; // PK\x03\x04 (ZIP header)
|
||||
|
||||
export function detectFormat(
|
||||
input: Buffer | string | Uint8Array,
|
||||
|
||||
@@ -16,15 +16,15 @@ export const extract = (output: string, extractor: AnswerExtractor): string => {
|
||||
const parts = output.split(extractor.delimiter);
|
||||
if (parts.length < 2) return output;
|
||||
const segment =
|
||||
extractor.position === 'first' ? parts[1] : parts[parts.length - 1];
|
||||
return segment.trim();
|
||||
extractor.position === 'first' ? parts[1] : parts.at(-1);
|
||||
return segment!.trim();
|
||||
}
|
||||
|
||||
case 'last-line': {
|
||||
const lines = output.split('\n').filter((l) => l.trim());
|
||||
if (lines.length === 0) return output;
|
||||
const last = lines[lines.length - 1];
|
||||
return extractor.trim !== false ? last.trim() : last;
|
||||
const last = lines.at(-1);
|
||||
return extractor.trim !== false ? last!.trim() : last!;
|
||||
}
|
||||
|
||||
case 'choice-index': {
|
||||
|
||||
@@ -91,7 +91,7 @@ export class ExcelLoader implements FileLoaderInterface {
|
||||
charCount,
|
||||
lineCount,
|
||||
metadata: {
|
||||
sheetName: sheetName,
|
||||
sheetName,
|
||||
},
|
||||
pageContent: tableMarkdown.trim(),
|
||||
});
|
||||
|
||||
@@ -112,7 +112,7 @@ export class PdfLoader implements FileLoaderInterface {
|
||||
lineCount: 0,
|
||||
metadata: {
|
||||
error: `Failed to load or parse PDF file: ${error.message}`,
|
||||
filePath: filePath,
|
||||
filePath,
|
||||
},
|
||||
pageContent: '',
|
||||
};
|
||||
@@ -159,7 +159,7 @@ export class PdfLoader implements FileLoaderInterface {
|
||||
});
|
||||
|
||||
return {
|
||||
pdfInfo: pdfInfo,
|
||||
pdfInfo,
|
||||
// PDF info (Author, Title, etc.)
|
||||
pdfMetadata: metadata,
|
||||
// PDF metadata
|
||||
|
||||
@@ -93,14 +93,14 @@ export class PptxLoader implements FileLoaderInterface {
|
||||
|
||||
const metadata = {
|
||||
pageCount: slideFiles.length, // Total number of slides found
|
||||
slideNumber: slideNumber,
|
||||
slideNumber,
|
||||
sourceFileName,
|
||||
};
|
||||
|
||||
return {
|
||||
charCount: slideText.length,
|
||||
lineCount: lines.length,
|
||||
metadata: metadata,
|
||||
metadata,
|
||||
pageContent: slideText.trim(), // Trim final content
|
||||
};
|
||||
} catch (parseError) {
|
||||
@@ -210,7 +210,7 @@ ${page.pageContent}
|
||||
metadata: {
|
||||
error: errorInfo,
|
||||
pageCount: 0,
|
||||
sourceFileName: sourceFileName,
|
||||
sourceFileName,
|
||||
...(sourceFilePath && { sourceFilePath }), // Add specific path if available
|
||||
},
|
||||
pageContent: '', // Error pages have no content
|
||||
|
||||
@@ -64,7 +64,7 @@ export class BenchmarkLocomoContextProvider implements MemoryContextProvider<
|
||||
context: toXml(root),
|
||||
metadata: {},
|
||||
sourceId: this.options.sourceId,
|
||||
userId: userId,
|
||||
userId,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ export class LobeChatTopicContextProvider implements MemoryContextProvider<
|
||||
context: topicContext,
|
||||
metadata: {},
|
||||
sourceId: this.options.topicId,
|
||||
userId: userId,
|
||||
userId,
|
||||
} satisfies BuiltContext;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,8 +250,8 @@ export class RetrievalUserMemoryContextProvider implements MemoryContextProvider
|
||||
return {
|
||||
context: memoryContext,
|
||||
metadata: {},
|
||||
sourceId: sourceId,
|
||||
userId: userId,
|
||||
sourceId,
|
||||
userId,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -343,8 +343,8 @@ export class RetrievalUserMemoryIdentitiesProvider implements MemoryContextProvi
|
||||
return {
|
||||
context: identityContext,
|
||||
metadata: {},
|
||||
sourceId: sourceId,
|
||||
userId: userId,
|
||||
sourceId,
|
||||
userId,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,8 +251,8 @@ export class MemoryExtractionService<RO> {
|
||||
layers: layersToExtract,
|
||||
outputs,
|
||||
processedCounts: processedCount,
|
||||
processedErrorsCount: processedErrorsCount,
|
||||
processedLayersCount: processedLayersCount,
|
||||
processedErrorsCount,
|
||||
processedLayersCount,
|
||||
};
|
||||
} catch (error) {
|
||||
await options?.resultRecorder?.recordFail?.(job, error as Error);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AIChatModelCard } from '../types/aiModel';
|
||||
import type { AIChatModelCard } from '../types/aiModel';
|
||||
|
||||
const straicoModels: AIChatModelCard[] = [];
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ describe('model-bank package.json exports should cover all aiModels files', () =
|
||||
const aiModelsDir = path.resolve(packageRoot, 'src/aiModels');
|
||||
const packageJsonPath = path.resolve(packageRoot, 'package.json');
|
||||
|
||||
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8')) as {
|
||||
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8')) as {
|
||||
exports?: Record<string, string>;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import type Anthropic from '@anthropic-ai/sdk';
|
||||
import debug from 'debug';
|
||||
|
||||
import type { GenerateObjectOptions, GenerateObjectPayload } from '../../types';
|
||||
import { buildAnthropicMessages, buildAnthropicTools } from '../contextBuilders/anthropic';
|
||||
import { GenerateObjectOptions, GenerateObjectPayload } from '../../types';
|
||||
|
||||
const log = debug('lobe-model-runtime:anthropic:generate-object');
|
||||
|
||||
@@ -66,7 +66,7 @@ export const createAnthropicGenerateObject = async (
|
||||
messages: anthropicMessages,
|
||||
model,
|
||||
system: systemPrompts,
|
||||
tool_choice: tool_choice,
|
||||
tool_choice,
|
||||
tools: finalTools,
|
||||
},
|
||||
{ signal: options?.signal },
|
||||
|
||||
@@ -317,7 +317,7 @@ export const buildGoogleTool = (tool: ChatCompletionTool): FunctionDeclaration =
|
||||
name: functionDeclaration.name,
|
||||
parameters: {
|
||||
description: parameters?.description,
|
||||
properties: properties,
|
||||
properties,
|
||||
required: parameters?.required,
|
||||
type: SchemaType.OBJECT,
|
||||
},
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { imageUrlToBase64 } from '@lobechat/utils';
|
||||
import OpenAI, { toFile } from 'openai';
|
||||
import type OpenAI from 'openai';
|
||||
import { toFile } from 'openai';
|
||||
|
||||
import { disableStreamModels, systemToUserModels } from '../../const/models';
|
||||
import { ChatStreamPayload, OpenAIChatMessage } from '../../types';
|
||||
import type { ChatStreamPayload, OpenAIChatMessage } from '../../types';
|
||||
import { parseDataUri } from '../../utils/uriParser';
|
||||
|
||||
type ConvertMessageContentOptions = {
|
||||
@@ -74,7 +75,7 @@ export const convertOpenAIResponseInputs = async (
|
||||
messages: OpenAIChatMessage[],
|
||||
options?: ConvertMessageContentOptions,
|
||||
) => {
|
||||
let input: OpenAI.Responses.ResponseInputItem[] = [];
|
||||
const input: OpenAI.Responses.ResponseInputItem[] = [];
|
||||
await Promise.all(
|
||||
messages.map(async (message) => {
|
||||
// if message has reasoning, add it as a separate reasoning item
|
||||
|
||||
@@ -245,7 +245,7 @@ export const AnthropicStream = (
|
||||
return readableStream
|
||||
.pipeThrough(
|
||||
createTokenSpeedCalculator(transformWithPayload, {
|
||||
enableStreaming: enableStreaming,
|
||||
enableStreaming,
|
||||
inputStartAt,
|
||||
streamStack,
|
||||
}),
|
||||
|
||||
@@ -46,7 +46,8 @@ function desensitizeAccountId(path: string): string {
|
||||
|
||||
function desensitizeCloudflareUrl(url: string): string {
|
||||
const urlObj = new URL(url);
|
||||
let { protocol, hostname, port, pathname, search } = urlObj;
|
||||
const { protocol, hostname, port, search } = urlObj;
|
||||
let { pathname } = urlObj;
|
||||
if (url.startsWith(DEFAULT_BASE_URL_PREFIX)) {
|
||||
return `${protocol}//${hostname}${port ? `:${port}` : ''}${desensitizeAccountId(pathname)}${search}`;
|
||||
} else {
|
||||
|
||||
@@ -840,7 +840,7 @@ describe('GoogleGenerativeAIStream', () => {
|
||||
|
||||
'id: chat_1',
|
||||
'event: grounding',
|
||||
`data: {\"citations\":[{\"favicon\":\"npmjs.com\",\"title\":\"npmjs.com\",\"url\":\"https://vertexaisearch.cloud.google.com/grounding-api-redirect/AbF9wXG1234545\"},{\"favicon\":\"google.dev\",\"title\":\"google.dev\",\"url\":\"https://vertexaisearch.cloud.google.com/grounding-api-redirect/AbF9wXE9288334\"}],\"searchQueries\":[\"sdk latest version\"]}\n`,
|
||||
`data: {"citations":[{"favicon":"npmjs.com","title":"npmjs.com","url":"https://vertexaisearch.cloud.google.com/grounding-api-redirect/AbF9wXG1234545"},{"favicon":"google.dev","title":"google.dev","url":"https://vertexaisearch.cloud.google.com/grounding-api-redirect/AbF9wXE9288334"}],"searchQueries":["sdk latest version"]}\n`,
|
||||
// stop
|
||||
'id: chat_1',
|
||||
'event: stop',
|
||||
@@ -928,7 +928,7 @@ describe('GoogleGenerativeAIStream', () => {
|
||||
[
|
||||
'id: chat_1',
|
||||
'event: tool_calls',
|
||||
'data: [{"function":{"arguments":"{\\"query\\":\\"\\\\\\\"version\\\\\\":\\",\\"repo\\":\\"lobehub/lobe-chat\\",\\"path\\":\\"package.json\\"}","name":"grep____searchGitHub____mcp"},"id":"grep____searchGitHub____mcp_0_abcd1234","index":0,"thoughtSignature":"123","type":"function"}]\n',
|
||||
'data: [{"function":{"arguments":"{\\"query\\":\\"\\\\\\"version\\\\\\":\\",\\"repo\\":\\"lobehub/lobe-chat\\",\\"path\\":\\"package.json\\"}","name":"grep____searchGitHub____mcp"},"id":"grep____searchGitHub____mcp_0_abcd1234","index":0,"thoughtSignature":"123","type":"function"}]\n',
|
||||
|
||||
'id: chat_1',
|
||||
'event: stop',
|
||||
|
||||
@@ -96,7 +96,7 @@ const transformGoogleGenerativeAIStream = (
|
||||
name: value.name,
|
||||
},
|
||||
id: generateToolCallId(index, value.name),
|
||||
index: index,
|
||||
index,
|
||||
thoughtSignature: value.thoughtSignature,
|
||||
type: 'function',
|
||||
}),
|
||||
@@ -328,7 +328,7 @@ export const GoogleGenerativeAIStream = (
|
||||
return rawStream
|
||||
.pipeThrough(
|
||||
createTokenSpeedCalculator(transformWithPayload, {
|
||||
enableStreaming: enableStreaming,
|
||||
enableStreaming,
|
||||
inputStartAt,
|
||||
streamStack,
|
||||
}),
|
||||
|
||||
@@ -22,7 +22,7 @@ const transformOllamaStream = (chunk: ChatResponse, stack: StreamContext): Strea
|
||||
name: value.function?.name ?? null,
|
||||
},
|
||||
id: generateToolCallId(index, value.function?.name),
|
||||
index: index,
|
||||
index,
|
||||
type: 'function',
|
||||
})),
|
||||
id: stack.id,
|
||||
|
||||
@@ -45,7 +45,7 @@ const processMarkdownBase64Images = (text: string): { cleanedText: string; urls:
|
||||
if (!text) return { cleanedText: text, urls: [] };
|
||||
|
||||
const urls: string[] = [];
|
||||
const mdRegex = /!\[[^\]]*]\(\s*(data:image\/[\d+.A-Za-z-]+;base64,[^\s)]+)\s*\)/g;
|
||||
const mdRegex = /!\[[^\]]*\]\(\s*(data:image\/[\d+.A-Za-z-]+;base64,[^\s)]+)\s*\)/g;
|
||||
let cleanedText = text;
|
||||
let m: RegExpExecArray | null;
|
||||
|
||||
@@ -605,7 +605,7 @@ export const OpenAIStream = (
|
||||
.pipeThrough(createFirstErrorHandleTransformer(bizErrorTypeTransformer, payload?.provider))
|
||||
.pipeThrough(
|
||||
createTokenSpeedCalculator(transformWithProvider, {
|
||||
enableStreaming: enableStreaming,
|
||||
enableStreaming,
|
||||
inputStartAt,
|
||||
streamStack,
|
||||
}),
|
||||
|
||||
@@ -219,7 +219,7 @@ export const OpenAIResponsesStream = (
|
||||
.pipeThrough(createFirstErrorHandleTransformer(bizErrorTypeTransformer, payload?.provider))
|
||||
.pipeThrough(
|
||||
createTokenSpeedCalculator(transformWithPayload, {
|
||||
enableStreaming: enableStreaming,
|
||||
enableStreaming,
|
||||
inputStartAt,
|
||||
streamStack,
|
||||
}),
|
||||
|
||||
@@ -160,7 +160,7 @@ export const QwenAIStream = (
|
||||
return readableStream
|
||||
.pipeThrough(
|
||||
createTokenSpeedCalculator(transformQwenStream, {
|
||||
enableStreaming: enableStreaming,
|
||||
enableStreaming,
|
||||
inputStartAt,
|
||||
streamStack: streamContext,
|
||||
}),
|
||||
|
||||
@@ -178,7 +178,7 @@ describe('SparkAIStream', () => {
|
||||
expect(chunks).toEqual([
|
||||
'id: cha000b0bf9@dx193d1ffa61cb894532\n',
|
||||
'event: tool_calls\n',
|
||||
`data: [{\"function\":{\"arguments\":\"{\\\"city\\\":\\\"Shanghai\\\"}\",\"name\":\"realtime-weather____fetchCurrentWeather\"},\"id\":\"call_1\",\"index\":0,\"type\":\"function\"}]\n\n`,
|
||||
`data: [{"function":{"arguments":"{\\"city\\":\\"Shanghai\\"}","name":"realtime-weather____fetchCurrentWeather"},"id":"call_1","index":0,"type":"function"}]\n\n`,
|
||||
]);
|
||||
|
||||
expect(onToolCallMock).toHaveBeenCalledTimes(1);
|
||||
|
||||
@@ -41,14 +41,14 @@ export const convertOpenAIUsage = (
|
||||
const data = {
|
||||
acceptedPredictionTokens: usage.completion_tokens_details?.accepted_prediction_tokens,
|
||||
inputAudioTokens: usage.prompt_tokens_details?.audio_tokens,
|
||||
inputCacheMissTokens: inputCacheMissTokens,
|
||||
inputCacheMissTokens,
|
||||
inputCachedTokens: cachedTokens,
|
||||
inputCitationTokens: inputCitationTokens,
|
||||
inputTextTokens: inputTextTokens,
|
||||
outputAudioTokens: outputAudioTokens,
|
||||
outputImageTokens: outputImageTokens,
|
||||
inputCitationTokens,
|
||||
inputTextTokens,
|
||||
outputAudioTokens,
|
||||
outputImageTokens,
|
||||
outputReasoningTokens: outputReasoning,
|
||||
outputTextTokens: outputTextTokens,
|
||||
outputTextTokens,
|
||||
rejectedPredictionTokens: usage.completion_tokens_details?.rejected_prediction_tokens,
|
||||
totalInputTokens,
|
||||
totalOutputTokens: totalOutputTokensNormalized,
|
||||
@@ -98,17 +98,17 @@ export const convertOpenAIResponseUsage = (
|
||||
// and potentially filtered out later.
|
||||
acceptedPredictionTokens: undefined, // Not in ResponseUsage
|
||||
inputAudioTokens: undefined, // Not in ResponseUsage
|
||||
inputCacheMissTokens: inputCacheMissTokens,
|
||||
inputCachedTokens: inputCachedTokens,
|
||||
inputCacheMissTokens,
|
||||
inputCachedTokens,
|
||||
inputCitationTokens: undefined, // Not in ResponseUsage
|
||||
inputTextTokens: inputTextTokens,
|
||||
inputTextTokens,
|
||||
outputAudioTokens: undefined, // Not in ResponseUsage
|
||||
outputImageTokens: outputImageTokens,
|
||||
outputReasoningTokens: outputReasoningTokens,
|
||||
outputTextTokens: outputTextTokens,
|
||||
outputImageTokens,
|
||||
outputReasoningTokens,
|
||||
outputTextTokens,
|
||||
rejectedPredictionTokens: undefined, // Not in ResponseUsage
|
||||
totalInputTokens: totalInputTokens,
|
||||
totalOutputTokens: totalOutputTokens,
|
||||
totalInputTokens,
|
||||
totalOutputTokens,
|
||||
totalTokens: overallTotalTokens,
|
||||
} satisfies ModelTokensUsage; // This helps ensure all keys of ModelTokensUsage are considered
|
||||
|
||||
|
||||
@@ -237,7 +237,7 @@ export const testProvider = ({
|
||||
// Expect the chat method to throw an error with InvalidHunyuanAPIKey
|
||||
expect(e).toEqual({
|
||||
endpoint: defaultBaseURL,
|
||||
error: error,
|
||||
error,
|
||||
errorType: invalidErrorType,
|
||||
provider,
|
||||
});
|
||||
|
||||
@@ -266,7 +266,7 @@ describe('LobeInternLMAI - custom features', () => {
|
||||
|
||||
// Mock a model with abilities in model-bank
|
||||
vi.mock('model-bank', async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import('model-bank')>();
|
||||
const actual = await importOriginal<Record<string, unknown>>();
|
||||
return {
|
||||
...actual,
|
||||
LOBE_DEFAULT_MODEL_LIST: [
|
||||
|
||||
@@ -303,9 +303,9 @@ export class LobeReplicateAI implements LobeRuntimeAI {
|
||||
this.debugLog('[Replicate] Final imageUrl:', outputImageUrl);
|
||||
|
||||
return {
|
||||
height: height,
|
||||
height,
|
||||
imageUrl: outputImageUrl,
|
||||
width: width,
|
||||
width,
|
||||
};
|
||||
} catch (error) {
|
||||
throw this.handleError(error);
|
||||
@@ -399,7 +399,7 @@ export class LobeReplicateAI implements LobeRuntimeAI {
|
||||
// Generic error
|
||||
throw AgentRuntimeError.chat({
|
||||
endpoint: desensitizedEndpoint,
|
||||
error: error,
|
||||
error,
|
||||
errorType: AgentRuntimeErrorType.ProviderBizError,
|
||||
provider: this.id,
|
||||
});
|
||||
|
||||
@@ -2,7 +2,7 @@ import { ModelProvider } from 'model-bank';
|
||||
|
||||
import { createOpenAICompatibleRuntime } from '../../core/openaiCompatibleFactory';
|
||||
import { processMultiProviderModelList } from '../../utils/modelParse';
|
||||
import { StraicoChatModel, StraicoModelsResponse } from './type';
|
||||
import type { StraicoChatModel, StraicoModelsResponse } from './type';
|
||||
|
||||
const formatPrice = (pricing?: { coins?: number; words?: number }) => {
|
||||
if (!pricing || typeof pricing.coins !== 'number' || typeof pricing.words !== 'number') {
|
||||
@@ -27,7 +27,7 @@ export const LobeStraicoAI = createOpenAICompatibleRuntime({
|
||||
baseURL: 'https://api.straico.com/v0',
|
||||
chatCompletion: {
|
||||
handlePayload: (payload) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars, unused-imports/no-unused-vars
|
||||
|
||||
const { model, ...rest } = payload;
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import createDebug from 'debug';
|
||||
|
||||
import { CreateVideoOptions } from '../../../core/openaiCompatibleFactory';
|
||||
import { CreateVideoPayload, CreateVideoResponse } from '../../../types/video';
|
||||
import type { CreateVideoOptions } from '../../../core/openaiCompatibleFactory';
|
||||
import type { CreateVideoPayload, CreateVideoResponse } from '../../../types/video';
|
||||
|
||||
const log = createDebug('lobe-video:volcengine');
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import createDebug from 'debug';
|
||||
|
||||
import {
|
||||
import type {
|
||||
HandleCreateVideoWebhookPayload,
|
||||
HandleCreateVideoWebhookResult,
|
||||
} from '../../../types/video';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { RuntimeVideoGenParams } from 'model-bank';
|
||||
import type { RuntimeVideoGenParams } from 'model-bank';
|
||||
|
||||
export type CreateVideoPayload = {
|
||||
callbackUrl?: string;
|
||||
|
||||
@@ -73,13 +73,13 @@ export function extractStatusCodeFromError(message: string): {
|
||||
// Create JSON containing status code and message
|
||||
const resultJson = {
|
||||
message: messageContent,
|
||||
statusCode: statusCode,
|
||||
statusCode,
|
||||
statusCodeText: `[${statusCode} ${statusText}]`,
|
||||
};
|
||||
|
||||
return {
|
||||
errorDetails: resultJson,
|
||||
prefix: prefix,
|
||||
prefix,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,36 +1,37 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { PageSelection, PageSelectionSchema } from './pageSelection';
|
||||
import type { PageSelection} from './pageSelection';
|
||||
import { PageSelectionSchema } from './pageSelection';
|
||||
|
||||
export interface ModelTokensUsage {
|
||||
// Prediction tokens
|
||||
acceptedPredictionTokens?: number;
|
||||
inputAudioTokens?: number;
|
||||
// Input tokens breakdown
|
||||
/**
|
||||
* user prompt input
|
||||
*/
|
||||
// Input cache tokens
|
||||
inputCachedTokens?: number;
|
||||
inputCacheMissTokens?: number;
|
||||
inputWriteCacheTokens?: number;
|
||||
|
||||
inputTextTokens?: number;
|
||||
/**
|
||||
* user prompt image
|
||||
*/
|
||||
inputImageTokens?: number;
|
||||
inputAudioTokens?: number;
|
||||
inputCacheMissTokens?: number;
|
||||
/**
|
||||
* currently only pplx has citation_tokens
|
||||
*/
|
||||
inputCitationTokens?: number;
|
||||
/**
|
||||
* user prompt image
|
||||
*/
|
||||
inputImageTokens?: number;
|
||||
inputTextTokens?: number;
|
||||
|
||||
inputWriteCacheTokens?: number;
|
||||
outputAudioTokens?: number;
|
||||
outputImageTokens?: number;
|
||||
outputReasoningTokens?: number;
|
||||
|
||||
// Output tokens breakdown
|
||||
outputTextTokens?: number;
|
||||
outputImageTokens?: number;
|
||||
outputAudioTokens?: number;
|
||||
outputReasoningTokens?: number;
|
||||
|
||||
// Prediction tokens
|
||||
acceptedPredictionTokens?: number;
|
||||
rejectedPredictionTokens?: number;
|
||||
|
||||
// Total tokens
|
||||
@@ -79,8 +80,8 @@ export const ModelPerformanceSchema = z.object({
|
||||
// ============ Emoji Reaction ============ //
|
||||
|
||||
export interface EmojiReaction {
|
||||
emoji: string;
|
||||
count: number;
|
||||
emoji: string;
|
||||
users: string[];
|
||||
}
|
||||
|
||||
@@ -109,14 +110,6 @@ export interface ModelUsage extends ModelTokensUsage {
|
||||
}
|
||||
|
||||
export interface ModelPerformance {
|
||||
/**
|
||||
* tokens per second
|
||||
*/
|
||||
tps?: number;
|
||||
/**
|
||||
* time to first token (ms)
|
||||
*/
|
||||
ttft?: number;
|
||||
/**
|
||||
* from output start to output finish (ms)
|
||||
*/
|
||||
@@ -125,36 +118,60 @@ export interface ModelPerformance {
|
||||
* from input start to output finish (ms)
|
||||
*/
|
||||
latency?: number;
|
||||
/**
|
||||
* tokens per second
|
||||
*/
|
||||
tps?: number;
|
||||
/**
|
||||
* time to first token (ms)
|
||||
*/
|
||||
ttft?: number;
|
||||
}
|
||||
|
||||
export interface MessageMetadata extends ModelUsage, ModelPerformance {
|
||||
activeBranchIndex?: number;
|
||||
activeColumn?: boolean;
|
||||
finishType?: string;
|
||||
/**
|
||||
* Message collapse state
|
||||
* true: collapsed, false/undefined: expanded
|
||||
*/
|
||||
collapsed?: boolean;
|
||||
compare?: boolean;
|
||||
finishType?: string;
|
||||
/**
|
||||
* Tool inspect expanded state
|
||||
* true: expanded, false/undefined: collapsed
|
||||
*/
|
||||
inspectExpanded?: boolean;
|
||||
compare?: boolean;
|
||||
usage?: ModelUsage;
|
||||
performance?: ModelPerformance;
|
||||
/**
|
||||
* Task instruction (for role='task' messages)
|
||||
* The instruction given by supervisor to the agent
|
||||
* Thread's sourceMessageId links back to this message for status tracking
|
||||
*/
|
||||
instruction?: string;
|
||||
/**
|
||||
* Flag indicating if message content is multimodal (serialized MessageContentPart[])
|
||||
*/
|
||||
isMultimodal?: boolean;
|
||||
// message content is multimodal, display content in the streaming, won't save to db
|
||||
tempDisplayContent?: string;
|
||||
/**
|
||||
* Flag indicating if message is from the Supervisor agent in group orchestration
|
||||
* Used by conversation-flow to transform role to 'supervisor' for UI rendering
|
||||
*/
|
||||
isSupervisor?: boolean;
|
||||
/**
|
||||
* Page selections attached to user message
|
||||
* Used for Ask AI functionality to persist selection context
|
||||
*/
|
||||
pageSelections?: PageSelection[];
|
||||
performance?: ModelPerformance;
|
||||
/**
|
||||
* Flag indicating if message is pinned (excluded from compression)
|
||||
*/
|
||||
pinned?: boolean;
|
||||
/**
|
||||
* Emoji reactions on this message
|
||||
*/
|
||||
reactions?: EmojiReaction[];
|
||||
/**
|
||||
* Message scope - indicates the context in which this message was created
|
||||
* Used by conversation-flow to determine how to handle message grouping and display
|
||||
@@ -168,24 +185,8 @@ export interface MessageMetadata extends ModelUsage, ModelPerformance {
|
||||
* Used by callAgent tool (sub_agent) and group orchestration (group modes)
|
||||
*/
|
||||
subAgentId?: string;
|
||||
/**
|
||||
* Flag indicating if message is pinned (excluded from compression)
|
||||
*/
|
||||
pinned?: boolean;
|
||||
/**
|
||||
* Task instruction (for role='task' messages)
|
||||
* The instruction given by supervisor to the agent
|
||||
* Thread's sourceMessageId links back to this message for status tracking
|
||||
*/
|
||||
instruction?: string;
|
||||
taskTitle?: string;
|
||||
/**
|
||||
* Page selections attached to user message
|
||||
* Used for Ask AI functionality to persist selection context
|
||||
*/
|
||||
pageSelections?: PageSelection[];
|
||||
/**
|
||||
* Emoji reactions on this message
|
||||
*/
|
||||
reactions?: EmojiReaction[];
|
||||
// message content is multimodal, display content in the streaming, won't save to db
|
||||
tempDisplayContent?: string;
|
||||
usage?: ModelUsage;
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ export interface SkillResourceTreeNode {
|
||||
|
||||
export interface SkillResourceContent {
|
||||
content: string;
|
||||
encoding: 'utf-8' | 'base64';
|
||||
encoding: 'utf8' | 'base64';
|
||||
fileHash: string;
|
||||
fileType: string;
|
||||
path: string;
|
||||
|
||||
@@ -230,6 +230,10 @@ const TokenDetail = memo<TokenDetailProps>(({ usage, performance, model, provide
|
||||
<Icon icon={isShowCredit ? BadgeCent : CoinsIcon} />
|
||||
<AnimatedNumber
|
||||
duration={1500}
|
||||
// Force remount when switching between token/credit to prevent unwanted animation
|
||||
// See: https://github.com/lobehub/lobe-chat/pull/10098
|
||||
key={isShowCredit ? 'credit' : 'token'}
|
||||
value={totalCount}
|
||||
formatter={(value) => {
|
||||
const roundedValue = Math.round(value);
|
||||
if (isShortFormat) {
|
||||
@@ -237,10 +241,6 @@ const TokenDetail = memo<TokenDetailProps>(({ usage, performance, model, provide
|
||||
}
|
||||
return new Intl.NumberFormat('en-US').format(roundedValue);
|
||||
}}
|
||||
// Force remount when switching between token/credit to prevent unwanted animation
|
||||
// See: https://github.com/lobehub/lobe-chat/pull/10098
|
||||
key={isShowCredit ? 'credit' : 'token'}
|
||||
value={totalCount}
|
||||
/>
|
||||
</Center>
|
||||
</Popover>
|
||||
|
||||
@@ -291,10 +291,10 @@ const AddButton = () => {
|
||||
multiple
|
||||
id="folder-upload-input"
|
||||
style={{ display: 'none' }}
|
||||
onChange={handleFolderUploadWithClose}
|
||||
type="file"
|
||||
// @ts-expect-error - webkitdirectory is not in the React types
|
||||
webkitdirectory=""
|
||||
onChange={handleFolderUploadWithClose}
|
||||
/>
|
||||
<input
|
||||
accept=".zip"
|
||||
|
||||
@@ -35,12 +35,12 @@ export const SuccessState = memo<SuccessStateProps>(
|
||||
>
|
||||
<ImageItem
|
||||
alt={prompt}
|
||||
preview={{
|
||||
src: generation.asset!.url,
|
||||
}}
|
||||
style={{ height: '100%', width: '100%' }}
|
||||
// Thumbnail quality is too bad
|
||||
url={generation.asset!.url}
|
||||
preview={{
|
||||
src: generation.asset!.url,
|
||||
}}
|
||||
/>
|
||||
<ActionButtons
|
||||
showDownload
|
||||
|
||||
@@ -42,13 +42,13 @@ const SystemAgentForm = memo(
|
||||
{
|
||||
children: (
|
||||
<ModelSelect
|
||||
showAbility={false}
|
||||
// value={value}
|
||||
onChange={async (props) => {
|
||||
setLoading(true);
|
||||
await updateSystemAgent(systemAgentKey, props);
|
||||
setLoading(false);
|
||||
}}
|
||||
showAbility={false}
|
||||
// value={value}
|
||||
/>
|
||||
),
|
||||
desc: t(`systemAgent.${systemAgentKey}.modelDesc`),
|
||||
|
||||
@@ -7,7 +7,7 @@ const mockCreateGlobalFile = vi.fn().mockResolvedValue({ fileHash: 'mock-file-ha
|
||||
const mockGetFileContentByHash = vi.fn().mockResolvedValue('file content');
|
||||
const mockGetFileByteArrayByHash = vi
|
||||
.fn()
|
||||
.mockResolvedValue(new Uint8Array([0x89, 0x50, 0x4e, 0x47]));
|
||||
.mockResolvedValue(new Uint8Array([0x89, 0x50, 0x4E, 0x47]));
|
||||
const mockUploadBuffer = vi.fn().mockResolvedValue({ key: 'mock-key' });
|
||||
|
||||
// Mock FileService only (no longer need FileModel)
|
||||
@@ -215,11 +215,11 @@ describe('SkillResourceService', () => {
|
||||
|
||||
expect(result).toEqual({
|
||||
content: 'file content',
|
||||
encoding: 'utf-8',
|
||||
encoding: 'utf8',
|
||||
fileHash: 'abc123fileHash',
|
||||
fileType: 'text/plain',
|
||||
path: 'test.txt',
|
||||
size: Buffer.byteLength('file content', 'utf-8'),
|
||||
size: Buffer.byteLength('file content', 'utf8'),
|
||||
});
|
||||
expect(mockGetFileContentByHash).toHaveBeenCalledWith('abc123fileHash');
|
||||
});
|
||||
@@ -227,7 +227,7 @@ describe('SkillResourceService', () => {
|
||||
it('should read binary resource content with base64 encoding', async () => {
|
||||
const service = new SkillResourceService({} as any, 'user-1');
|
||||
const resources = { 'image.png': { fileHash: 'binaryFileHash', size: 1024 } };
|
||||
const binaryData = new Uint8Array([0x89, 0x50, 0x4e, 0x47]);
|
||||
const binaryData = new Uint8Array([0x89, 0x50, 0x4E, 0x47]);
|
||||
mockGetFileByteArrayByHash.mockResolvedValue(binaryData);
|
||||
|
||||
const result = await service.readResource(resources, 'image.png');
|
||||
|
||||
@@ -88,11 +88,11 @@ export class SkillResourceService {
|
||||
|
||||
return {
|
||||
content,
|
||||
encoding: 'utf-8',
|
||||
encoding: 'utf8',
|
||||
fileHash: meta.fileHash,
|
||||
fileType,
|
||||
path: virtualPath,
|
||||
size: Buffer.byteLength(content, 'utf-8'),
|
||||
size: Buffer.byteLength(content, 'utf8'),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user