Restrict Codex task scheduling to CI watchers

This commit is contained in:
Eyejoker
2026-03-20 04:09:36 +09:00
parent f3283f0314
commit 767ab20d76
4 changed files with 119 additions and 108 deletions

View File

@@ -15,8 +15,8 @@ Your output is sent directly to the Discord group.
- Keep answers concise unless more detail is genuinely needed - Keep answers concise unless more detail is genuinely needed
- Give conclusions and concrete next steps, not hidden reasoning - Give conclusions and concrete next steps, not hidden reasoning
- Use code blocks for commands or code when helpful - Use code blocks for commands or code when helpful
- Do not claim you will keep watching, monitor later, report back later, or continue tracking unless you actually scheduled an EJClaw task with `watch_ci` or `schedule_task` - Do not claim you will keep watching, monitor later, report back later, or continue tracking unless you actually scheduled an EJClaw task with `watch_ci`
- If no task was scheduled, do not imply that background tracking is active. If future follow-up is needed, tell the user to ping you again or explicitly ask for scheduling - If no `watch_ci` task was scheduled, do not imply that background tracking is active. If future follow-up is needed, tell the user to ping you again or explicitly ask for scheduling
- When you do schedule background follow-up, mention that it was scheduled. Include the task ID only when it is useful for later reference - When you do schedule background follow-up, mention that it was scheduled. Include the task ID only when it is useful for later reference
## Working style ## Working style
@@ -25,4 +25,5 @@ Your output is sent directly to the Discord group.
- Modify only what is needed for the task - Modify only what is needed for the task
- Verify changes when you can instead of claiming they should work - Verify changes when you can instead of claiming they should work
- For CI/status/watch requests that require future follow-up, schedule `watch_ci` - For CI/status/watch requests that require future follow-up, schedule `watch_ci`
- Use generic `schedule_task` for reminders or other non-CI recurring work - Do not use generic recurring task registration from Codex
- If the user wants a reminder or other non-CI recurring task, tell them to ask Claude/클코 to schedule it

View File

@@ -509,6 +509,8 @@ async function runQuery(
NANOCLAW_CHAT_JID: containerInput.chatJid, NANOCLAW_CHAT_JID: containerInput.chatJid,
NANOCLAW_GROUP_FOLDER: containerInput.groupFolder, NANOCLAW_GROUP_FOLDER: containerInput.groupFolder,
NANOCLAW_IS_MAIN: containerInput.isMain ? '1' : '0', NANOCLAW_IS_MAIN: containerInput.isMain ? '1' : '0',
NANOCLAW_AGENT_TYPE:
process.env.NANOCLAW_AGENT_TYPE || 'claude-code',
}, },
}, },
...(process.env.MEMENTO_MCP_SSE_URL ...(process.env.MEMENTO_MCP_SSE_URL

View File

@@ -24,6 +24,8 @@ const TASKS_DIR = path.join(IPC_DIR, 'tasks');
const chatJid = process.env.NANOCLAW_CHAT_JID!; const chatJid = process.env.NANOCLAW_CHAT_JID!;
const groupFolder = process.env.NANOCLAW_GROUP_FOLDER!; const groupFolder = process.env.NANOCLAW_GROUP_FOLDER!;
const isMain = process.env.NANOCLAW_IS_MAIN === '1'; const isMain = process.env.NANOCLAW_IS_MAIN === '1';
const agentType = process.env.NANOCLAW_AGENT_TYPE || 'claude-code';
const allowGenericScheduling = agentType !== 'codex';
function writeIpcFile(dir: string, data: object): string { function writeIpcFile(dir: string, data: object): string {
fs.mkdirSync(dir, { recursive: true }); fs.mkdirSync(dir, { recursive: true });
@@ -67,7 +69,8 @@ server.tool(
}, },
); );
server.tool( if (allowGenericScheduling) {
server.tool(
'schedule_task', 'schedule_task',
`Schedule a recurring or one-time task. The task will run as a full agent with access to all tools. Returns the task ID for future reference. To modify an existing task, use update_task instead. `Schedule a recurring or one-time task. The task will run as a full agent with access to all tools. Returns the task ID for future reference. To modify an existing task, use update_task instead.
@@ -155,11 +158,12 @@ SCHEDULE VALUE FORMAT (all times are LOCAL timezone):
content: [{ type: 'text' as const, text: `Task ${taskId} scheduled: ${args.schedule_type} - ${args.schedule_value}` }], content: [{ type: 'text' as const, text: `Task ${taskId} scheduled: ${args.schedule_type} - ${args.schedule_value}` }],
}; };
}, },
); );
}
server.tool( server.tool(
'watch_ci', 'watch_ci',
'Schedule a background CI watcher that checks until a run or check reaches a terminal state, then sends one message and cancels itself.', 'Schedule a background CI watcher that checks until a run or check reaches a terminal state, then sends one message and cancels itself. Use this for CI, benchmark, deploy, or profiling completion tracking instead of generic recurring scheduling.',
{ {
target: z target: z
.string() .string()
@@ -336,7 +340,8 @@ server.tool(
}, },
); );
server.tool( if (allowGenericScheduling) {
server.tool(
'update_task', 'update_task',
'Update an existing scheduled task. Only provided fields are changed; omitted fields stay the same.', 'Update an existing scheduled task. Only provided fields are changed; omitted fields stay the same.',
{ {
@@ -384,7 +389,8 @@ server.tool(
return { content: [{ type: 'text' as const, text: `Task ${args.task_id} update requested.` }] }; return { content: [{ type: 'text' as const, text: `Task ${args.task_id} update requested.` }] };
}, },
); );
}
server.tool( server.tool(
'register_group', 'register_group',

View File

@@ -206,6 +206,7 @@ function prepareGroupEnvironment(
NANOCLAW_CHAT_JID: group.folder, NANOCLAW_CHAT_JID: group.folder,
NANOCLAW_GROUP_FOLDER: group.folder, NANOCLAW_GROUP_FOLDER: group.folder,
NANOCLAW_IS_MAIN: isMain ? '1' : '0', NANOCLAW_IS_MAIN: isMain ? '1' : '0',
NANOCLAW_AGENT_TYPE: agentType,
// Claude sessions directory — set CLAUDE_CONFIG_DIR so SDK uses per-group sessions // Claude sessions directory — set CLAUDE_CONFIG_DIR so SDK uses per-group sessions
CLAUDE_CONFIG_DIR: groupSessionsDir, CLAUDE_CONFIG_DIR: groupSessionsDir,
}; };
@@ -314,6 +315,7 @@ NANOCLAW_IPC_DIR = ${JSON.stringify(env.NANOCLAW_IPC_DIR)}
NANOCLAW_CHAT_JID = ${JSON.stringify(group.folder)} NANOCLAW_CHAT_JID = ${JSON.stringify(group.folder)}
NANOCLAW_GROUP_FOLDER = ${JSON.stringify(group.folder)} NANOCLAW_GROUP_FOLDER = ${JSON.stringify(group.folder)}
NANOCLAW_IS_MAIN = ${JSON.stringify(isMain ? '1' : '0')} NANOCLAW_IS_MAIN = ${JSON.stringify(isMain ? '1' : '0')}
NANOCLAW_AGENT_TYPE = ${JSON.stringify(env.NANOCLAW_AGENT_TYPE)}
`; `;
// Inject memento-mcp if MEMENTO_MCP_SSE_URL is set // Inject memento-mcp if MEMENTO_MCP_SSE_URL is set
const mementoSseUrl = const mementoSseUrl =