Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
10 changes: 5 additions & 5 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -425,14 +425,14 @@ OPENAI_API_KEY=sk-xxxxxxxxx
# MCP_TOOL_TIMEOUT=60000

# #######################################
# ######### Klavis Service ##############
# ######### Composio Service ############
# #######################################

# Klavis API Key for accessing Strata hosted MCP servers
# Get your API key from: https://klavis.io
# Composio API Key for accessing hosted integrations (Gmail, Slack, etc.)
# Get your API key from: https://composio.dev
# IMPORTANT: This key is stored server-side only and NEVER exposed to the client
# When this key is set, Klavis integration will be automatically enabled
# KLAVIS_API_KEY=your_klavis_api_key_here
# When this key is set, Composio integration will be automatically enabled
# COMPOSIO_API_KEY=your_composio_api_key_here

# #######################################
# #### Message Gateway (IM Integration) ##
Expand Down
4 changes: 2 additions & 2 deletions apps/server/src/globalConfig/getServerGlobalConfig.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ const mockGlobalConfigDependencies = (
ENABLE_BUSINESS_FEATURES: enableBusinessFeatures,
}));

vi.doMock('@/config/klavis', () => ({
klavisEnv: {},
vi.doMock('@/config/composio', () => ({
composioEnv: {},
}));

vi.doMock('@/const/version', () => ({
Expand Down
4 changes: 2 additions & 2 deletions apps/server/src/globalConfig/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ENABLE_BUSINESS_FEATURES } from '@lobechat/business-const';
import { ModelProvider } from 'model-bank';

import { klavisEnv } from '@/config/klavis';
import { composioEnv } from '@/config/composio';
import { isDesktop } from '@/const/version';
import { appEnv, getAppConfig } from '@/envs/app';
import { authEnv } from '@/envs/auth';
Expand Down Expand Up @@ -104,9 +104,9 @@ export const getServerGlobalConfig = async () => {
disableEmailPassword: authEnv.AUTH_DISABLE_EMAIL_PASSWORD,
enableBusinessFeatures: ENABLE_BUSINESS_FEATURES,
enableEmailVerification: authEnv.AUTH_EMAIL_VERIFICATION,
enableComposio: !!composioEnv.COMPOSIO_API_KEY,
enableGatewayMode:
ENABLE_BUSINESS_FEATURES || (!!appEnv.ENABLE_AGENT_GATEWAY && !!appEnv.AGENT_GATEWAY_URL),
enableKlavis: !!klavisEnv.KLAVIS_API_KEY,
enableLobehubSkill: !!(appEnv.MARKET_TRUSTED_CLIENT_SECRET && appEnv.MARKET_TRUSTED_CLIENT_ID),
enableMagicLink: authEnv.AUTH_ENABLE_MAGIC_LINK,
enableMarketTrustedClient: !!(
Expand Down
37 changes: 18 additions & 19 deletions apps/server/src/modules/AgentRuntime/RuntimeExecutors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ import {
} from '@lobechat/agent-runtime';
import { LobeActivatorIdentifier } from '@lobechat/builtin-tool-activator';
import {
type ComposioServiceSummary,
type CredSummary,
generateComposioServicesList,
generateCredsList,
generateKlavisServicesList,
type KlavisServiceSummary,
} from '@lobechat/builtin-tool-creds';
import { LocalSystemManifest } from '@lobechat/builtin-tool-local-system';
import { BRANDING_PROVIDER } from '@lobechat/business-const';
import { KLAVIS_SERVER_TYPES } from '@lobechat/const';
import { COMPOSIO_APP_TYPES } from '@lobechat/const';
import {
type AgentContextDocument,
type AgentGroupConfig,
Expand Down Expand Up @@ -68,7 +68,7 @@ import {
import { sanitizeToolCallArguments, serializePartsForStorage } from '@lobechat/utils';
import debug from 'debug';

import { klavisEnv } from '@/config/klavis';
import { composioEnv } from '@/config/composio';
import { type MessageModel, MessageModel as MessageModelClass } from '@/database/models/message';
import { TopicModel } from '@/database/models/topic';
import { UserModel } from '@/database/models/user';
Expand Down Expand Up @@ -999,39 +999,38 @@ export const createRuntimeExecutors = (
}
}

// {{KLAVIS_SERVICES_LIST}} — used by lobe-creds system role (Klavis integrations section).
// Mirrors client-side: klavisStoreSelectors.getServers() filtered by connection status.
let klavisServicesListStr = '';
if (ctx.serverDB && ctx.userId && !!klavisEnv.KLAVIS_API_KEY) {
// {{COMPOSIO_SERVICES_LIST}} — used by lobe-creds system role (Composio integrations section).
let composioServicesListStr = '';
if (ctx.serverDB && ctx.userId && !!composioEnv.COMPOSIO_API_KEY) {
try {
const { PluginModel } = await import('@/database/models/plugin');
const pluginModel = new PluginModel(ctx.serverDB, ctx.userId, ctx.workspaceId);
const allPlugins = await pluginModel.query();
const validKlavisIds = new Set(KLAVIS_SERVER_TYPES.map((t) => t.identifier));
const validComposioIds = new Set(COMPOSIO_APP_TYPES.map((t) => t.identifier));
const connectedIds = new Set(
allPlugins
.filter(
(p) =>
validKlavisIds.has(p.identifier) &&
(p.customParams as any)?.klavis?.isAuthenticated === true,
validComposioIds.has(p.identifier) &&
(p.customParams as any)?.composio?.status === 'ACTIVE',
)
.map((p) => p.identifier),
);
const connected: KlavisServiceSummary[] = KLAVIS_SERVER_TYPES.filter((t) =>
const connected: ComposioServiceSummary[] = COMPOSIO_APP_TYPES.filter((t) =>
connectedIds.has(t.identifier),
).map((t) => ({ identifier: t.identifier, name: t.label }));
const available: KlavisServiceSummary[] = KLAVIS_SERVER_TYPES.filter(
const available: ComposioServiceSummary[] = COMPOSIO_APP_TYPES.filter(
(t) => !connectedIds.has(t.identifier),
).map((t) => ({ identifier: t.identifier, name: t.label }));
klavisServicesListStr = generateKlavisServicesList(connected, available);
composioServicesListStr = generateComposioServicesList(connected, available);
log(
'Fetched Klavis services for {{KLAVIS_SERVICES_LIST}}: connected=%d, available=%d',
'Fetched Composio services for {{COMPOSIO_SERVICES_LIST}}: connected=%d, available=%d',
connected.length,
available.length,
);
} catch (error) {
log(
'Failed to fetch Klavis services for {{KLAVIS_SERVICES_LIST}} substitution: %O',
'Failed to fetch Composio services for {{COMPOSIO_SERVICES_LIST}} substitution: %O',
error,
);
}
Expand All @@ -1055,7 +1054,7 @@ export const createRuntimeExecutors = (
sandbox_enabled: sandboxEnabled,
sandbox_uploaded_files: sandboxUploadedFiles,
CREDS_LIST: credsListStr,
KLAVIS_SERVICES_LIST: klavisServicesListStr,
COMPOSIO_SERVICES_LIST: composioServicesListStr,
// Memory tool variables
memory_effort: memoryEffort,
},
Expand Down Expand Up @@ -2446,7 +2445,7 @@ export const createRuntimeExecutors = (
execution = { attempts: 1, result: dispatchResult };
} else {
// Inject source from sourceMap so BuiltinToolsExecutor can route
// lobehubSkill / klavis tools correctly (LLM responses don't carry source)
// lobehubSkill / composio tools correctly (LLM responses don't carry source)
if (toolSource && !chatToolPayload.source) {
chatToolPayload.source = toolSource;
}
Expand Down Expand Up @@ -3026,7 +3025,7 @@ export const createRuntimeExecutors = (
execution = { attempts: 1, result: dispatchResult };
} else {
// Inject source from sourceMap so BuiltinToolsExecutor can route
// lobehubSkill / klavis tools correctly (LLM responses don't carry source)
// lobehubSkill / composio tools correctly (LLM responses don't carry source)
const batchToolSource =
state.operationToolSet?.sourceMap?.[chatToolPayload.identifier] ??
state.toolSourceMap?.[chatToolPayload.identifier];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,11 @@ vi.mock('model-bank', () => ({
LOBE_DEFAULT_MODEL_LIST: mockBuiltinModels,
}));

// klavisEnv uses @t3-oss/env-nextjs which throws in jsdom (treats it as client context)
vi.mock('@/config/klavis', () => ({
getKlavisConfig: vi.fn(),
getServerKlavisApiKey: vi.fn().mockReturnValue(undefined),
klavisEnv: { KLAVIS_API_KEY: undefined },
// composioEnv uses @t3-oss/env-nextjs which throws in jsdom (treats it as client context)
vi.mock('@/config/composio', () => ({
getComposioConfig: vi.fn(),
getServerComposioApiKey: vi.fn().mockReturnValue(undefined),
composioEnv: { COMPOSIO_API_KEY: undefined },
}));

// fileEnv uses @t3-oss/env-core; stub the only field the runtime reads so the
Expand Down
4 changes: 2 additions & 2 deletions apps/server/src/modules/Mecha/AgentToolsEngine/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ export const createServerToolsEngine = (
// Combine all manifests, then drop anything whose identifier the caller
// has explicitly forbidden for this turn. The post-merge filter closes
// the second half of the wall: an installed plugin or a
// Skill/Klavis manifest claiming `lobe-remote-device` would otherwise
// Skill/Composio manifest claiming `lobe-remote-device` would otherwise
// slip through `buildAllowedBuiltinTools` (which only touches the
// builtin source).
const combinedManifests = [...pluginManifests, ...builtinManifests, ...additionalManifests];
Expand Down Expand Up @@ -256,7 +256,7 @@ export const createServerAgentToolsEngine = (
: isChatMode
? chatModeAllowedToolIds
: defaultToolIds,
// Post-merge wall: a plugin or Skill/Klavis manifest claiming a
// Post-merge wall: a plugin or Skill/Composio manifest claiming a
// device identifier survives `buildAllowedBuiltinTools` (which only
// filters the builtin source). Excluding the identifiers here drops
// them from the combined `manifestSchemas` so the activator cannot
Expand Down
4 changes: 2 additions & 2 deletions apps/server/src/modules/Mecha/AgentToolsEngine/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export interface ServerAgentToolsContext {
* Configuration options for createServerToolsEngine
*/
export interface ServerAgentToolsEngineConfig {
/** Additional manifests to include (e.g., Klavis tools) */
/** Additional manifests to include (e.g., Composio tools) */
additionalManifests?: LobeToolManifest[];
/**
* Override the list of builtin tools fed into the engine's
Expand All @@ -39,7 +39,7 @@ export interface ServerAgentToolsEngineConfig {
/**
* Identifiers to drop from `manifestSchemas` after combining plugin,
* builtin, and additional manifests. Filtering builtins alone is not
* enough: an installed plugin or a Skill/Klavis manifest can declare
* enough: an installed plugin or a Skill/Composio manifest can declare
* `identifier: 'lobe-remote-device'` and slip past `buildAllowedBuiltinTools`.
* This is the final post-merge wall referenced in .
*/
Expand Down
Loading
Loading