hop2 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +33 -0
- package/INTEGRATION.md +77 -85
- package/MULTI-AGENT-CHECKLIST.md +37 -0
- package/README-MCP.md +232 -0
- package/README.md +209 -148
- package/demo/30s-product-demo.md +98 -0
- package/demo/README.md +106 -0
- package/demo/director.mjs +236 -0
- package/demo/drive-hop-terminal.mjs +70 -0
- package/demo/hop-demo-lib.mjs +525 -0
- package/demo/record-hop-view.mjs +26 -0
- package/demo/static-preview-server.mjs +45 -0
- package/demo/stitch-demo-video.mjs +128 -0
- package/hay/CHANGELOG.md +6 -0
- package/hay/DEV_NOTES.md +25 -0
- package/hay/README.md +136 -198
- package/hay/apps/cli/src/index.ts +321 -67
- package/hay/apps/server/src/index.ts +4 -3
- package/hay/apps/server/src/lib.ts +5 -4
- package/hay/apps/server/src/pty.ts +20 -7
- package/hay/apps/server/src/rooms.ts +226 -12
- package/hay/apps/server/test/rooms.test.ts +82 -3
- package/hay/apps/web/src/App.tsx +487 -112
- package/hay/apps/web/src/components/MobileKeyboard.tsx +43 -2
- package/hay/apps/web/src/styles.css +259 -29
- package/hay/package-lock.json +4 -4
- package/hay/packages/shared/src/protocol.ts +8 -0
- package/hay-web/assets/index-BmWjq_Nh.css +32 -0
- package/hay-web/assets/index-D9aOC5Zt.js +63 -0
- package/hay-web/assets/{index-FDfdolCs.js.map → index-D9aOC5Zt.js.map} +1 -1
- package/hay-web/index.html +2 -2
- package/hop +6801 -1714
- package/lib/naming-themes.js +194 -0
- package/lib/terminal-access.js +17 -0
- package/mcp/hop-mcp.js +4730 -0
- package/package.json +6 -3
- package/scripts/hay-host.js +189 -0
- package/sessions.html +378 -26
- package/setup-mcp.js +443 -0
- package/tests/hop-mcp.integration.test.cjs +3014 -0
- package/tests/terminal-access.unit.test.cjs +21 -0
- package/tests/terminal-api.integration.test.cjs +298 -0
- package/.hop-tmux.conf +0 -18
- package/hay-web/assets/index-CTTzApRp.css +0 -32
- package/hay-web/assets/index-FDfdolCs.js +0 -60
- package/tunnel-shell.js +0 -254
package/AGENTS.md
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# AGENTS.md (hop2)
|
|
2
|
+
|
|
3
|
+
Guidance for agents working on hop2.
|
|
4
|
+
|
|
5
|
+
## Project shape
|
|
6
|
+
- `hop` is the main Node.js CLI/server entry point (bin target).
|
|
7
|
+
- `sessions.html` is the built-in session picker UI.
|
|
8
|
+
- `hay/` contains the terminal sharing stack (server/cli/web).
|
|
9
|
+
- `hay-web/` is the built web client output served by `hop`.
|
|
10
|
+
|
|
11
|
+
## Local state & config
|
|
12
|
+
- Default config dir is `~/.hop2` (override via `HOP_HOME`).
|
|
13
|
+
- State files here should remain private (permissions matter).
|
|
14
|
+
- Be careful with migrations: preserve backward compatibility where possible.
|
|
15
|
+
|
|
16
|
+
## Change discipline
|
|
17
|
+
- Keep changes focused and consistent with existing patterns.
|
|
18
|
+
- Avoid unrelated refactors; minimize surface area.
|
|
19
|
+
- Add concise comments only for non-obvious logic.
|
|
20
|
+
- Update docs when user-visible behavior changes.
|
|
21
|
+
|
|
22
|
+
## Build & test
|
|
23
|
+
- Build web assets via `npm run build` (builds `hay` then syncs to `hay-web`).
|
|
24
|
+
- Basic sanity check: `npm test` (runs `node --check hop`).
|
|
25
|
+
- If you don’t run tests, say so and suggest likely commands.
|
|
26
|
+
|
|
27
|
+
## UI work
|
|
28
|
+
- Preserve existing visual language unless a redesign is intended.
|
|
29
|
+
- Ensure layouts remain usable on desktop and mobile.
|
|
30
|
+
|
|
31
|
+
## Server/CLI work
|
|
32
|
+
- Prefer clear errors and non-zero exit codes on failures.
|
|
33
|
+
- Keep security-sensitive behavior conservative and explicit.
|
package/INTEGRATION.md
CHANGED
|
@@ -1,92 +1,84 @@
|
|
|
1
|
-
# Hop +
|
|
1
|
+
# Hop + Hay Architecture
|
|
2
2
|
|
|
3
|
-
This
|
|
3
|
+
This document describes the current Hop terminal architecture.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
The historical `ttyd`/`tmux` backend has been removed from the active runtime.
|
|
6
|
+
Hop now uses Hay, a local terminal-sharing stack built on WebSocket plus
|
|
7
|
+
`node-pty`, with browser, CLI, and MCP clients all operating on the same
|
|
8
|
+
session model.
|
|
6
9
|
|
|
7
|
-
|
|
8
|
-
- **Built-in presence** - See who's connected, typing indicators
|
|
9
|
-
- **Control modes** - Collaborative or locked single-controller
|
|
10
|
-
- **No injection hacks** - Direct control over web UI
|
|
11
|
-
- **Mobile-ready** - Responsive design with iOS-style keyboard built-in
|
|
12
|
-
- **CLI client** - Connect from real terminals too
|
|
10
|
+
## Current Stack
|
|
13
11
|
|
|
14
|
-
## Architecture Change
|
|
15
|
-
|
|
16
|
-
### Before (ttyd)
|
|
17
12
|
```
|
|
18
|
-
Browser
|
|
19
|
-
|
|
20
|
-
|
|
13
|
+
Browser / Hay CLI / Hop MCP
|
|
14
|
+
|
|
|
15
|
+
v
|
|
16
|
+
Hop daemon
|
|
17
|
+
|
|
|
18
|
+
v
|
|
19
|
+
local hay-host process
|
|
20
|
+
|
|
|
21
|
+
v
|
|
22
|
+
Hay room manager
|
|
23
|
+
|
|
|
24
|
+
v
|
|
25
|
+
node-pty
|
|
26
|
+
|
|
|
27
|
+
v
|
|
28
|
+
shell
|
|
21
29
|
```
|
|
22
30
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
-
|
|
35
|
-
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
-
|
|
39
|
-
-
|
|
40
|
-
-
|
|
41
|
-
-
|
|
42
|
-
-
|
|
43
|
-
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
-
|
|
47
|
-
-
|
|
48
|
-
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
1. Start hop: `node hop`
|
|
78
|
-
2. Open browser to tunnel URL
|
|
79
|
-
3. Verify:
|
|
80
|
-
- [ ] Login with TOTP works
|
|
81
|
-
- [ ] Terminal session works
|
|
82
|
-
- [ ] Multiple clients see same session
|
|
83
|
-
- [ ] Presence indicators show
|
|
84
|
-
- [ ] Control modes work
|
|
85
|
-
- [ ] Mobile UI works without injection
|
|
86
|
-
|
|
87
|
-
## Migration Notes
|
|
88
|
-
|
|
89
|
-
- Sessions are not persistent (by design) - shell exits when all clients disconnect
|
|
90
|
-
- tmux scrollback replaced by termshare's output buffer (200KB)
|
|
91
|
-
- iOS keyboard injection replaced by termshare's built-in mobile keyboard
|
|
92
|
-
- The old ttyd/tmux code paths are still present but no longer used; can be removed in a cleanup pass
|
|
31
|
+
Key properties:
|
|
32
|
+
|
|
33
|
+
- No `ttyd` dependency
|
|
34
|
+
- No `tmux` dependency
|
|
35
|
+
- Shared session model across browser, CLI, and MCP
|
|
36
|
+
- Session-aware audit logging and history isolation
|
|
37
|
+
- Native mobile UI and virtual keyboard support
|
|
38
|
+
- Local host process survives hop daemon restarts
|
|
39
|
+
|
|
40
|
+
## Main Components
|
|
41
|
+
|
|
42
|
+
- `hop`
|
|
43
|
+
- user-facing CLI and daemon
|
|
44
|
+
- auth, Cloudflare tunnel management, session metadata, workspace handling
|
|
45
|
+
- serves the built Hay web client from `hay-web/`
|
|
46
|
+
- `scripts/hay-host.js`
|
|
47
|
+
- persistent local host process for active Hay rooms
|
|
48
|
+
- isolates PTY/runtime ownership from the daemon lifecycle
|
|
49
|
+
- `hay/apps/server`
|
|
50
|
+
- room manager, PTY lifecycle, websocket protocol handling
|
|
51
|
+
- `hay/apps/web`
|
|
52
|
+
- browser terminal client
|
|
53
|
+
- `hay/apps/cli`
|
|
54
|
+
- local terminal client used by Hop for direct attach flows
|
|
55
|
+
- `mcp/hop-mcp.js`
|
|
56
|
+
- MCP server exposing Hop terminal/session primitives
|
|
57
|
+
|
|
58
|
+
## Session Model
|
|
59
|
+
|
|
60
|
+
- Terminal sessions are identified by stable Hop session names.
|
|
61
|
+
- MCP attaches to daemon-scoped terminal handles, but can recover across daemon
|
|
62
|
+
restart by reattaching through the stable session identity.
|
|
63
|
+
- Active PTYs live in Hay rooms managed by the host process.
|
|
64
|
+
- Browser users, local CLI attaches, and agents all talk to the same underlying
|
|
65
|
+
room runtime.
|
|
66
|
+
|
|
67
|
+
## Build Outputs
|
|
68
|
+
|
|
69
|
+
- `hay/apps/web/dist/` is the source web build output.
|
|
70
|
+
- `hay-web/` is the synced bundle served by `hop`.
|
|
71
|
+
- `npm run build` from the repo root rebuilds Hay and syncs `hay-web/`.
|
|
72
|
+
|
|
73
|
+
## Operational Notes
|
|
74
|
+
|
|
75
|
+
- Hop always uses the external Hay host runtime.
|
|
76
|
+
- `HOP_TERMINAL_BACKEND` is accepted only for compatibility and ignored.
|
|
77
|
+
- Session history and audit logging are per-session and workspace-aware.
|
|
78
|
+
- Alternate-screen/TUI applications are captured with TUI-aware audit behavior.
|
|
79
|
+
|
|
80
|
+
## Legacy Notes
|
|
81
|
+
|
|
82
|
+
The earlier `ttyd`/`tmux` approach is now only historical context.
|
|
83
|
+
If you see older references in commit history or archived notes, treat them as
|
|
84
|
+
obsolete unless the current code still uses them explicitly.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Multi-Agent Run Checklist
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
Ensure concurrent agent sessions stay isolated, time-bounded, and recoverable.
|
|
5
|
+
|
|
6
|
+
## Safety Gates
|
|
7
|
+
|
|
8
|
+
- [ ] **Isolated terminals** — assign each agent its own PTY via `hop_create_terminal`; never share a session between agents.
|
|
9
|
+
- [ ] **Destructive-command approval** — gate every `rm -rf`, force-push, or `DROP TABLE` behind explicit user confirmation, regardless of autonomy level.
|
|
10
|
+
- [ ] **Per-command timeouts** — enforce `idle_ms` and `max_wait_ms` on every `hop_wait_terminal` call; escalate or kill on deadline breach.
|
|
11
|
+
|
|
12
|
+
## Execution Loop
|
|
13
|
+
|
|
14
|
+
1. **Create session** — one `hop_create_terminal` per agent.
|
|
15
|
+
2. **Validate prompt** — use `hop_wait_terminal(until_prompt=true, start_from="latest")` before the first command.
|
|
16
|
+
3. **Preferred turn helper** — use `hopx_agent_turn` or `hopx_send_and_wait` for normal multi-turn work.
|
|
17
|
+
4. **Manual fallback** — drop to `hop_write_terminal` + `hop_wait_terminal` only when you need custom wait conditions or lower-level control.
|
|
18
|
+
5. **Assert state** — verify expected output before continuing.
|
|
19
|
+
6. **Repeat** the loop; never write into a terminal that is still busy.
|
|
20
|
+
|
|
21
|
+
Recommended defaults:
|
|
22
|
+
|
|
23
|
+
- `capture="readable_raw"`
|
|
24
|
+
- `start_from="latest"` for prompt waits, `start_from="cursor"` for deltas
|
|
25
|
+
- explicit `max_wait_ms`
|
|
26
|
+
- explicit `idle_ms` when using raw wait conditions
|
|
27
|
+
|
|
28
|
+
## Recovery
|
|
29
|
+
|
|
30
|
+
| Step | Action |
|
|
31
|
+
|------|--------|
|
|
32
|
+
| 1 | Send `ctrl_c` via `hop_send_key` or `control="interrupt"` via `hopx_agent_turn` |
|
|
33
|
+
| 2 | If still running, continue waiting or poll an async wait job instead of blind-resending |
|
|
34
|
+
| 3 | If unresponsive after deadline, `hop_close_terminal(killSession=true)` |
|
|
35
|
+
| 4 | On orchestrator crash, close all child terminals and verify there are no orphaned sessions |
|
|
36
|
+
|
|
37
|
+
**Rule:** Never skip escalation. Always tear down — never leave orphaned sessions.
|
package/README-MCP.md
ADDED
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
# Hop MCP Server
|
|
2
|
+
|
|
3
|
+
The Hop MCP server exposes Hop terminal and session APIs over MCP so agents can
|
|
4
|
+
create terminals, stream output, send input, and recover cleanly across daemon
|
|
5
|
+
restarts.
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
1. Ensure the Hop daemon is running locally.
|
|
10
|
+
|
|
11
|
+
2. Auto-configure supported MCP clients:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
hop-mcp-setup
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
If you are running from source in this repo:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm run setup-mcp
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Supported auto-detected clients:
|
|
24
|
+
- Claude Code
|
|
25
|
+
- Claude Desktop
|
|
26
|
+
- Cursor IDE
|
|
27
|
+
- Gemini CLI
|
|
28
|
+
- Codex CLI
|
|
29
|
+
- VS Code / GitHub Copilot (workspace via `.vscode/mcp.json`)
|
|
30
|
+
- Antigravity
|
|
31
|
+
|
|
32
|
+
3. Or configure your MCP client manually:
|
|
33
|
+
|
|
34
|
+
```json
|
|
35
|
+
{
|
|
36
|
+
"mcpServers": {
|
|
37
|
+
"hop": {
|
|
38
|
+
"command": "hop-mcp"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
4. Restart your MCP client.
|
|
45
|
+
|
|
46
|
+
The server auto-connects to the local Hop daemon via `~/.hop2/.tunnel-state`.
|
|
47
|
+
|
|
48
|
+
## Recommended Flow: One Agent Terminal
|
|
49
|
+
|
|
50
|
+
Recommended flow for driving one Claude/Codex/Gemini terminal safely:
|
|
51
|
+
|
|
52
|
+
1. Launch a dedicated terminal:
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
hop_create_terminal(name="subagent", cwd="/path/to/repo")
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
2. Start the agent CLI:
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
hop_write_terminal(data="claude\n")
|
|
62
|
+
# or
|
|
63
|
+
hop_write_terminal(data="codex\n")
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
3. Wait for a prompt before sending work:
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
hop_wait_terminal(until_prompt=true, start_from="latest")
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
4. Run a multi-turn loop:
|
|
73
|
+
- Preferred: `hopx_agent_turn(data="<task>", mode="auto")`
|
|
74
|
+
- Good lower-level helper: `hopx_send_and_wait(data="<task>", press_enter=true, capture="readable_raw")`
|
|
75
|
+
- Manual split only when needed:
|
|
76
|
+
- send with `hop_write_terminal(data="<task>\n")`
|
|
77
|
+
- wait with `hop_wait_terminal(capture="readable_raw")`
|
|
78
|
+
- continue via cursor deltas from `hop_read_terminal(start_from="cursor", cursor=...)`
|
|
79
|
+
|
|
80
|
+
5. Stop or clean up:
|
|
81
|
+
- interrupt with `hop_send_key(key="ctrl_c")`
|
|
82
|
+
- close with `hop_close_terminal(killSession=false)`
|
|
83
|
+
|
|
84
|
+
Safety notes:
|
|
85
|
+
- Keep one subagent per terminal (no multiplexing multiple agent CLIs in one PTY).
|
|
86
|
+
- For existing user sessions, verify `agentPermitted` (or set with `hop_set_agent_permission`) before writing input.
|
|
87
|
+
|
|
88
|
+
## Remote Hop
|
|
89
|
+
|
|
90
|
+
To connect to a remote hop instance, set env vars or use `connect_server`:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
HOP_API_URL="https://hop2.example.com" HOP_TOKEN="<token>" hop-mcp
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Or from tools:
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
connect_server(base_url="https://hop2.example.com", token="<token>")
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Optional verification:
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
connect_server(base_url="https://hop2.example.com", token="<token>", verify=true, verify_endpoint="/api/sessions")
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Tools
|
|
109
|
+
|
|
110
|
+
Core tools (`hop_`): stable atomic operations.
|
|
111
|
+
- `connect_server`
|
|
112
|
+
- `hop_server_info`
|
|
113
|
+
- `hop_list_sessions`
|
|
114
|
+
- `hop_list_terminals`
|
|
115
|
+
- `hop_create_terminal`
|
|
116
|
+
- `hop_attach_terminal`
|
|
117
|
+
- `hop_write_terminal`
|
|
118
|
+
- `hop_send_key`
|
|
119
|
+
- `hop_wait_terminal`
|
|
120
|
+
- `hop_wait_start`
|
|
121
|
+
- `hop_wait_poll`
|
|
122
|
+
- `hop_resize_terminal`
|
|
123
|
+
- `hop_read_terminal`
|
|
124
|
+
- `hop_close_terminal`
|
|
125
|
+
- `hop_set_agent_permission`
|
|
126
|
+
- `hop_list_workspaces`
|
|
127
|
+
- `hop_save_workspace`
|
|
128
|
+
- `hop_load_workspace`
|
|
129
|
+
- `hop_use_workspace`
|
|
130
|
+
|
|
131
|
+
Helper tools (`hopx_`): convenience wrappers built on top of core tools.
|
|
132
|
+
- `hopx_send_and_wait` (single-call send + wait wrapper)
|
|
133
|
+
- `hopx_agent_turn` (single-turn send + wait + mode-aware output, default `mode="auto"`)
|
|
134
|
+
|
|
135
|
+
## Resources
|
|
136
|
+
|
|
137
|
+
- `hop://sessions`
|
|
138
|
+
- `hop://terminals`
|
|
139
|
+
- `hop://workspaces`
|
|
140
|
+
|
|
141
|
+
## Notes
|
|
142
|
+
|
|
143
|
+
- Agent access is gated by `agentPermitted` for sessions created by users.
|
|
144
|
+
- `terminal_id` is an ephemeral daemon attachment handle; underlying hop `sessionName` is the stable identity.
|
|
145
|
+
- On daemon restart, terminal-scoped tools auto-reattach once using stored session identity and retry transparently when possible.
|
|
146
|
+
- `hop_read_terminal` returns a cursor for incremental polling.
|
|
147
|
+
- Default fallback terminal size is `140x40` when no explicit `cols`/`rows` are provided.
|
|
148
|
+
- `hop_create_terminal` and `hop_attach_terminal` do a short output warmup before returning, reducing first-command races.
|
|
149
|
+
- Hop isolates shell history per session and writes per-session NDJSON audit logs under `~/.hop2/workspaces/<workspace>/logs/<session>/audit.ndjson`.
|
|
150
|
+
- Audit logging automatically switches to diff-suppressed `tui_keyframe` snapshots for alternate-screen/TUI apps while still capturing all input.
|
|
151
|
+
|
|
152
|
+
### `hop_read_terminal`
|
|
153
|
+
|
|
154
|
+
- `hop_read_terminal` supports `mode: "ui"` for structured terminal snapshots:
|
|
155
|
+
- `ui.lines`: visible screen lines
|
|
156
|
+
- `ui.cursor`: cursor position
|
|
157
|
+
- `ui.window.strategy`: `cursor_centered` with auto fallback to `densest_nonempty` when needed
|
|
158
|
+
- `rawTail`: optional lossless tail of recent raw events (for transient output)
|
|
159
|
+
- Hop server now replays buffered terminal events on stream connect, so late attaches get immediate context instead of an empty first read.
|
|
160
|
+
- `hop_read_terminal` supports `mode: "readable_raw"`:
|
|
161
|
+
- preserves printable text in `events[].text`
|
|
162
|
+
- includes compact control hints in `events[].controls` (cursor, erase, alt-screen, visibility)
|
|
163
|
+
- `control_level` tunes control noise:
|
|
164
|
+
- `full`
|
|
165
|
+
- `structural` (cursor/edit/screen controls; omits CR/LF noise)
|
|
166
|
+
- `none` (default; text only)
|
|
167
|
+
- `noise_filter` tunes status/spinner suppression:
|
|
168
|
+
- `balanced` (default; suppresses CR/erase rewrite bursts, commits stable lines, strips spinner-prefix/dot animation for dedupe)
|
|
169
|
+
- in `balanced`, recent shell echo lines for agent-sent input (prompt + command) and prompt-padding artifacts are compacted
|
|
170
|
+
- `off` (raw parsed text; useful for parser debugging)
|
|
171
|
+
- in default `none`, empty output frames are dropped to reduce event noise
|
|
172
|
+
- `coalesce_ms` and `coalesce_max_chars` can merge adjacent output frames for cleaner streaming text
|
|
173
|
+
- defaults: `coalesce_ms=250`, `coalesce_max_chars=32768`
|
|
174
|
+
- parses incrementally across chunk boundaries to avoid split ANSI artifacts
|
|
175
|
+
- reconstructs common inline edits (backspace/cursor rewrites) so text is cleaner for agent parsing
|
|
176
|
+
- avoids full ANSI noise while retaining interaction structure
|
|
177
|
+
|
|
178
|
+
### `hop_wait_terminal`
|
|
179
|
+
|
|
180
|
+
- `hop_send_key` sends normalized named keys (for example `enter`, `esc`, `up`, `ctrl_c`) to improve interactive TUI control without raw escape-string handling.
|
|
181
|
+
- `hop_wait_terminal` blocks on output conditions without client polling loops:
|
|
182
|
+
- `start_from` controls where matching begins:
|
|
183
|
+
- `latest` (default): stream tail / new output only
|
|
184
|
+
- `cursor`: requires `cursor` argument
|
|
185
|
+
- `beginning`: oldest buffered event
|
|
186
|
+
- if no explicit condition is provided, it defaults to `until_agent_done=true`
|
|
187
|
+
- `async=true` starts a background wait job and returns `wait_id` immediately
|
|
188
|
+
- `until_agent_done` matches when output has started, terminal becomes quiet, and interactive cursor is visible (agent-friendly completion)
|
|
189
|
+
- regex match via `until_regex`
|
|
190
|
+
- prompt match via `until_prompt` (optional custom `prompt_regex`)
|
|
191
|
+
- quiet-period detection via `idle_ms`
|
|
192
|
+
- bounded event capture in `raw` or `readable_raw`
|
|
193
|
+
- for `capture="readable_raw"`, supports `control_level`, `noise_filter`, `coalesce_ms`, `coalesce_max_chars`, and optional `includeMetaEvents`
|
|
194
|
+
|
|
195
|
+
### Async wait helpers
|
|
196
|
+
|
|
197
|
+
- `hop_wait_start` / `hop_wait_poll` provide explicit async wait orchestration for long-running conditions:
|
|
198
|
+
- start with `hop_wait_start(...)` and poll with `hop_wait_poll(wait_id=..., wait=true)`
|
|
199
|
+
- use `consume=true` on poll to remove completed jobs
|
|
200
|
+
|
|
201
|
+
### `hopx_send_and_wait`
|
|
202
|
+
|
|
203
|
+
- `hopx_send_and_wait` combines input send + optional enter/key + wait, and defaults to cursor-based delta capture from just before send.
|
|
204
|
+
- helper defaults are token-thrifty for interactive loops: `capture_max_events=60`, `control_level=none`, `noise_filter=balanced`, `coalesce_ms=350` (unless overridden)
|
|
205
|
+
- for `capture="readable_raw"`, `text_only` defaults to `true`; this condenses wait payloads by returning joined `wait.text`, setting `wait.events=[]`, `wait.eventCount=0`, and preserving prior count in `wait.originalEventCount` (set `text_only=false` to keep full events)
|
|
206
|
+
- `hop_read_terminal` supports deterministic delta reads:
|
|
207
|
+
- `start_from`: `beginning` (default), `cursor`, or `latest`
|
|
208
|
+
- response includes `cursorStart`, `cursorEnd`, and `next_cursor`
|
|
209
|
+
|
|
210
|
+
### `hopx_agent_turn`
|
|
211
|
+
|
|
212
|
+
- `hopx_agent_turn` is a helper wrapper (not a core primitive):
|
|
213
|
+
- default `mode="auto"` chooses `ui` when terminal is in alternate-screen, otherwise `readable_raw`
|
|
214
|
+
- in `mode="auto"`, if alternate-screen starts during the same turn, it auto-promotes to `ui` for that response
|
|
215
|
+
- wait-only continuation is supported: omit `data`/`message` and use `control="wait"` to keep waiting on a terminal without sending new input
|
|
216
|
+
- `async=true` starts the turn wait in the background and returns `wait_id` immediately; continue polling or controlling that turn with `hopx_agent_turn(wait_id=..., wait=true|false, control=...)`
|
|
217
|
+
- `control="interrupt"` / `control="terminate"` send an explicit interrupt key (default `esc`); `terminate_message` can send a final follow-up after the interrupt
|
|
218
|
+
- `mode="ui"` returns a UI snapshot payload after wait
|
|
219
|
+
- for readable modes, `text_only` defaults to `true` and condenses waits the same way as `hopx_send_and_wait` (set `text_only=false` to keep full wait events)
|
|
220
|
+
- `text_only` is ignored for `mode="ui"` output snapshots
|
|
221
|
+
- `mode="ui"` defaults `includeRawTail=false` to reduce noisy tail payloads (opt in with `includeRawTail=true`)
|
|
222
|
+
- `mode="ui"` defaults wait capture to `capture_max_events=0` (override when you need readable wait-event diagnostics)
|
|
223
|
+
- when using default `until_agent_done` semantics in `mode="ui"`, hopx applies a short UI busy-guard pass to avoid returning while status lines still indicate active work (`esc to interrupt`, `working`, `waiting for process`, etc.)
|
|
224
|
+
- `mode="readable_raw"` / `mode="raw"` returns the same wait payload shape as `hopx_send_and_wait`
|
|
225
|
+
|
|
226
|
+
### Error model
|
|
227
|
+
|
|
228
|
+
- Tool calls that fail at the Hop API layer now return MCP errors (`isError: true`) with normalized fields:
|
|
229
|
+
- `ok`
|
|
230
|
+
- `status`
|
|
231
|
+
- `endpoint`
|
|
232
|
+
- `error`
|