Skip to content

feat(subagents): add TUI slash subagent runtime browser#2463

Open
JimmyDaddy wants to merge 6 commits into
esengine:main-v2from
JimmyDaddy:feat/custom-slash-commands-go
Open

feat(subagents): add TUI slash subagent runtime browser#2463
JimmyDaddy wants to merge 6 commits into
esengine:main-v2from
JimmyDaddy:feat/custom-slash-commands-go

Conversation

@JimmyDaddy

@JimmyDaddy JimmyDaddy commented May 31, 2026

Copy link
Copy Markdown
Contributor

What

Ports the custom slash command + slash-subagent workflow to the Go implementation, with runtime management UI scoped to the TUI.

Skill and command infrastructure

  • Parses disable-model-invocation: true so skills can remain slash-invokable while staying out of the model prompt index.
  • Loads agent files from .reasonix/agents/ and .claude/agents/ as runAs=subagent slash skills, including CJK file names.
  • Supports settings-defined shell slash commands, with project scope overriding global scope.
  • Keeps dispatch priority as:
Custom commands (.md) > Shell commands (settings.json) > Skills / Agents
  • Keeps the accepted behavior narrow: agent-style skills are invoked only by explicit user /name slash commands, and run through the skill subagent runner.

TUI slash subagents

  • Bare /subagents is the TUI task-center entrypoint for active and retained slash-subagent runs.
  • /subagents cancel <id-or-alias> and /subagents clear [completed|failed|canceled|all] remain controller-backed management commands.
  • Slash completion emphasizes cancel and clear, and the task-center list view supports filter mode via /.
  • Renders live slash-subagent output as an embedded transcript block in conversational order with the parent session.
  • Keeps the main composer interactive while a background slash subagent runs.
  • Supports collapsing/expanding the embedded block with Ctrl-O; terminal states auto-expand so the final answer is visible in full.
  • Preserves completed subagent results without compressing the final answer before handing them back to the parent flow.
  • Localizes /subagents picker, controller, and slash-completion copy through internal/i18n.

Desktop scope

  • Desktop keeps existing slash skills such as /explore visible.
  • Desktop omits /subagents from command autocomplete and blocks hand-entered /subagents runtime-management commands with a localized TUI-only notice.
  • Desktop does not expose ListSubagents, SubagentDetail, or CancelSubagent bindings in this slice.

Rebase Notes

  • Rebuilt the PR branch linearly on current upstream/main-v2 (4c5fec61) as 4601a9c0; no merge commit remains on the PR branch.
  • The conflict resolution preserves the maintainer-approved direction: strictly user-invoked /name subagents through the skill runner.
  • GitHub now reports the PR head as MERGEABLE (BLOCKED only by normal branch protection/checks).

Split Plan

  • internal/cli/subagents.go is currently 684 lines, below the 800-line ceiling, so this PR keeps it intact.
  • internal/control/controller.go is currently 3203 lines and remains above the repo ceiling. To keep this review focused on the accepted behavior, this PR keeps the remaining controller wiring local while already moving retained runtime/text helpers into internal/control/subagent_*.go.
  • Follow-up after functional review: move the remaining slash-subagent orchestration out of controller.go into narrower control files, leaving Submit as a small dispatch branch and controller-owned runtime helpers grouped by subagent lifecycle.

Tests

Latest rebase verification:

  • gofmt -l .
  • git diff --check
  • GOPROXY=https://proxy.golang.org,direct go test ./...
  • cd desktop && GOPROXY=https://proxy.golang.org,direct go test ./...

Ref

  • docs/SLASH_SUBAGENT_DESIGN.md

@github-actions github-actions Bot added the v2 Go rewrite (1.x) — main-v2 branch, active development label May 31, 2026
@JimmyDaddy JimmyDaddy changed the title feat(slash): custom slash commands — disableModelInvocation, shell commands, /agents [WIP]feat(slash): custom slash commands — disableModelInvocation, shell commands, /agents May 31, 2026
@JimmyDaddy JimmyDaddy force-pushed the feat/custom-slash-commands-go branch from d23b367 to f47c394 Compare May 31, 2026 16:00
@JimmyDaddy JimmyDaddy changed the title [WIP]feat(slash): custom slash commands — disableModelInvocation, shell commands, /agents feat(slash): custom slash commands — disableModelInvocation, shell commands, /agents, subagent panel May 31, 2026
@JimmyDaddy JimmyDaddy force-pushed the feat/custom-slash-commands-go branch 10 times, most recently from af628d0 to 08d1df8 Compare May 31, 2026 17:11
@JimmyDaddy JimmyDaddy changed the title feat(slash): custom slash commands — disableModelInvocation, shell commands, /agents, subagent panel [WIP]feat(subagents): custom slash commands — disableModelInvocation, shell commands, /agents, subagent panel May 31, 2026
@JimmyDaddy JimmyDaddy marked this pull request as draft May 31, 2026 17:13
@JimmyDaddy JimmyDaddy changed the title [WIP]feat(subagents): custom slash commands — disableModelInvocation, shell commands, /agents, subagent panel feat(subagents): add TUI slash subagent runtime browser Jun 1, 2026
@JimmyDaddy JimmyDaddy marked this pull request as ready for review June 1, 2026 14:45
@esengine

