JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 49
  • Score
    100M100P100Q111498F
  • License Apache-2.0

Standalone Node.js CLI port of Harbor's Terminus2 agent — runs entirely inside the task container.

Package Exports

    This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@zhuerle/terminus-2-cli) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

    Readme

    terminus-2-cli

    Standalone Node.js port of Harbor's Terminus2 agent.

    The Python terminus-2 agent assumes a host-side loop that talks to a container-side tmux through docker exec. This package collapses that into a single in-container Node.js binary so the agent loop, tmux interaction, and LLM calls all happen on the same side of the docker boundary — matching the terminus-codeinf deployment variant, but with no Python wheel to bootstrap.

    It is intentionally small (zero npm runtime deps) and faithful to the Terminus2 behavior that matters for benchmarks: prompt template, XML/JSON parsers, tmux send + capture loop, task_complete two-step confirmation, and per-step trajectory dumps.

    What's ported

    • Prompt templates (prompts/terminus-{xml,json}-plain.txt, copied verbatim from the Python repo)
    • Both parsers (XML plain + JSON plain), with the same warnings and auto-fixes
    • tmux session driver (script(1)-allocated PTY → tmux new-session -d), send-key chunking under the ~16 KB tmux command-buffer limit
    • Main agent loop with batched send + capture, observation feedback, task_complete confirmation, parser-error re-prompt
    • Per-step trajectory in an ATIF-shaped subset, written to <logs-dir>/trajectory.json

    What's not ported (yet)

    • Context-length summarization / truncation (the Python summarization subagent flow is ~1k LOC — add only if you hit it)
    • Tokenizer-based token counting (we trust the API's usage block)
    • Asciinema recording, skill discovery, subagent metrics, linear-history splitting, output-length salvage

    Requirements

    • Node.js >= 18.17 (uses built-in fetch and node:util.parseArgs)
    • tmux and script available on PATH inside the container
    • An OpenAI-compatible chat-completions endpoint (works with vLLM, LiteLLM-proxy, SGLang, OpenAI, Anthropic via LiteLLM)

    Standalone usage

    cat > /tmp/cfg.json <<EOF
    {
      "model_name": "openai/gpt-4o",
      "api_base": "https://api.openai.com/v1",
      "api_key": "$OPENAI_API_KEY",
      "parser_name": "xml",
      "temperature": 0.2,
      "max_turns": 30
    }
    EOF
    
    echo "Print 'hello world' to the terminal and stop." > /tmp/instruction.txt
    
    mkdir -p /tmp/agent-logs
    ./bin/terminus-2-cli.mjs run \
      --config /tmp/cfg.json \
      --instruction /tmp/instruction.txt \
      --logs-dir /tmp/agent-logs \
      --session-id demo

    After the run:

    • /tmp/agent-logs/trajectory.json — per-step trajectory
    • /tmp/agent-logs/context.json — final token / cost counters
    • /tmp/agent-logs/exception.txt — only present on failure

    Config schema

    The --config JSON accepts both Python-style snake_case and JS-style camelCase keys; CLI flags override config values.

    Key Type Notes
    model_name string required (or pass --model)
    api_base string OpenAI-compatible base URL
    api_key string falls back to OPENAI_API_KEY env
    parser_name "xml" | "json" default "xml"
    max_turns number default 1,000,000 (i.e. unbounded)
    temperature number default 0.7
    top_p number optional
    max_new_tokens number optional
    reasoning_effort string OpenAI-style
    max_thinking_tokens number Anthropic-style; sent as thinking.budget_tokens
    llm_request_timeout_sec number default 600
    llm_extra_body object merged into the request body
    llm_headers object extra HTTP headers
    tmux_pane_width / tmux_pane_height number default 160×40

    Running under harbor

    src/harbor/agents/installed/terminus_2_cli.py registers this CLI as harbor's terminus-2-cli agent. The host wrapper tars up this directory, uploads it into the task container, runs install-terminus-2-cli.sh.j2 to install Node and extract the source, then invokes:

    /usr/local/bin/terminus-2-cli run \
      --config /logs/agent/terminus-2-cli-config.json \
      --instruction /logs/agent/terminus-2-cli-instruction.txt \
      --logs-dir /logs/agent \
      --session-id <trial-session-id>

    harbor-level kwargs (--agent-kwarg max_turns=30, etc.) are forwarded into the config JSON exactly the same way TerminusCli does it.

    Tests

    node --test test/

    Parser + utility tests run without external services. The loop test (test/loop.test.mjs) needs tmux on PATH; it stubs the LLM and verifies a real tmux command is dispatched and observed.