feat: add ops backend and ops panel UI (reports + triggers)#13
feat: add ops backend and ops panel UI (reports + triggers)#13huiyuanXP wants to merge 3 commits into
Conversation
Task system: - task-manager.mjs: dependency-based task orchestration across sessions - API routes: GET/POST/PATCH/DELETE /api/tasks Report system: - reports.mjs: report CRUD with HTML storage - API routes: POST /api/internal/report, GET/DELETE /api/reports Scheduler: - scheduler.mjs: interval-based recurring schedule execution - API routes: GET/PATCH/DELETE /api/schedules Workflow engine: - workflow-engine.mjs: multi-step parallel/sequential workflows - Adapted to v2 API (createSession + sendMessage) MCP server: - mcp-server.mjs: session management MCP for orchestrator - mcp-task-server.mjs: standalone task MCP for child agents - Label API routes: GET/POST/DELETE /api/session-labels, PATCH /api/sessions/:id/label Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8c9e4b4024
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| getLabels, | ||
| removeLabel, | ||
| setSessionLabel, | ||
| } from './session-labels.mjs'; |
There was a problem hiding this comment.
Remove unresolved session-labels import
router-control-routes now imports ./session-labels.mjs, but that module is not present in this commit, so Node fails module resolution before the server can start. This is a universal startup failure (not input-dependent) because the import is at top level and loaded during route module initialization.
Useful? React with 👍 / 👎.
| import { randomBytes } from 'crypto'; | ||
| import { readFileSync, writeFileSync, mkdirSync, existsSync, unlinkSync, copyFileSync, renameSync } from 'fs'; | ||
| import { dirname, join } from 'path'; | ||
| import { REPORTS_DIR, REPORTS_META_FILE } from '../lib/config.mjs'; |
There was a problem hiding this comment.
Export report config keys before loading reports module
reports.mjs imports REPORTS_DIR and REPORTS_META_FILE from lib/config.mjs, but this commit does not add those exports. In ESM this throws at link time (does not provide an export named ...), so any code path importing reports.mjs (including control routes) will crash during startup.
Useful? React with 👍 / 👎.
| @@ -0,0 +1,175 @@ | |||
| import { readFileSync, writeFileSync, existsSync, renameSync } from 'fs'; | |||
| import { randomBytes } from 'crypto'; | |||
| import { TASKS_FILE } from '../lib/config.mjs'; | |||
There was a problem hiding this comment.
Define TASKS_FILE export before importing task manager
task-manager.mjs now imports TASKS_FILE from lib/config.mjs, but this commit does not define that export. That produces an ESM link error when the module is loaded, so task routes cannot initialize and server startup fails once this import is reached.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2b6016d1aa
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (pathname === '/api/tasks' && req.method === 'POST') { | ||
| let body; | ||
| try { body = JSON.parse(await readBody(req, 16384)); } catch { | ||
| writeJson(res, 400, { error: 'Invalid JSON' }); | ||
| return true; |
There was a problem hiding this comment.
Restrict task ops endpoints to owner sessions
This route accepts any authenticated caller and does not enforce authSession.role === 'owner', so visitor sessions created from shared App links can create/update/delete global tasks. I checked the same commit’s chat/router.mjs owner-only allowlist and /api/tasks is not included there either, so the new task APIs bypass the Owner/Visitor isolation model and let visitors mutate owner-wide orchestration state.
Useful? React with 👍 / 👎.
| if (scheduleReloadMatch && req.method === 'POST') { | ||
| reloadSchedule(scheduleReloadMatch[1]); | ||
| writeJson(res, 200, { ok: true }); | ||
| return true; |
There was a problem hiding this comment.
Initialize scheduler before reporting reload success
This endpoint always returns { ok: true } even when reloadSchedule() cannot arm anything because _onTrigger is unset. In this commit, startScheduler(...) is defined but never invoked (repo search only finds its definition), so schedules added via MCP (schedule_message) are acknowledged as reloaded but never executed.
Useful? React with 👍 / 👎.
| export function initTaskManager(onTaskReady) { | ||
| _onTaskReady = onTaskReady; | ||
| loadTasks(); | ||
| console.log(`[TaskManager] Loaded ${tasks.length} task(s) from disk`); |
There was a problem hiding this comment.
Load persisted tasks at startup before task mutations
Disk hydration only happens inside initTaskManager(), but this initializer is never called anywhere in this commit. That leaves tasks empty after every restart; once a new task is created/updated, saveTasks() writes the in-memory subset back to tasks.json, which can drop previously persisted tasks and dependency links.
Useful? React with 👍 / 👎.
Summary
Scope