Land staged session/MCP/chrome work + sidebar clear-J fix
This batches the in-flight [Unreleased] block from CHANGELOG.md into a single commit. Highlights: - Real MCP protocol layer (initialize / tools/list / tools/call) so vendor MCP clients can complete the handshake against the per-PID socket. Legacy direct-dispatch preserved for the harness. - New mcp_injection kinds — cli_override for codex, config_env for opencode — joining the existing env-var and config_file paths so patterm can slot into more agents without touching their real config or auth. - Ctrl+A/D and Ctrl+W/S focus navigation across tabs and intra-tab process lists, recognised in legacy / kitty CSI u / xterm modifyOtherKeys encodings. - Palette macros (sw / k / sp ) and reordering so open sessions surface above spawn-new entries. - Two-row tab bar, sidebar/tabbar/status chrome cache, viewport-wipe on agent spawn, CR-terminated orchestrator injections, and split- Enter PTY writes so paste-detecting TUIs see Enter as a key event. Also fixes the bug logged in TODO: claude's Ctrl+O tool-call expansion emits CSI 0 J, which the viewport renderer was forwarding verbatim — wiping the sidebar to the right of the cursor and leaving the chrome cache convinced nothing had changed. CSI 0 J and CSI 1 J are now translated into per-row ECH sequences clamped to the viewport, same as CSI 2 J and CSI K already were. Agent guides (CLAUDE.md / AGENTS.md) now spell out the TODO->CHANGELOG workflow so completed items land in the changelog rather than as ticked entries left behind in TODO.
This commit is contained in:
@@ -142,3 +142,37 @@ func isModifyOtherKeysCtrlK(params string) bool {
|
||||
}
|
||||
return parts[0] == "27" && parts[1] == "5" && parts[2] == "107"
|
||||
}
|
||||
|
||||
// matchCtrlChar reports whether chunk[i:] starts with Ctrl+<ch> where
|
||||
// ch is a lowercase ASCII letter. Recognises the same three encodings
|
||||
// as matchCtrlK: legacy single byte (Ctrl-A = 0x01 .. Ctrl-Z = 0x1A),
|
||||
// kitty CSI u with mods=5, and xterm modifyOtherKeys CSI 27;5;<key>~.
|
||||
// Only unmodified Ctrl (no Shift/Alt/Meta) and a press event match.
|
||||
func matchCtrlChar(chunk []byte, i int, ch byte) (matched bool, advance int) {
|
||||
if i >= len(chunk) || ch < 'a' || ch > 'z' {
|
||||
return false, 0
|
||||
}
|
||||
legacy := ch - 'a' + 1
|
||||
if chunk[i] == legacy {
|
||||
return true, 1
|
||||
}
|
||||
n := csiLen(chunk, i)
|
||||
if n == 0 {
|
||||
return false, 0
|
||||
}
|
||||
final := chunk[i+n-1]
|
||||
params := string(chunk[i+2 : i+n-1])
|
||||
switch final {
|
||||
case 'u':
|
||||
k, ok := decodeCSIu(params)
|
||||
if ok && k.key == int(ch) && k.mods == 5 && k.event == 1 {
|
||||
return true, n
|
||||
}
|
||||
case '~':
|
||||
parts := strings.Split(params, ";")
|
||||
if len(parts) == 3 && parts[0] == "27" && parts[1] == "5" && parts[2] == strconv.Itoa(int(ch)) {
|
||||
return true, n
|
||||
}
|
||||
}
|
||||
return false, 0
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user