esengine commented Jun 1, 2026

Copy link
Copy Markdown
Owner

Took this for a thorough pass — the architecture is sound: the slash-subagent surface is strictly user-invoked, task.go's model-facing Description/Schema is unchanged (no new model-driven spawning), and disable-model-invocation keeping slash skills out of the model index is exactly right. Root Go build and the frontend typecheck are clean.

One blocker before this can land: it fails go test on Windows, in internal/control:

--- FAIL: TestSubmitRunsShellCommand
    submit_test.go:78: Submit shell command notices = [\a b"], want [a b]
--- FAIL: TestSubmitRunsShellCommandWithMultilineArgs
    submit_test.go:91: ... = [\a b"], want [a b]

The tests use printf '%s\n' with /echo "a b", which assumes POSIX sh -c semantics. On Windows shellInvocation falls back to cmd /c, where single-quotes and printf behave differently, so the output comes back mangled. Our CI only runs macOS/ubuntu, so this stays green there but breaks on Windows.

Could you:

  1. Make those tests OS-aware (skip on Windows, or use a portable command that behaves the same under both sh -c and cmd /c), and
  2. Confirm the shell-command feature itself quotes args sanely under cmd /c on Windows (or document that user shell commands are written per-platform)?

Given the size (+5957/45 files), I'll also want to walk through docs/SLASH_SUBAGENT_DESIGN.md once the Windows failures are resolved. Thanks for the design doc — it made the review much easier.

@JimmyDaddy

JimmyDaddy commented Jun 1, 2026

Copy link
Copy Markdown
Contributor Author

Took this for a thorough pass — the architecture is sound: the slash-subagent surface is strictly user-invoked, task.go's model-facing Description/Schema is unchanged (no new model-driven spawning), and disable-model-invocation keeping slash skills out of the model index is exactly right. Root Go build and the frontend typecheck are clean.

One blocker before this can land: it fails go test on Windows, in internal/control:

--- FAIL: TestSubmitRunsShellCommand
    submit_test.go:78: Submit shell command notices = [\a b"], want [a b]
--- FAIL: TestSubmitRunsShellCommandWithMultilineArgs
    submit_test.go:91: ... = [\a b"], want [a b]

The tests use printf '%s\n' with /echo "a b", which assumes POSIX sh -c semantics. On Windows shellInvocation falls back to cmd /c, where single-quotes and printf behave differently, so the output comes back mangled. Our CI only runs macOS/ubuntu, so this stays green there but breaks on Windows.

Could you:

  1. Make those tests OS-aware (skip on Windows, or use a portable command that behaves the same under both sh -c and cmd /c), and
  2. Confirm the shell-command feature itself quotes args sanely under cmd /c on Windows (or document that user shell commands are written per-platform)?

Given the size (+5957/45 files), I'll also want to walk through docs/SLASH_SUBAGENT_DESIGN.md once the Windows failures are resolved. Thanks for the design doc — it made the review much easier.

Thanks for the careful pass - I've pushed an update for the Windows blocker.

What changed:

  • Made the shell-command controller tests platform-safe. The /echo "a b" and multiline-arg cases now use the test binary as a helper command instead of POSIX-only printf '%s\n', so they exercise the same raw slash-arg path without assuming sh syntax.
  • Added lower-level internal/command coverage for quoted user args and a plain arg case.
  • Updated docs/SLASH_SUBAGENT_DESIGN.md to document the contract: settings slash commands are platform shell snippets (cmd /c on Windows, sh -c elsewhere); Reasonix preserves quoted user args but does not translate POSIX shell syntax to Windows cmd.exe syntax.
  • I also included a Windows execution-path change for settings slash commands and the hook shell spawner: on Windows it sets SysProcAttr.CmdLine for cmd /c ... so Go's argv escaping does not mangle the quoted command string before cmd.exe applies its own parsing. Could you sanity-check whether that is an acceptable direction for this codebase? If you'd rather keep the runtime path unchanged and only make the tests/docs OS-aware, I can trim that part back.

Validation run locally:

  • go test ./internal/command ./internal/control ./internal/hook
  • go test ./...
  • cd desktop && go test ./...
  • cd desktop/frontend && pnpm build
  • git diff --check

@JimmyDaddy JimmyDaddy force-pushed the feat/custom-slash-commands-go branch 4 times, most recently from 6584053 to 80b0d26 Compare June 2, 2026 15:55

JimmyDaddy commented Jun 4, 2026

Copy link
Copy Markdown
Contributor Author

@esengine latest conflicts are resolved again and the branch is back to a clean, mergeable state.

Before I keep chasing main-v2 conflicts every few days, could you help confirm whether this feature direction is still something you'd like reviewed / considered for merge?

If the overall direction looks good, I'd really appreciate a review pass and any design feedback you have, especially on the TUI-only /subagents management surface

If this is not a direction you want to take, no worries at all — a short "not aligned" reply is enough and I can close the PR instead of continuing to carry the merge burden.

Thanks.

@JimmyDaddy JimmyDaddy requested a review from SivanCola as a code owner June 4, 2026 14:54
@JimmyDaddy JimmyDaddy requested a review from esengine as a code owner June 5, 2026 08:04
@github-actions github-actions Bot added desktop Wails desktop app (desktop/**) tui Terminal UI / CLI (internal/cli, internal/control) labels Jun 6, 2026
@github-actions github-actions Bot added skills Skill system (internal/skill, internal/tool) agent Core agent loop (internal/agent, internal/control) mcp MCP servers / plugins (internal/plugin, codegraph) config Configuration & setup (internal/config) labels Jun 6, 2026
@esengine

Copy link
Copy Markdown
Owner

Status update after today's merge batch: this now conflicts in 14 files, including the heavy ones your deltas live in (controller.go, chat_tui.go, boot.go, the i18n catalogues — #3186 touched the same Submit switch). The direction still stands from the earlier pass — strictly user-invoked /name subagents through the skill runner is exactly the accepted shape — so a rebase onto current main-v2 is the only blocker; ping me when it's up and I'll do the full line review. Two notes for that round: watch internal/cli/subagents.go (684 lines, ceiling is 800), and controller.go keeps growing past the ceiling, so the PR description should carry a split plan per repo policy.

@JimmyDaddy JimmyDaddy force-pushed the feat/custom-slash-commands-go branch from 8672196 to 4601a9c Compare June 11, 2026 14:10
@JimmyDaddy

Copy link
Copy Markdown
Contributor Author

@esengine rebased/rebuilt this PR onto current main-v2 and force-pushed the linear head 4601a9c0. GitHub now reports mergeable=MERGEABLE / mergeStateStatus=BLOCKED.

I also updated the PR description with the requested split plan: internal/cli/subagents.go is still 684 lines, and controller.go is called out with a follow-up split plan per repo policy. Latest local checks passed:

  • gofmt -l .
  • git diff --check
  • GOPROXY=https://proxy.golang.org,direct go test ./...
  • cd desktop && GOPROXY=https://proxy.golang.org,direct go test ./...

Ready for the full line review when you have bandwidth. If the behavior/design direction should change further, please call that out and I can adjust.

Reasonix Test added 5 commits June 11, 2026 22:32
…h-commands-go

# Conflicts:
#	internal/boot/boot_test.go
#	internal/control/slash.go
#	internal/control/slash_test.go
#	internal/i18n/i18n.go
#	internal/i18n/messages_en.go
#	internal/i18n/messages_zh.go
…h-commands-go

# Conflicts:
#	internal/boot/boot.go
#	internal/control/controller.go
#	internal/control/controller_test.go
#	internal/jobs/jobs.go
…h-commands-go

# Conflicts:
#	internal/control/input.go
#	internal/control/slash.go
#	internal/i18n/i18n.go
#	internal/i18n/messages_en.go
#	internal/i18n/messages_zh.go
#	internal/i18n/messages_zh_tw.go
…h-commands-go

# Conflicts:
#	internal/boot/boot.go
#	internal/control/controller.go
#	internal/control/input.go
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent Core agent loop (internal/agent, internal/control) config Configuration & setup (internal/config) desktop Wails desktop app (desktop/**) mcp MCP servers / plugins (internal/plugin, codegraph) skills Skill system (internal/skill, internal/tool) tui Terminal UI / CLI (internal/cli, internal/control) v2 Go rewrite (1.x) — main-v2 branch, active development

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants