🐛 fix(creds): replace hardcoded session_context values with template variables (#15352)

* 🐛 fix(creds): replace hardcoded session_context values with template variables

- Replace hardcoded `Current user`, `Session date`, `Sandbox mode` in
  systemRole.ts with {{username}}, {{session_date}}, {{sandbox_enabled}}
- Inject {{session_date}} via Intl.DateTimeFormat in RuntimeExecutors
- Remove isCredsEnabled gate so {{CREDS_LIST}} / {{KLAVIS_SERVICES_LIST}}
  are always substituted when userId is available, regardless of execution path

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* 🧪 test(creds): mock klavisEnv to prevent t3-oss jsdom throws in tests

klavisEnv uses @t3-oss/env-nextjs which throws in jsdom (vitest treats
it as a client context). Previously the isCredsEnabled gate short-circuited
before the access; now that the gate is removed, the mock is needed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* 🐛 fix(creds): add client-side generators and restore isCredsEnabled gate

- Add session_date and sandbox_enabled variable generators to
  contextEngineering.ts so client-side renders substitute them correctly
- Restore isCredsEnabled gate in RuntimeExecutors to avoid fetching creds
  on every call_llm step; now checks both enabledToolIds (client-activated
  path) and manifestMap (execAgent path) to cover all execution paths

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* 🔨 chore(creds): revert isCredsEnabled gate in RuntimeExecutors

Remove the isCredsEnabled OR-condition that caused execAgent test failures.
Keep session_date, sandbox_enabled, and always-inject CREDS_LIST/KLAVIS_SERVICES_LIST.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
LiJian
2026-05-31 20:03:51 +08:00
committed by GitHub
parent e4d5017e76
commit 4bc77fc103
4 changed files with 36 additions and 13 deletions
@@ -1,9 +1,9 @@
export const systemPrompt = `You have access to a LobeHub Credentials Tool. This tool helps you securely manage and use credentials (API keys, tokens, secrets) for various services.
<session_context>
Current user: Arvin Xu
Session date: Wednesday, May 20, 2026
Sandbox mode: false
Current user: {{username}}
Session date: {{session_date}}
Sandbox mode: {{sandbox_enabled}}
</session_context>
<available_credentials>
@@ -67,7 +67,7 @@ When suggesting to save, always:
</credential_saving_triggers>
<sandbox_integration>
**Only applies when sandbox mode is enabled (current value: false).**
**Only applies when sandbox mode is enabled (current value: {{sandbox_enabled}}).**
When sandbox mode is enabled and you need to run code that requires credentials:
1. Check if the required credential is in the available credentials list
@@ -14,7 +14,6 @@ import {
} from '@lobechat/agent-runtime';
import { LobeActivatorIdentifier } from '@lobechat/builtin-tool-activator';
import {
CredsIdentifier,
type CredSummary,
generateCredsList,
generateKlavisServicesList,
@@ -639,18 +638,25 @@ export const createRuntimeExecutors = (
// {{sandbox_enabled}} — mirrors client-side check for lobe-cloud-sandbox.
const sandboxEnabled = String(resolved.enabledToolIds.includes('lobe-cloud-sandbox'));
// {{session_date}} — current date formatted for user's timezone.
const sessionDate = new Intl.DateTimeFormat('en-US', {
day: 'numeric',
month: 'long',
timeZone: ctx.userTimezone || 'UTC',
weekday: 'long',
year: 'numeric',
}).format(new Date());
// {{memory_effort}} — read from agentConfig chatConfig; no extra query needed.
const memoryEffort = String(
(state.metadata?.agentConfig as any)?.chatConfig?.memory?.effort ?? '',
);
// {{CREDS_LIST}} — used by lobe-creds system role.
// Gate on manifestMap presence, NOT enabledToolIds: in execAgent mode lobe-creds is
// added to manifestMap (for activator discovery) but never into enabledToolIds, so
// checking enabledToolIds would always be false while the system role IS injected.
const isCredsEnabled = !!resolved.manifestMap[CredsIdentifier];
// Always fetched when userId is available so substitution works regardless of which
// execution path (execAgent / client-side activator) injected the system role.
let credsListStr = '';
if (isCredsEnabled && ctx.userId) {
if (ctx.userId) {
try {
const { MarketService } = await import('@/server/services/market');
const marketService = new MarketService({ userInfo: { userId: ctx.userId } });
@@ -675,7 +681,7 @@ 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 (isCredsEnabled && ctx.serverDB && ctx.userId && !!klavisEnv.KLAVIS_API_KEY) {
if (ctx.serverDB && ctx.userId && !!klavisEnv.KLAVIS_API_KEY) {
try {
const { PluginModel } = await import('@/database/models/plugin');
const pluginModel = new PluginModel(ctx.serverDB, ctx.userId);
@@ -718,10 +724,11 @@ export const createRuntimeExecutors = (
// User identity variables
username: serverUsername,
language: serverLanguage,
session_date: sessionDate,
// Creds tool variables
sandbox_enabled: sandboxEnabled,
...(isCredsEnabled && { CREDS_LIST: credsListStr }),
...(isCredsEnabled && { KLAVIS_SERVICES_LIST: klavisServicesListStr }),
CREDS_LIST: credsListStr,
KLAVIS_SERVICES_LIST: klavisServicesListStr,
// Memory tool variables
memory_effort: memoryEffort,
},
@@ -62,6 +62,13 @@ 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 },
}));
describe('RuntimeExecutors', () => {
let mockMessageModel: any;
let mockStreamManager: any;
@@ -719,6 +719,15 @@ export const contextEngineering = async ({
CREDS_LIST: () => (credsList ? generateCredsList(credsList) : ''),
// NOTICE: required by builtin-tool-creds/src/systemRole.ts (Klavis integrations)
KLAVIS_SERVICES_LIST: () => klavisServicesList,
// NOTICE: required by builtin-tool-creds/src/systemRole.ts (session_context)
session_date: () =>
new Intl.DateTimeFormat('en-US', {
day: 'numeric',
month: 'long',
weekday: 'long',
year: 'numeric',
}).format(new Date()),
sandbox_enabled: () => String(tools?.includes('lobe-cloud-sandbox') ?? false),
// NOTICE(@nekomeowww): required by builtin-tool-memory/src/systemRole.ts
memory_effort: () => (userMemoryConfig ? (memoryContext?.effort ?? '') : ''),
// Current agent + topic identity — referenced by the LobeHub builtin