Previously CAI_SUPPORT_INTERVAL only checked at the end of each outer
while-loop iteration (once per user input). In agentic sessions the agent
makes many successive tool calls inside a single Runner.run invocation,
so the check would only fire after the runner returned — too late, or
never if the runner was still running.
Fix:
- Add ContextCompactedError exception class.
- Add a count-based trigger at the top of _auto_compact_if_needed (which
fires on EVERY LLM API call, inside both get_response and stream_response).
When assistant-message count >= CAI_SUPPORT_INTERVAL:
1. Set the compact model to CAI_SUPPORT_MODEL temporarily.
2. Summarise via _ai_summarize_history (awaited in-situ, no asyncio.run).
3. Store summary in COMPACTED_SUMMARIES so get_system_prompt picks it
up on the next turn without needing agent reload.
4. Clear message_history + reset CAI_CONTEXT_USAGE.
5. Raise ContextCompactedError to abort the current runner invocation.
- cli.py catches ContextCompactedError in both streaming and non-streaming
runner call sites:
- Sets _post_compact_input = _last_user_input so the task is replayed.
- Re-syncs the local agent reference via AGENT_MANAGER.
- Continues the outer while-loop, restarting with a clean context window.
The existing outer-loop CLI check (counting assistant messages in history
after the runner finishes) is kept as a belt-and-suspenders fallback.
Both get_response (token counting) and _fetch_response (actual API call)
were prepending self.message_history to every request. But cli.py already
passes the full conversation history via history_context as conversation_input
to Runner.run, which threads it through as original_input to these methods.
Result: every historical message was sent TWICE in every API call, doubling
the effective context size. After auto-compact cleared message_history, the
duplication between runner-accumulated generated_items and message_history
rebuilt the doubled context within a single Runner.run invocation (after
just 3-4 tool calls), explaining why n_tokens never dropped post-compact.
Fix: remove the prepend loops. The runner's input parameter already contains
the full conversation (original_input + generated_items), so converted_messages
is built from input alone. message_history continues to serve its role as
cross-turn persistence (populated via add_to_message_history, consumed by
cli.py as history_context for the next Runner.run call).
Expected effect: halved token counts in normal operation; post-compact first
call starts at ~system_prompt + 1 user message and grows linearly with tool
calls rather than doubling.
CAI_SUPPORT_INTERVAL previously counted outer while-loop iterations
(one per user input). In agentic/continue mode the agent makes many
tool-call rounds per single user input, so the interval never fired
unless the user typed N separate messages.
Fix: count assistant messages in message_history as a proxy for LLM
API calls. This fires after every N responses from the main model
regardless of how many came from a single outer iteration.
- Startup banner updated: 'every N LLM responses' instead of 'turns'
- Countdown shows [{current}/{threshold}] response counts
- Fire condition: llm_call_count >= support_interval (fires as soon
as threshold is reached; resets naturally when history is cleared
after compact)
- Print startup banner confirming CAI_SUPPORT_MODEL + CAI_SUPPORT_INTERVAL
are loaded so users can verify env vars are picked up.
- Show a per-turn countdown (dim cyan) so it is visible the interval is
counting correctly toward the next compact.
- Remove the CAI_DEBUG=2 gate on error output — auto-compact errors are
now always printed so silent failures can no longer mask a broken
support model endpoint or compaction issue.
After auto-compact fired the main run loop fell back to get_user_input()
and waited for the human, so the agent stopped working mid-task.
Root cause: no mechanism existed to replay the current task into the next
iteration after message_history was cleared.
Fix:
- Add _post_compact_input (str | None) variable initialised to None at
session start.
- Capture _last_user_input from user_input just before turn_count += 1.
- After a successful auto-compact set _post_compact_input to
_last_user_input (or 'Continue the current task.' if it was blank).
- At the top of the input-gathering block, consume _post_compact_input
before calling get_user_input() so the agent immediately re-runs with
its previous task prompt and the fresh compacted context.
Problem
-------
CAI_SUPPORT_MODEL and CAI_SUPPORT_INTERVAL were documented environment
variables that had no runtime implementation. The support/reasoner agent
was constructed using CAI_SUPPORT_MODEL but was never invoked automatically.
CAI_SUPPORT_INTERVAL existed only in docs/config tables with no scheduler
reading it. As a result, users with a limited context window (e.g. 32k on a
local llama.cpp setup) had no way to automatically keep the main model's
message_history from overflowing during a long pentest.
Solution
--------
Added an auto-compact scheduler block immediately after turn_count += 1 in
the main single-agent run loop (run_cai_cli).
When both CAI_SUPPORT_MODEL and CAI_SUPPORT_INTERVAL are set the scheduler:
1. Fires every CAI_SUPPORT_INTERVAL turns (modulo check).
2. Calls COMPACT_COMMAND_INSTANCE._perform_compaction(model_override=
CAI_SUPPORT_MODEL) which:
- Sends the full message_history to the support model for summarisation.
- Clears message_history entirely (hard context reset).
- Saves the summary to /memory as a .md file.
- Stores the summary in COMPACTED_SUMMARIES under the agent name.
3. Re-syncs the local agent variable from AGENT_MANAGER.get_active_agent()
so the run loop continues with the freshly reloaded agent instance whose
system prompt already contains the injected summary (the system prompt
template calls get_compacted_summary() dynamically on every turn so no
extra wiring was needed).
4. Prints a visible yellow/green indicator so users can see when compaction
fires and confirm the context window has been reset.
5. Silently swallows errors (only logs when CAI_DEBUG=2) so a failing support
model never crashes the main session.
Usage
-----
CAI_SUPPORT_MODEL="openai/support" # lighter model on litellm proxy
CAI_SUPPORT_INTERVAL=4 # compact every 4 turns
* Block dangerous flags in find_file function
Added a set of dangerous flags to prevent RCE and file manipulation in the find_file function.
* Fix typo in error message for dangerous flags
* Fix typo in README.md for 'Agents'
Correcting typo and adjusting diagram
* Update banner title from Alias0 to Alias1
* Fix formatting issues in README diagram
This was a formating missmatch that now is fixed
---------
Co-authored-by: UnaiAlias <52742669+UnaiAlias@users.noreply.github.com>
* feat: Add Ollama Cloud integration with ollama_cloud/ prefix
- Added support for Ollama Cloud models via AsyncOpenAI
- Models use ollama_cloud/ prefix (e.g., ollama_cloud/gpt-oss:120b)
- Reads OLLAMA_API_KEY and OLLAMA_API_BASE for cloud authentication
- Added predefined Ollama Cloud models to /model-show
- Filtered obsolete ollama/*-cloud models from LiteLLM database
- Updated authentication headers in completer, banner, and toolbar
- Added concise English documentation in docs/providers/
- Adapted to new global model cache architecture from #371
Modified files:
- src/cai/sdk/agents/models/openai_chatcompletions.py
- src/cai/repl/commands/model.py (adapted to global cache)
- src/cai/util.py
- src/cai/repl/commands/completer.py
- src/cai/repl/ui/banner.py
- src/cai/repl/ui/toolbar.py
- docs/providers/ollama.md
- docs/providers/ollama_cloud.md
All existing functionality preserved (backward compatible).
* fix: Add missing Ollama Cloud models and get_ollama_auth_headers
- Added Ollama Cloud models to get_predefined_model_categories()
- Added get_ollama_auth_headers() function to util.py
- Added Ollama Cloud to category_to_provider mapping
- Imported get_ollama_auth_headers in model.py
This fixes the issue where predefined models weren't showing in /model-show.
* fix: Display predefined models first in /model-show
- Added loop to display predefined models (Alias, Claude, OpenAI, DeepSeek, Ollama Cloud) before LiteLLM models
- Models #1-14 now correctly show predefined models
- LiteLLM models start from #15+ as expected
- Added get_ollama_auth_headers() function in util.py for Ollama Cloud auth
- Fixed model numbering to be consistent with global cache
This resolves the issue where predefined models were skipped and only LiteLLM models appeared starting from #15.
* fix: Restore correct import of cai.caibench instead of pentestperf
During rebase, the import was incorrectly changed from 'import cai.caibench as ptt'
to 'import pentestperf as ptt'. This commit restores the correct import.
The original code uses cai.caibench, not an external pentestperf module.
fix: consistent model numbering between /model and /model-show for Ollama
When using OLLAMA_API_BASE, model selection by number was incorrect.
/model-show displayed Ollama models with certain numbers, but /model <number>
selected different models from LiteLLM instead.
This happened because both commands used separate caches with inconsistent
numbering. Now they share a global cache that loads models in consistent order:
predefined → LiteLLM → Ollama.
Fixes model number mismatch when selecting Ollama models by number.
Add idle detection to prevent CAI from freezing when executing
interactive tools (cat, python -i, gdb, radare2) that wait for
user input indefinitely.
- Add non-blocking I/O with asyncio.wait_for() timeouts
- Add 10s idle timeout to terminate idle processes
- Apply to streaming and non-streaming execution paths
- Add select.select() to ShellSession._read_output()
Resolves blocking I/O issue where interactive tools would hang
CAI for the full timeout period (100s).
This release introduces significant enhancements to CAI's web security testing capabilities,
improves MCP server support, and substantially expands documentation coverage.
New Features
- Add web_pentester_agent for professional web application security testing (#353)
- Add HTTP header support to /mcp load command for SSE servers (#350)
- Implement custom tool example for agent extensibility (#347)
- Support for reasoning tokens in response processing (#318)
- Docker container based on Kali Linux for enhanced tooling (#308)
Documentation
- Add comprehensive CAI PRO documentation and CLI section (#333)
- Add four new case studies: Unitree G1, Dragos CTF, HackerOne, PortSwigger (#345)
- Add environment variables reference guide (#330)
- Add installation guides for CAI Pro v0.5 and v0.6 (#312)
- Document parallel agents functionality (#337)
- Document --continue mode for session resumption
- Document open router selection capabilities
- Add CAI_TOOL_TIMEOUT to environment docs
- Add Azure OpenAI provider configuration (#273)
Bug fixes
- Fix missing import sys error (#335)
- Fix TUI documentation issues and CAI-Pro links (#328)
- Various stability improvements and error handling enhancements
Adds --header/-H flag support to `/mcp load` for authenticated MCP servers
like Hack The Box. Handles long Bearer tokens that wrap across terminal lines.
Changes:
- Added --header/-H flag parsing in mcp.py handle_load() method
- Parse "Key: Value" format headers and strip quotes
- Pass headers to MCPServerSseParams
- Fix CLI command parsing to handle newlines from terminal wrapping
- Use shlex.split() for proper quote handling in pasted commands
Example usage:
/mcp load https://mcp.ai.hackthebox.com/v1/ctf/sse htb --header "Authorization: Bearer TOKEN"
Tested with HTB MCP server - successfully connects with 13 tools.
Developed by Claude Sonnet 4 with guidance from @AgeOfAlgorithms
Co-authored-by: AgeOfAlgorithms <AgeOfAlgorithms@pm.me>
* docs: add three new case studies to README
- Add Unitree G1 Humanoid Robot security analysis case study
- Add Dragos OT CTF 2025 Top-10 achievement case study
- Add HackerOne bug bounty platform case study
- Include case study images in docs/assets/images/
- Position new studies at the top as most recent
- Maintain consistent formatting with existing case studies
* docs: update case study descriptions with official text from web pages
- Update Unitree G1 description with official text
- Update Dragos CTF description with official text
- Update HackerOne description with official text
- Ensure consistency with published case studies
* docs: add PortSwigger case study to maintain 2-column structure
- Add PortSwigger Web Security Academy case study
- Position alongside MQTT broker in last row
- Maintain consistent 2-column layout throughout
- Include case study image in docs/assets/images/
* docs: update HackerOne case study title
- Remove 'and alias1' reference from HackerOne title
- Keep consistent naming with other case studies
* all agent are working, and docuemnted + benchmkar fixes
* revert
* Document extension of Red Team Agent
Added an example of extending the Red Team Agent with custom instructions.
---------
Co-authored-by: Maria <maria@aliasrobotics.com>
Co-authored-by: Francesco Balassone <77972200+duel0@users.noreply.github.com>
* adapted readme and added dockerized folder for ease of use
* added brupsuite and seclists to dockerfile
* fixed env param in docker compose. OLLAMA_API_BASE does not map to OLLAMA anymore
* made host.docker.internal extra host optional as in commenting it out. i dont wanna threat a maybe edge case problem as regular issue
* removed pip upgrade Step since its already up to date from kali itslef and breaks the build..
* fixed cai install given cali python packages already present
* host.docker.internal not working in wsl docker when coming from host. window shost ip is working. so removed the part and modified doc
---------
Co-authored-by: Robert Herzog <robert.herzog@hypnolords.com>