fix: 彻底移除 /loop 及 cron 工具的 feature('AGENT_TRIGGERS') gate

上次提交仅移除了 isKairosCronEnabled 中的 gate,但 /loop 整条链路
仍被 feature('AGENT_TRIGGERS') 拦截导致无法使用:
- skills/bundled/index.ts: registerLoopSkill() 未被调用
- tools.ts: CronCreate/Delete/List 工具未加载
- constants/tools.ts: cron 工具名未加入 teammate 工具列表
- screens/REPL.tsx: useScheduledTasks hook 被跳过
- cli/print.ts: pipe 模式 cron 调度器未初始化

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
claude-code-best 2026-04-01 11:57:16 +08:00
parent 33fe4940e1
commit 2934f30084
5 changed files with 15 additions and 41 deletions

View File

@ -362,15 +362,9 @@ const proactiveModule =
feature('PROACTIVE') || feature('KAIROS')
? (require('../proactive/index.js') as typeof import('../proactive/index.js'))
: null
const cronSchedulerModule = feature('AGENT_TRIGGERS')
? (require('../utils/cronScheduler.js') as typeof import('../utils/cronScheduler.js'))
: null
const cronJitterConfigModule = feature('AGENT_TRIGGERS')
? (require('../utils/cronJitterConfig.js') as typeof import('../utils/cronJitterConfig.js'))
: null
const cronGate = feature('AGENT_TRIGGERS')
? (require('../tools/ScheduleCronTool/prompt.js') as typeof import('../tools/ScheduleCronTool/prompt.js'))
: null
const cronSchedulerModule = require('../utils/cronScheduler.js') as typeof import('../utils/cronScheduler.js')
const cronJitterConfigModule = require('../utils/cronJitterConfig.js') as typeof import('../utils/cronJitterConfig.js')
const cronGate = require('../tools/ScheduleCronTool/prompt.js') as typeof import('../tools/ScheduleCronTool/prompt.js')
const extractMemoriesModule = feature('EXTRACT_MEMORIES')
? (require('../services/extractMemories/extractMemories.js') as typeof import('../services/extractMemories/extractMemories.js'))
: null
@ -2706,9 +2700,7 @@ function runHeadlessStreaming(
let cronScheduler: import('../utils/cronScheduler.js').CronScheduler | null =
null
if (
feature('AGENT_TRIGGERS') &&
cronSchedulerModule &&
cronGate?.isKairosCronEnabled()
cronGate.isKairosCronEnabled()
) {
cronScheduler = cronSchedulerModule.createCronScheduler({
onFire: prompt => {

View File

@ -82,9 +82,7 @@ export const IN_PROCESS_TEAMMATE_ALLOWED_TOOLS = new Set([
SEND_MESSAGE_TOOL_NAME,
// Teammate-created crons are tagged with the creating agentId and routed to
// that teammate's pendingUserMessages queue (see useScheduledTasks.ts).
...(feature('AGENT_TRIGGERS')
? [CRON_CREATE_TOOL_NAME, CRON_DELETE_TOOL_NAME, CRON_LIST_TOOL_NAME]
: []),
CRON_CREATE_TOOL_NAME, CRON_DELETE_TOOL_NAME, CRON_LIST_TOOL_NAME,
])
/*

View File

@ -197,7 +197,7 @@ const PROACTIVE_NO_OP_SUBSCRIBE = (_cb: () => void) => () => {};
const PROACTIVE_FALSE = () => false;
const SUGGEST_BG_PR_NOOP = (_p: string, _n: string): boolean => false;
const useProactive = feature('PROACTIVE') || feature('KAIROS') ? require('../proactive/useProactive.js').useProactive : null;
const useScheduledTasks = feature('AGENT_TRIGGERS') ? require('../hooks/useScheduledTasks.js').useScheduledTasks : null;
const useScheduledTasks = require('../hooks/useScheduledTasks.js').useScheduledTasks;
/* eslint-enable @typescript-eslint/no-require-imports */
import { isAgentSwarmsEnabled } from '../utils/agentSwarmsEnabled.js';
import { useTaskListWatcher } from '../hooks/useTaskListWatcher.js';
@ -4047,16 +4047,9 @@ export function REPL({
});
// Scheduled tasks from .claude/scheduled_tasks.json (CronCreate/Delete/List)
if (feature('AGENT_TRIGGERS')) {
// Assistant mode bypasses the isLoading gate (the proactive tick →
// Sleep → tick loop would otherwise starve the scheduler).
// kairosEnabled is set once in initialState (main.tsx) and never mutated — no
// subscription needed. The tengu_kairos_cron runtime gate is checked inside
// useScheduledTasks's effect (not here) since wrapping a hook call in a dynamic
// condition would break rules-of-hooks.
{
const assistantMode = store.getState().kairosEnabled;
// biome-ignore lint/correctness/useHookAtTopLevel: feature() is a compile-time constant
useScheduledTasks!({
useScheduledTasks({
isLoading,
assistantMode,
setMessages

View File

@ -9,6 +9,7 @@ import { registerRememberSkill } from './remember.js'
import { registerSimplifySkill } from './simplify.js'
import { registerSkillifySkill } from './skillify.js'
import { registerStuckSkill } from './stuck.js'
import { registerLoopSkill } from './loop.js'
import { registerUpdateConfigSkill } from './updateConfig.js'
import { registerVerifySkill } from './verify.js'
@ -32,6 +33,7 @@ export function initBundledSkills(): void {
registerSimplifySkill()
registerBatchSkill()
registerStuckSkill()
registerLoopSkill()
if (feature('KAIROS') || feature('KAIROS_DREAM')) {
/* eslint-disable @typescript-eslint/no-require-imports */
const { registerDreamSkill } = require('./dream.js')
@ -44,15 +46,6 @@ export function initBundledSkills(): void {
/* eslint-enable @typescript-eslint/no-require-imports */
registerHunterSkill()
}
if (feature('AGENT_TRIGGERS')) {
/* eslint-disable @typescript-eslint/no-require-imports */
const { registerLoopSkill } = require('./loop.js')
/* eslint-enable @typescript-eslint/no-require-imports */
// /loop's isEnabled delegates to isKairosCronEnabled() — same lazy
// per-invocation pattern as the cron tools. Registered unconditionally;
// the skill's own isEnabled callback decides visibility.
registerLoopSkill()
}
if (feature('AGENT_TRIGGERS_REMOTE')) {
/* eslint-disable @typescript-eslint/no-require-imports */
const {

View File

@ -26,13 +26,11 @@ const SleepTool =
feature('PROACTIVE') || feature('KAIROS')
? require('./tools/SleepTool/SleepTool.js').SleepTool
: null
const cronTools = feature('AGENT_TRIGGERS')
? [
require('./tools/ScheduleCronTool/CronCreateTool.js').CronCreateTool,
require('./tools/ScheduleCronTool/CronDeleteTool.js').CronDeleteTool,
require('./tools/ScheduleCronTool/CronListTool.js').CronListTool,
]
: []
const cronTools = [
require('./tools/ScheduleCronTool/CronCreateTool.js').CronCreateTool,
require('./tools/ScheduleCronTool/CronDeleteTool.js').CronDeleteTool,
require('./tools/ScheduleCronTool/CronListTool.js').CronListTool,
]
const RemoteTriggerTool = feature('AGENT_TRIGGERS_REMOTE')
? require('./tools/RemoteTriggerTool/RemoteTriggerTool.js').RemoteTriggerTool
: null