Files
Codeman/src/config/map-limits.ts
T
Codeman maintainer 84ab4ff07b fix(review): harden cron security, session lifecycle, skip policy (PR #141)
- Reject multi-line prompts end-to-end: schema refines on promptText/
  launchCommand, runtime check in resolvePrompt (prompt-file content;
  trailing newlines tolerated), matching cron-ui form validation — delivery
  is single-line only, so multi-line was silently corrupted (typed mode
  fused lines, paste mode submitted partials)
- Close the workingDir confinement bypass (arbitrary server-side file read,
  e.g. workingDir=/proc + /proc/self/environ): realpath-resolve workingDir
  before the containment check, reject '/' and blocked/pseudo-fs trees
  (/proc, /sys, /dev + the attachment-guard blocklist) at fire time AND at
  job create/update (workingDir must exist and be a directory)
- Session lifecycle: new per-job autoClosePreviousSession (default true,
  recurring schedules only; ignored for 'once') — the previous run's
  still-open session is closed via the normal cleanupSession path when the
  next run fires; UI switch added; 50-session cap math documented in
  docs/cron-guide.md §8
- skip_if_same_agent_running: count only live sessions (exclude
  stopped/error dead tabs), exclude sessions created by this job's own runs
  (fixes the fire-once-then-skip-forever self-deadlock), and a skipped
  'once' job stays armed and retries next tick instead of being consumed;
  liveness filter mirrored in cron-ui _countActiveAgents
- Wire launchCommand (was accepted+documented but dead): shell mode sends
  it via writeViaMux as the first input line after startShell readiness
  (single-line, schema-enforced); form field shown for shell agent type
- Record delivery failures: a false writeViaMux result now fails the run
  instead of recording a false 'prompt_sent'
- Cap saved jobs at MAX_CRON_JOBS (100) to bound state.json growth
- Surface field-specific schema messages (drop parseBody custom
  errorMessage on cron create/update)
- Tests: workingDir create/update validation, /proc bypass regression,
  single-line enforcement (schema+runtime+trailing-newline tolerance),
  live/own-session skip filtering, once-skip re-arm, auto-close on/off/once,
  job-count cap

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 19:25:42 +02:00

83 lines
2.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @fileoverview Centralized Map size limits for memory management.
*
* These constants define maximum sizes for Maps that track ephemeral data.
* Without limits, long-running sessions can accumulate unbounded entries
* leading to memory leaks.
*
* Memory Budget Rationale:
* - Assuming average entry size of ~1KB
* - MAX_TRACKED_AGENTS=500 × 1KB = ~500KB for agent tracking
* - Activity/results per agent × agents = bounded by these limits
* - Total Map overhead: <50MB even under heavy load
*
* @module config/map-limits
*/
// ============================================================================
// Session Tracking Limits
// ============================================================================
/**
* Maximum concurrent sessions allowed.
* Each session consumes significant resources (PTY, buffers, watchers).
*/
export const MAX_CONCURRENT_SESSIONS = 50;
// ============================================================================
// SSE Client Limits
// ============================================================================
/**
* Maximum concurrent SSE client connections.
* Each connection holds an open HTTP response and receives all broadcast events.
*/
export const MAX_SSE_CLIENTS = 100;
// ============================================================================
// Todo Item Limits (Ralph Tracker)
// ============================================================================
/**
* Maximum todo items to track per session.
*/
export const MAX_TODOS_PER_SESSION = 500;
/**
* Maximum cron-job run-history records retained across all jobs. Oldest runs
* (by startedAt) are pruned when exceeded — bounds state.json growth from
* frequently-firing or perpetually-skipped jobs.
*/
export const MAX_CRON_RUN_HISTORY = 500;
/**
* Maximum saved cron jobs. Jobs persist to state.json, so an unbounded count
* would grow it without limit; creation past the cap is rejected with 400.
*/
export const MAX_CRON_JOBS = 100;
// ============================================================================
// Pending Tool Calls Limits
// ============================================================================
// ============================================================================
// Agent Tracking Limits
// ============================================================================
/**
* Maximum agents to track across all sessions (LRU eviction when exceeded).
*/
export const MAX_TRACKED_AGENTS = 500;
/**
* Maximum pending tool calls to track per subagent.
* Entries should be cleaned up on tool_result, but this prevents leaks.
*/
export const MAX_PENDING_TOOL_CALLS = 100;
/**
* TTL for orphaned pending tool calls (5 minutes).
* If no tool_result received, entry is cleaned up.
*/
export const PENDING_TOOL_CALL_TTL_MS = 5 * 60 * 1000;