From 665b48239047028109bd4e54bd4e7b984a966077 Mon Sep 17 00:00:00 2001 From: LiJian Date: Tue, 21 Apr 2026 15:25:55 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20fix:=20inject=20timezone=20and?= =?UTF-8?q?=20cron=20jobs=20list=20into=20cron=20tool=20system=20prompt=20?= =?UTF-8?q?(#14012)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 🐛 fix: inject timezone and cron jobs list into cron tool system prompt Add {{timezone}} to cron systemRole session_context so the model knows the user's local timezone when creating scheduled tasks. Wire up the {{CRON_JOBS_LIST}} placeholder that was already referenced in the systemRole but never populated — now fetches the agent's existing cron jobs via tRPC and injects them, following the same pattern as CREDS_LIST. Co-Authored-By: Claude Opus 4.6 (1M context) * 🐛 fix: limit cron jobs context to 4 items to save context window Only inject a preview of up to 4 cron jobs into the system prompt. When there are more, append a hint directing the model to call listCronJobs API for the full list. This avoids bloating the context window for agents with many scheduled tasks. Co-Authored-By: Claude Opus 4.6 (1M context) --------- Co-authored-by: Claude Opus 4.6 (1M context) --- packages/builtin-tool-cron/src/helpers.ts | 25 +++++++++++ packages/builtin-tool-cron/src/index.ts | 1 + packages/builtin-tool-cron/src/systemRole.ts | 1 + src/services/chat/mecha/contextEngineering.ts | 43 +++++++++++++++++++ 4 files changed, 70 insertions(+) create mode 100644 packages/builtin-tool-cron/src/helpers.ts diff --git a/packages/builtin-tool-cron/src/helpers.ts b/packages/builtin-tool-cron/src/helpers.ts new file mode 100644 index 0000000000..543ddbc98d --- /dev/null +++ b/packages/builtin-tool-cron/src/helpers.ts @@ -0,0 +1,25 @@ +import type { CronJobSummaryForContext } from './types'; + +const formatCronJob = (job: CronJobSummaryForContext): string => { + const status = job.enabled ? 'enabled' : 'disabled'; + const execInfo = + job.remainingExecutions != null ? `${job.remainingExecutions} remaining` : 'unlimited'; + const lastRun = job.lastExecutedAt ?? 'never'; + const desc = job.description ? ` - ${job.description}` : ''; + + return ` - ${job.name || 'Unnamed'} (id: ${job.id}): ${job.cronPattern} [${job.timezone}] [${status}, ${execInfo}, ${job.totalExecutions} completed, last run: ${lastRun}]${desc}`; +}; + +export const generateCronJobsList = (jobs: CronJobSummaryForContext[], total?: number): string => { + if (jobs.length === 0) { + return 'No scheduled tasks configured for this agent.'; + } + + const lines = jobs.map(formatCronJob); + + if (total && total > jobs.length) { + lines.push(` (showing ${jobs.length} of ${total} tasks — use listCronJobs to see all)`); + } + + return lines.join('\n'); +}; diff --git a/packages/builtin-tool-cron/src/index.ts b/packages/builtin-tool-cron/src/index.ts index c6ad95cb5a..fb62eb03d5 100644 --- a/packages/builtin-tool-cron/src/index.ts +++ b/packages/builtin-tool-cron/src/index.ts @@ -1,4 +1,5 @@ export { CronExecutionRuntime, type ICronService } from './ExecutionRuntime'; +export { generateCronJobsList } from './helpers'; export { CronIdentifier, CronManifest } from './manifest'; export { systemPrompt } from './systemRole'; export { diff --git a/packages/builtin-tool-cron/src/systemRole.ts b/packages/builtin-tool-cron/src/systemRole.ts index 28ab37d901..ddea4fc5d0 100644 --- a/packages/builtin-tool-cron/src/systemRole.ts +++ b/packages/builtin-tool-cron/src/systemRole.ts @@ -4,6 +4,7 @@ export const systemPrompt = `You have access to a LobeHub Scheduled Tasks Tool. Current user: {{username}} Session date: {{date}} Current agent: {{agent_id}} +User timezone: {{timezone}} diff --git a/src/services/chat/mecha/contextEngineering.ts b/src/services/chat/mecha/contextEngineering.ts index 71c9301a1f..a4265549c3 100644 --- a/src/services/chat/mecha/contextEngineering.ts +++ b/src/services/chat/mecha/contextEngineering.ts @@ -2,6 +2,11 @@ import { LobeActivatorIdentifier } from '@lobechat/builtin-tool-activator'; import { AgentBuilderIdentifier } from '@lobechat/builtin-tool-agent-builder'; import { AgentManagementIdentifier } from '@lobechat/builtin-tool-agent-management'; import { CredsIdentifier, type CredSummary, generateCredsList } from '@lobechat/builtin-tool-creds'; +import { + CronIdentifier, + type CronJobSummaryForContext, + generateCronJobsList, +} from '@lobechat/builtin-tool-cron'; import { GroupAgentBuilderIdentifier } from '@lobechat/builtin-tool-group-agent-builder'; import { GTDIdentifier } from '@lobechat/builtin-tool-gtd'; import { WebOnboardingIdentifier } from '@lobechat/builtin-tool-web-onboarding'; @@ -377,6 +382,42 @@ export const contextEngineering = async ({ } } + // Resolve cron jobs context for cron tool + // Only inject a small preview (up to 4) to save context window; + // the model can call listCronJobs API for the full list. + const isCronEnabled = tools?.includes(CronIdentifier) ?? false; + let cronJobsList: CronJobSummaryForContext[] | undefined; + let cronJobsTotal = 0; + + if (isCronEnabled && agentId) { + try { + const cronResult = await lambdaClient.agentCronJob.list.query({ agentId, limit: 4 }); + const jobs = (cronResult as any)?.data ?? []; + cronJobsTotal = (cronResult as any)?.pagination?.total ?? jobs.length; + cronJobsList = jobs.map( + (job: any): CronJobSummaryForContext => ({ + cronPattern: job.cronPattern, + description: job.description, + enabled: job.enabled, + id: job.id, + lastExecutedAt: job.lastExecutedAt, + name: job.name, + remainingExecutions: job.remainingExecutions, + timezone: job.timezone ?? 'UTC', + totalExecutions: job.totalExecutions ?? 0, + }), + ); + log( + 'Cron jobs context resolved: count=%d, total=%d', + cronJobsList?.length ?? 0, + cronJobsTotal, + ); + } catch (error) { + // Silently fail - cron context is optional + log('Failed to resolve cron jobs context:', error); + } + } + const userMemoryConfig = enableUserMemories && userMemoryData ? { @@ -694,6 +735,8 @@ export const contextEngineering = async ({ ...VARIABLE_GENERATORS, // NOTICE: required by builtin-tool-creds/src/systemRole.ts CREDS_LIST: () => (credsList ? generateCredsList(credsList) : ''), + // NOTICE: required by builtin-tool-cron/src/systemRole.ts + CRON_JOBS_LIST: () => (cronJobsList ? generateCronJobsList(cronJobsList, cronJobsTotal) : ''), // NOTICE(@nekomeowww): required by builtin-tool-memory/src/systemRole.ts memory_effort: () => (userMemoryConfig ? (memoryContext?.effort ?? '') : ''), // Current agent + topic identity — referenced by the LobeHub builtin