Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
43df509
fix: honor reduced motion in the TUI
chrisnestrud Sep 24, 2026
8b2552d
test: cover core linear-mode flows
chrisnestrud Sep 24, 2026
bd5ff24
test: enforce linear transcript invariants
chrisnestrud Sep 24, 2026
81720c9
fix: clean up linear agent task lifecycles
chrisnestrud Sep 24, 2026
955c9e5
docs: describe supported linear terminal mode
chrisnestrud Sep 24, 2026
5c426c0
docs: document non-TUI input and one-shot --message contract
chrisnestrud Sep 26, 2026
e0d50ed
fix: deliver queued input and confirmations in non-TUI IOProxy
chrisnestrud Sep 26, 2026
39657f3
Centralize agent tree in its own file and exempt workflow agents from…
dwash96 Oct 29, 2026
fcfaf9a
Rename Tools: Command to Shell, ResourceManager to ManageResources, C…
dwash96 Oct 29, 2026
6cb39a9
cli-73: added more aggressive auto compaction, potential token saving…
Oct 30, 2026
0238c47
Remove overzealous compation messages
dwash96 Oct 30, 2026
1de3f00
Rewrite user-specified key bindings into Textual's specified order
dwash96 Oct 30, 2026
f9bf164
Merge pull request #727 from szmania/cli-73-aggressive-compaction
dwash96 Oct 30, 2026
5f4ffc8
Fix formatting
dwash96 Oct 30, 2026
fd99cf6
Command consolidation part 1: /skills and /mcp
dwash96 Oct 31, 2026
5972845
Command consolidation part 2: Hooks, skills, queues
dwash96 Oct 31, 2026
70d006b
Add sub command completions
dwash96 Oct 31, 2026
2fe75cd
Add command aliases for verb first commands for easy look up
dwash96 Oct 31, 2026
54e67cf
Add `persist` and sub agent `metadata` configuration options for work…
dwash96 Oct 31, 2026
f92419c
Update tests for sub commands
dwash96 Oct 31, 2026
0b8971c
Update key redaction heuristics
dwash96 Oct 31, 2026
228c0f0
Allow non-write tools to run automatically saving tool approvals for …
dwash96 Oct 31, 2026
9a956c6
Auto-save on by default
dwash96 Oct 31, 2026
445f4ca
Add an /open panel triggerable with alt+o to see the status of backgr…
dwash96 Oct 31, 2026
2f34cbf
Fix tests
dwash96 Nov 1, 2026
c3bca4a
Address #728 by making --show-speed more aesthetic
dwash96 Nov 1, 2026
18c34bc
Merge branch 'v1.11.0' into feature/cecli-tui-reduced-motion
dwash96 Nov 1, 2026
4f31c46
Merge pull request #687 from chrisnestrud/feature/cecli-tui-reduced-m…
dwash96 Nov 1, 2026
a34cc02
Merge branch 'v1.11.0' into feature/cecli-100-4-linear-docs
dwash96 Nov 1, 2026
ee6af95
fix: restore queued prompt echo and refresh linear-mode tests
dwash96 Nov 1, 2026
b5d9f09
Merge branch 'v1.11.0' into docs/non-tui-input-contract
dwash96 Nov 1, 2026
1138428
Merge pull request #698 from chrisnestrud/docs/non-tui-input-contract
dwash96 Nov 1, 2026
7ca55ad
Merge branch 'v1.11.0' into fix/non-tui-queued-input
dwash96 Nov 1, 2026
192821f
Merge PR #697: deliver queued input and confirmations in non-TUI IOProxy
dwash96 Nov 1, 2026
a213a35
fix: drain non-TUI input queue without global wakeups
dwash96 Nov 1, 2026
8a36a68
Make test robust in CI/CD pipeline
dwash96 Nov 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cecli/args.py
Original file line number Diff line number Diff line change
Expand Up @@ -466,10 +466,10 @@ def get_parser(default_config_files, git_root):
group.add_argument(
"--auto-save",
action=argparse.BooleanOptionalAction,
default=False,
default=True,
help=(
"Enable/disable automatic saving of sessions as --auto-save-session-name (default:"
" False)"
" True)"
),
)
group.add_argument(
Expand Down
103 changes: 65 additions & 38 deletions cecli/coders/agent_coder.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from cecli.change_tracker import ChangeTracker
from cecli.helpers import nested, responses
from cecli.helpers.agents.service import AgentService
from cecli.helpers.agents.tree import AgentTree
from cecli.helpers.background_commands import BackgroundCommandManager
from cecli.helpers.conversation import ConversationService, MessageTag
from cecli.helpers.similarity import (
Expand Down Expand Up @@ -62,15 +63,15 @@ def __init__(self, *args, **kwargs):
self.tool_similarity_threshold = 0.95
self.max_tool_vector_history = 20
self.read_tools = {
"command",
"shell",
"explorecode",
"readfile",
"grep",
"updatetodolist",
"searchfacts",
}
self.write_tools = {
"command",
"shell",
"editfile",
"undochange",
"replacefacts",
Expand Down Expand Up @@ -233,7 +234,7 @@ def _get_agent_config(self, config=None):
config,
["tools_excludelist", "tools_blacklist"],
[
"create",
"manageextensions",
"gitbranch",
"gitdiff",
"gitlog",
Expand Down Expand Up @@ -782,7 +783,7 @@ def get_context_summary(self):
result += f" ({percentage:.1f}% of limit)"
if percentage > 80:
result += "\n\n⚠ **Context is getting full!**\n"
result += "- Remove non-essential files, skills and tool servers via the `ResourceManager` tool.\n"
result += "- Remove non-essential files, skills and tool servers via the `ManageResources` tool.\n"
result += "- Keep only essential files, skills, and MCP servers in context for best performance"
result += "\n</context>"
if not hasattr(self, "context_blocks_cache"):
Expand Down Expand Up @@ -821,7 +822,10 @@ def get_environment_info(self):
primary_uuid = str(service.coder.uuid)
self_name = service.get_agent_name(self) or "primary"
result += f"- Agent: {self_name} ({self_uuid}) [self]\n"
result += f"- Primary agent: primary ({primary_uuid})\n"
# Workflow agents run in an isolated tree and must not see the
# primary agent (nor it them).
if AgentTree.is_visible(self_uuid, primary_uuid):
result += f"- Primary agent: primary ({primary_uuid})\n"
if self.repo:
try:
rel_repo_dir = self.repo.get_rel_repo_dir()
Expand Down Expand Up @@ -1515,7 +1519,7 @@ async def check_for_file_mentions(self, content):

Override parent's method to disable implicit file mention handling in agent mode.
Files should only be added via explicit tool commands
(`ResourceManager`).
(`ManageResources`).
"""
pass

Expand Down Expand Up @@ -1812,6 +1816,11 @@ def get_sub_agents_context(self):
return None
try:
registry = AgentService.get_registry()
# Workflow agents live in isolated trees; the primary must not see
# them as delegatable sub-agent types.
registry = {
name: config for name, config in registry.items() if not name.startswith("wf:")
}
if not registry:
return None

Expand Down Expand Up @@ -1842,9 +1851,11 @@ def get_sub_agent_states(self):
independent sub-agents. The independent ones are those reachable via
the ``Broadcast`` tool.

Finished/errored sub-agents are excluded. Returns None if there are no
active sub-agents, if enhanced context is disabled, or if the caller is
a sub-agent without nested delegation enabled.
Finished/errored sub-agents are excluded. Agents inside a workflow tree
see every active agent in that tree rather than only their own children.
Returns None if there are no active sub-agents, if enhanced context is
disabled, or if the caller is a sub-agent without nested delegation
enabled.

The primary agent and calling agent's own identity are deliberately not
included here — they live in ``get_environment_info()`` (a static block)
Expand All @@ -1868,34 +1879,50 @@ def get_sub_agent_states(self):
from cecli.helpers.agents.service import SubAgentStatus

originator_uuid = str(self.uuid)

# Dependent children are the coder's direct children.
children = service.get_children(self)
dependent_children = [
info
for info in children
if not info.independent
and not info.detached
and info.status not in (SubAgentStatus.FINISHED, SubAgentStatus.ERROR)
]

# Independent agents aren't all direct children, so iterate over
# every active sub-agent reachable via the Broadcast tool and dedupe
# against the dependent children already captured above.
dependent_uuids = {info.coder.uuid for info in dependent_children}
independent_agents = []
seen = set()
for info in service.sub_agents.values():
if (
info.independent
visible_uuids = AgentTree.get_visible_uuids(originator_uuid)
workflow_root = AgentTree.get_workflow_root(originator_uuid)

if workflow_root is not None:
# Inside a workflow tree, every active agent in that tree is
# visible: the workflow root, its children and their descendants.
dependent_children = [
info
for info in service.sub_agents.values()
if str(info.coder.uuid) != originator_uuid
and str(info.coder.uuid) in visible_uuids
and not info.detached
and str(info.coder.uuid) != originator_uuid
and info.status not in (SubAgentStatus.ERROR,)
and info.coder.uuid not in dependent_uuids
and info.coder.uuid not in seen
):
seen.add(info.coder.uuid)
independent_agents.append(info)
and info.status not in (SubAgentStatus.FINISHED, SubAgentStatus.ERROR)
]
independent_agents = []
else:
# Outside a workflow tree, dependent agents are the coder's
# direct children; independent agents are the others reachable
# through Broadcast in the same visibility domain.
children = service.get_children(self)
dependent_children = [
info
for info in children
if not info.independent
and not info.detached
and str(info.coder.uuid) in visible_uuids
and info.status not in (SubAgentStatus.FINISHED, SubAgentStatus.ERROR)
]

dependent_uuids = {info.coder.uuid for info in dependent_children}
independent_agents = []
seen = set()
for info in service.sub_agents.values():
if (
info.independent
and not info.detached
and str(info.coder.uuid) != originator_uuid
and str(info.coder.uuid) in visible_uuids
and info.status not in (SubAgentStatus.ERROR,)
and info.coder.uuid not in dependent_uuids
and info.coder.uuid not in seen
):
seen.add(info.coder.uuid)
independent_agents.append(info)

if not dependent_children and not independent_agents:
return None
Expand Down Expand Up @@ -1937,7 +1964,7 @@ def get_background_command_output(self):

Emits a roster of active commands (keeping command keys in context)
plus any new incremental output. Output that has been paged to disk is
advertised by command key and read on demand through ``ResourceManager``
advertised by command key and read on demand through ``ManageResources``
paging.
"""
command_info = BackgroundCommandManager.list_background_commands()
Expand Down Expand Up @@ -1970,7 +1997,7 @@ def get_background_command_output(self):
output += f"\nNew output ({command_key}):\n{cmd_output}\n"

if paged_keys:
output += "\nPaged output is available via `ResourceManager` (up to 3 pages):\n"
output += "\nPaged output is available via `ManageResources` (up to 3 pages):\n"
for command_key in paged_keys:
output += f'{{"paging": [{{"target": "{command_key}", "page": 1}}]}}\n'

Expand Down
Loading
Loading