Skip to content

feat(ctl): add Terminal-Bench chat runner - #1175

Open
choskeli wants to merge 1 commit into
moltis-org:mainfrom
choskeli:feat/terminal-bench-harbor-20260728
Open

feat(ctl): add Terminal-Bench chat runner#1175
choskeli wants to merge 1 commit into
moltis-org:mainfrom
choskeli:feat/terminal-bench-harbor-20260728

Conversation

@choskeli

Copy link
Copy Markdown

Summary

  • add moltis-ctl chat and chat-history commands over authenticated gateway RPC
  • add a Harbor/Terminal-Bench installed-agent wrapper with per-task session isolation
  • document setup and include a shell contract test

Verification

  • cargo fmt --all -- --check
  • cargo test -p moltis-ctl (2 passed)
  • cargo clippy -p moltis-ctl --all-targets -- -D warnings
  • tools/terminal_bench/test_run_moltis_agent.sh
  • authenticated local-gateway smoke reached chat.send; the deployed gateway did not return before the existing 10-second ctl timeout, so model-backed benchmark completion remains environment-blocked

No credentials are included.

Copilot AI review requested due to automatic review settings July 28, 2026 20:55

MOLTIS_CTL_BIN="${MOLTIS_CTL_BIN:-moltis-ctl}"
MOLTIS_GATEWAY_URL="${MOLTIS_GATEWAY_URL:-http://host.docker.internal:13131}"
MOLTIS_SESSION_KEY="${MOLTIS_SESSION_KEY:-terminal-bench:${HARBOR_TASK_ID:-task}}"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Shared fallback session state

When two benchmark invocations omit both MOLTIS_SESSION_KEY and HARBOR_TASK_ID, this fallback gives both terminal-bench:task; the gateway then reads and appends the same persisted conversation, leaking prior instructions and results into the later task's model context.

Knowledge Base Used: CLI and Ctl: moltis binary and moltis-ctl gateway control

