mirror of
https://github.com/wu736139669/hapi.git
synced 2026-08-05 06:24:37 +00:00
* Add Kimi agent support via ACP protocol Add full integration for the Kimi Code CLI agent using the standard Agent Client Protocol (ACP). Includes: - kimi command and CLI registry wiring - Local launcher spawning kimi directly - Remote launcher with ACP stdio transport via AcpSdkBackend - Session management with resume support - Permission handler supporting all Kimi permission modes - Terminal UI display component - Runtime config resolving model from env and ~/.kimi/config.toml via [HAPI](https://hapi.run) Co-Authored-By: HAPI <noreply@hapi.run> * Fix Kimi ACP tool call input decoding on web Kimi streams tool arguments as JSON text inside the content array (e.g. {\"command\": \"df -h\"}) instead of rawInput/kind. The handler now extracts input from three sources in priority order: 1. rawInput (Claude/Codex path) 2. kind + title fallback (Gemini path) 3. content JSON text (Kimi path) Also handles: - rawInput: null no longer blocks the kind+title fallback - Title prefixes like \"Shell: free -h\" are stripped to extract args - Stale placeholder inputs are re-derived when the title updates - Normalized kind aliases (shell, run, read_file, write, etc.) via [HAPI](https://hapi.run) Co-Authored-By: HAPI <noreply@hapi.run> * Add kimi support to web UI * Fix some bugs * fix(kimi): dedupe repeated tool_call display in terminal UI * fix(web): keep tool block immutable so React detects input/state changes * fix(web): recognise Kimi subagent titles like 'Agent: ...' as subagent tools * fix(web): allow-for-session for ACP agents (kimi, cursor) PermissionFooter treated all non-codex sessions as Claude, sending Claude-specific acceptEdits/allowTools to ACP agents that don't support them. Hub rejected acceptEdits for kimi, and the ACP PermissionAdapter ignored allowTools. - Only show 'allow all edits' for Claude sessions - Send decision: approved_for_session for non-Claude ACP agents - Update status display to check decision field * fix(web): lookup subagent sidechains by tool-call id instead of msg id * fix(web): don't trim newest messages when loading older history fetchOlderMessages was using trimVisible(merged, 'prepend') which kept the oldest 400 messages and dropped the newest ones. This caused: 1. Latest messages to disappear when user loaded older history 2. User to see no visible change when new old messages were drowned in the 400-message window. Remove the incorrect trim so all fetched older messages are retained alongside the current window. Subsequent ingestIncomingMessages (append mode) will naturally keep the window bounded when new agent messages arrive. * fix(cli): route Kimi session resume to runKimi instead of runCursor Kimi was present in AGENT_FLAVORS but dispatchLocalResume had no branch for it, so resuming a Kimi session fell through to the Cursor launcher. via [HAPI](https://hapi.run) Co-Authored-By: HAPI <noreply@hapi.run> * fix(cli): pass selected model to Kimi ACP backend via KIMI_MODEL env createKimiBackend was ignoring opts.model and only setting KIMI_PROJECT_DIR. Use buildKimiEnv so the selected model reaches the subprocess as KIMI_MODEL. via [HAPI](https://hapi.run) Co-Authored-By: HAPI <noreply@hapi.run> * fix(web): bound message window on older loads with dedicated larger cap fetchOlderMessages was keeping all messages unbounded, causing sessionStorage bloat on repeated pagination. Reintroduce trimming with OLDER_LOAD_WINDOW_SIZE (800) so growth is capped while the newest messages are still preserved for far longer than before. via [HAPI](https://hapi.run) Co-Authored-By: HAPI <noreply@hapi.run> * fix(web): revert sidechain lookup to message id, matching tracer/grouping pipeline tracer.ts sets sidechainId to the parent message id, and reducer.ts groups by sidechainId. A prior commit changed reducerTimeline.ts to look up by tool-call id (c.id), which broke sidechain attachment. Revert to msg.id so the lookup matches the actual grouping key end-to-end. via [HAPI](https://hapi.run) Co-Authored-By: HAPI <noreply@hapi.run> * fix(cli): gate ACP title prefix stripping to known tool-kind labels extractTitleArgument stripped at the first colon unconditionally, corrupting commands/paths like curl http://localhost:3000 or Windows paths. Now it only strips when the prefix normalizes to the same tool kind as the event, verified via regex. via [HAPI](https://hapi.run) Co-Authored-By: HAPI <noreply@hapi.run> * fix(shared): include kimi in isCodexFamilyFlavor for ACP permission UI Kimi is an ACP-style agent that supports the abort decision, but isCodexFamilyFlavor excluded it, so PermissionFooter rendered the non-Codex Allow/Deny UI without the Abort button. via [HAPI](https://hapi.run) Co-Authored-By: HAPI <noreply@hapi.run> --------- Co-authored-by: HAPI <noreply@hapi.run>
hapi CLI
Run Claude Code, Codex, Cursor Agent, Gemini, or OpenCode sessions from your terminal and control them remotely through the hapi hub.
What it does
- Starts Claude Code sessions and registers them with hapi-hub.
- Starts Codex mode for OpenAI-based sessions.
- Starts Cursor Agent mode for Cursor CLI sessions.
- Starts Gemini mode via ACP (Anthropic Code Plugins).
- Starts OpenCode mode via ACP and its plugin hook system.
- Provides an MCP stdio bridge for external tools.
- Manages a background runner for long-running sessions.
- Includes diagnostics and auth helpers.
Typical flow
- Start the hub and set env vars (see ../hub/README.md).
- Set the same CLI_API_TOKEN on this machine or run
hapi auth login. - Run
hapito start a session. - Use the web app or Telegram Mini App to monitor and control.
Commands
Session commands
hapi- Start a Claude Code session (passes through Claude CLI flags). Seesrc/index.ts.hapi codex- Start Codex mode. Seesrc/codex/runCodex.ts.hapi codex resume <sessionId>- Resume existing Codex session.hapi cursor- Start Cursor Agent mode. Seesrc/cursor/runCursor.ts. Supportshapi cursor resume <chatId>,hapi cursor --continue,--mode plan|ask,--yolo,--model. Local and remote modes supported; remote usesagent -pwith stream-json.hapi gemini- Start Gemini mode via ACP. Seesrc/agent/runners/runAgentSession.ts. Note: Gemini runs in remote mode only; it waits for messages from the hub UI/Telegram.hapi opencode- Start OpenCode mode via ACP. Seesrc/opencode/runOpencode.ts. Note: OpenCode supports local and remote modes; local mode streams via OpenCode plugins.hapi resume [sessionId]- List resumable sessions for this machine or resume one locally.
Resume a remote session locally
hapi resume
hapi resume <session-id>
hapi resume lists resumable sessions for the current machine. hapi resume <session-id> hands off an active remote session and opens the same HAPI session in the local terminal.
Authentication
hapi auth status- Show authentication configuration and token source.hapi auth login- Interactively enter and save CLI_API_TOKEN.hapi auth logout- Clear saved credentials.
See src/commands/auth.ts.
Runner management
hapi runner start- Start runner as detached process.hapi runner stop- Stop runner gracefully.hapi runner status- Show runner diagnostics.hapi runner list- List active sessions managed by runner.hapi runner stop-session <sessionId>- Terminate specific session.hapi runner logs- Print path to latest runner log file.
Both start and start-sync accept repeatable --workspace-root <path> (or --workspace-root=<path>). When set:
- The web
/browsepage surfaces scoped file trees rooted at those paths. - The runner refuses
list-directoryandspawn-sessionrequests for paths outside the configured roots. ~and~/fooare expanded.
Omitting the flag keeps the legacy behavior: no scoping, no /browse feature.
See src/runner/run.ts.
Diagnostics
hapi doctor- Show full diagnostics (version, runner status, logs, processes).hapi doctor clean- Kill runaway HAPI processes.
See src/ui/doctor.ts.
Other
hapi mcp- Start MCP stdio bridge. Seesrc/codex/happyMcpStdioBridge.ts.hapi hub- Start the bundled hub (single binary workflow).hapi server- Alias forhapi hub.
Configuration
See src/configuration.ts for all options.
Required
CLI_API_TOKEN- Shared secret; must match the hub. Can be set via env or~/.hapi/settings.json(env wins).HAPI_API_URL- Hub base URL (default: http://localhost:3006).
Optional
HAPI_HOME- Config/data directory (default: ~/.hapi).HAPI_EXPERIMENTAL- Enable experimental features (true/1/yes).HAPI_EXTRA_HEADERS_JSON- JSON object of extra headers to send on CLI → hub requests, e.g.{"Cookie":"CF_Authorization=..."}.HAPI_CLAUDE_PATH- Path to a specificclaudeexecutable.HAPI_HTTP_MCP_URL- Default MCP target forhapi mcp.
Runner
HAPI_RUNNER_HEARTBEAT_INTERVAL- Heartbeat interval in ms (default: 60000).HAPI_RUNNER_HTTP_TIMEOUT- HTTP timeout for runner control in ms (default: 10000).
Worktree (set by runner)
HAPI_WORKTREE_BASE_PATH- Base repository path.HAPI_WORKTREE_BRANCH- Current branch name.HAPI_WORKTREE_NAME- Worktree name.HAPI_WORKTREE_PATH- Full worktree path.HAPI_WORKTREE_CREATED_AT- Creation timestamp (ms).
Storage
Data is stored in ~/.hapi/ (or $HAPI_HOME):
settings.json- User settings (machineId, token, onboarding flag). Seesrc/persistence.ts.runner.state.json- Runner state (pid, port, version, heartbeat).logs/- Log files.
Requirements
- Claude CLI installed and logged in (
claudeon PATH). - Cursor Agent CLI installed (
agenton PATH) forhapi cursor. Install:curl https://cursor.com/install -fsS | bash(macOS/Linux),irm 'https://cursor.com/install?win32=true' | iex(Windows). - OpenCode CLI installed (
opencodeon PATH). - Bun for building from source.
Build from source
From the repo root:
bun install
bun run build:cli
bun run build:cli:exe
For an all-in-one binary that also embeds the web app:
bun run build:single-exe
Source structure
src/api/- Bot communication (Socket.IO + REST).src/claude/- Claude Code integration.src/codex/- Codex mode integration.src/cursor/- Cursor Agent integration.src/agent/- Multi-agent support (Gemini via ACP).src/opencode/- OpenCode ACP + hook integration.src/runner/- Background service.src/commands/- CLI command handlers.src/ui/- User interface and diagnostics.src/modules/- Tool implementations (ripgrep, difftastic, git).
Related docs
../hub/README.md../web/README.md