Comment on lines +8 to +17
pub async fn send(client: &mut CtlClient, text: &str, session_key: &str) -> anyhow::Result<Value> {
client
.call(
"chat.send",
json!({
"text": text,
"_session_key": session_key,
}),
)
.await

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Agent loop exceeds RPC deadline

When a benchmark's model and tool loop takes longer than 120 seconds, chat.send remains subject to CtlClient::call's fixed deadline, causing moltis-ctl to exit with a timeout before the documented wait-for-completion behavior finishes.

Knowledge Base Used: CLI and Ctl: moltis binary and moltis-ctl gateway control

Comment on lines +23 to +28
exec "$MOLTIS_CTL_BIN" \
--gateway-url "$MOLTIS_GATEWAY_URL" \
--api-key "$MOLTIS_API_KEY" \
chat \
--session-key "$MOLTIS_SESSION_KEY" \
"$instruction"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Hyphenated instructions become options

A non-empty task instruction beginning with a hyphen is passed without an option terminator, so clap interprets it as an option rather than the text positional and exits before sending chat.send.

Suggested change
exec "$MOLTIS_CTL_BIN" \
--gateway-url "$MOLTIS_GATEWAY_URL" \
--api-key "$MOLTIS_API_KEY" \
chat \
--session-key "$MOLTIS_SESSION_KEY" \
"$instruction"
exec "$MOLTIS_CTL_BIN" \
--gateway-url "$MOLTIS_GATEWAY_URL" \
--api-key "$MOLTIS_API_KEY" \
chat \
--session-key "$MOLTIS_SESSION_KEY" \
-- \
"$instruction"

Knowledge Base Used: CLI and Ctl: moltis binary and moltis-ctl gateway control

@greptile-apps

greptile-apps Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Adds authenticated moltis-ctl chat commands and a Terminal-Bench installed-agent wrapper.

  • Exposes chat.send and chat.history with explicit session keys.
  • Adds a Harbor wrapper that accepts task instructions from arguments, environment, or stdin.
  • Documents setup and adds a shell-level wrapper contract test.

Confidence Score: 2/5

This PR should not merge until task sessions remain isolated without HARBOR_TASK_ID and long-running chat turns can outlive the generic RPC deadline.

The default wrapper state reuses one persisted conversation across tasks, while the synchronous benchmark command can terminate before valid model and tool work completes; leading-hyphen instructions also fail before reaching the gateway.

Files Needing Attention: tools/terminal_bench/run_moltis_agent.sh, crates/ctl/src/commands/chat.rs

Important Files Changed

Filename Overview
crates/ctl/src/commands/chat.rs Adds correctly shaped chat RPC wrappers, but synchronous agent turns remain constrained by the generic fixed RPC timeout.
crates/ctl/src/main.rs Adds chat command dispatch; the text positional does not accept hyphen-prefixed task instructions.
tools/terminal_bench/run_moltis_agent.sh Adds the installed-agent wrapper, but its constant session fallback can merge task histories and its argument boundary rejects leading-hyphen instructions.
tools/terminal_bench/test_run_moltis_agent.sh Covers normal argument, stdin, session, and missing-key behavior but not isolation across missing task IDs or hyphen-prefixed instructions.
tools/terminal_bench/README.md Documents the workflow and isolation requirement, although the wrapper fallback and fixed client timeout do not uphold those guarantees.

Sequence Diagram

sequenceDiagram
  participant Harbor
  participant Wrapper as run_moltis_agent.sh
  participant Ctl as moltis-ctl
  participant Gateway
  participant Agent
  participant Sessions
  Harbor->>Wrapper: task instruction
  Wrapper->>Ctl: chat --session-key key instruction
  Ctl->>Gateway: chat.send(text, _session_key)
  Gateway->>Sessions: load session history
  Gateway->>Agent: run model/tool loop
  Agent->>Sessions: persist messages
  Agent-->>Gateway: final response
  Gateway-->>Ctl: RPC response
  Ctl-->>Harbor: JSON result
Loading

Reviews (1): Last reviewed commit: "feat(ctl): add terminal bench chat runne..." | Re-trigger Greptile

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds chat runner capabilities to moltis-ctl (authenticated gateway RPC over WebSocket) and introduces a Terminal-Bench/Harbor “installed-agent” wrapper that invokes moltis-ctl chat with per-task session separation, plus documentation and a shell contract test.

Changes:

  • Add moltis-ctl chat and moltis-ctl chat-history subcommands backed by gateway RPC (chat.send / chat.history).
  • Add tools/terminal_bench/run_moltis_agent.sh wrapper to run Moltis as a Harbor/Terminal-Bench installed agent with a session key.
  • Add wrapper documentation and a contract-style shell test for the invocation contract.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tools/terminal_bench/test_run_moltis_agent.sh Adds a shell contract test validating how the wrapper invokes moltis-ctl.
tools/terminal_bench/run_moltis_agent.sh Adds the installed-agent wrapper that builds an instruction and execs moltis-ctl chat.
tools/terminal_bench/README.md Documents how to build/configure Terminal-Bench/Harbor runner and how to smoke test it.
crates/ctl/src/main.rs Adds Chat and ChatHistory clap subcommands and routes them to new command handlers.
crates/ctl/src/commands/mod.rs Exposes the new chat subcommand module.
crates/ctl/src/commands/chat.rs Implements the chat.send / chat.history RPC calls and adds a small unit test.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +23 to +26
exec "$MOLTIS_CTL_BIN" \
--gateway-url "$MOLTIS_GATEWAY_URL" \
--api-key "$MOLTIS_API_KEY" \
chat \
Comment on lines +6 to +9
MOLTIS_CTL_BIN="${MOLTIS_CTL_BIN:-moltis-ctl}"
MOLTIS_GATEWAY_URL="${MOLTIS_GATEWAY_URL:-http://host.docker.internal:13131}"
MOLTIS_SESSION_KEY="${MOLTIS_SESSION_KEY:-terminal-bench:${HARBOR_TASK_ID:-task}}"

Comment on lines +8 to +19
pub async fn send(client: &mut CtlClient, text: &str, session_key: &str) -> anyhow::Result<Value> {
client
.call(
"chat.send",
json!({
"text": text,
"_session_key": session_key,
}),
)
.await
.map_err(Into::into)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants