Skip to content

Commit 6a173a6

Browse files
authored
working on more terminal context (#2444)
* add automatic OSC 7 support to bash and zsh * add new wave OSC 16162 (planck length) to get up-to-date shell information into blockrtinfo. currently implemented only for zsh. bash will not support as rich of data as zsh, but we'll be able to do some. * new rtinfo will be used to provide better context for AI in the future, and to make sure AI is running safe commands. * added a small local machine description to tab context (so AI knows we're running on MacOS, Linux, or Windows)
1 parent 54cd3e5 commit 6a173a6

24 files changed

Lines changed: 814 additions & 159 deletions

File tree

Taskfile.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ tasks:
157157
- go.mod
158158
- go.sum
159159
- pkg/**/*.go
160+
- pkg/**/*.sh
160161
- cmd/**/*.go
161162
- tsunami/go.mod
162163
- tsunami/go.sum
@@ -188,6 +189,7 @@ tasks:
188189
- "cmd/server/*.go"
189190
- "pkg/**/*.go"
190191
- "pkg/**/*.json"
192+
- "pkg/**/*.sh"
191193
- tsunami/**/*.go
192194
generates:
193195
- dist/bin/wavesrv.*
@@ -215,6 +217,7 @@ tasks:
215217
- "cmd/server/*.go"
216218
- "pkg/**/*.go"
217219
- "pkg/**/*.json"
220+
- "pkg/**/*.sh"
218221
- "tsunami/**/*.go"
219222
generates:
220223
- dist/bin/wavesrv.*

aiprompts/wave-osc-16162.md

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
# Wave Terminal OSC 16162 Escape Sequences
2+
3+
Wave Terminal uses a custom OSC (Operating System Command) escape sequence numbered **16162** for shell integration. This allows the shell to communicate its state and events to the terminal.
4+
5+
## Format
6+
7+
All commands use this escape sequence format:
8+
9+
```
10+
ESC ] 16162 ; command [;<json-data>] BEL
11+
```
12+
13+
Where:
14+
- `ESC` = `\033` (escape character)
15+
- `BEL` = `\007` (bell character)
16+
- `command` = Single letter (A, C, M, D, I, or R)
17+
- `<json-data>` = Optional JSON payload (depends on command)
18+
19+
## Commands
20+
21+
### A - Prompt Start
22+
23+
Marks the beginning of a new shell prompt.
24+
25+
**Format:** `A`
26+
27+
**When:** Sent in `precmd` hook (after previous command completes, before new prompt is displayed)
28+
29+
**Purpose:** Signals to the terminal that a new prompt is being drawn. This helps Wave Terminal distinguish between prompt output and command output.
30+
31+
**Example:**
32+
```bash
33+
printf '\033]16162;A\007'
34+
```
35+
36+
---
37+
38+
### C - Command Execution
39+
40+
Sent immediately before a command is executed, optionally including the command text.
41+
42+
**Format:** `C[;<json-data>]`
43+
44+
**Data Type:**
45+
```typescript
46+
{
47+
cmd64?: string; // base64-encoded command text
48+
}
49+
```
50+
51+
**When:** Sent in `preexec` hook (after user presses Enter, before command runs)
52+
53+
**Purpose:** Notifies the terminal that a command is about to execute. The command text is base64-encoded to handle special characters safely.
54+
55+
**Example:**
56+
```bash
57+
cmd64=$(printf '%s' "ls -la" | base64)
58+
printf '\033]16162;C;{"cmd64":"%s"}\007' "$cmd64"
59+
```
60+
61+
---
62+
63+
### M - Metadata
64+
65+
Sends shell metadata information (typically only once at shell initialization).
66+
67+
**Format:** `M;<json-data>`
68+
69+
**Data Type:**
70+
```typescript
71+
{
72+
shell?: string; // Shell name (e.g., "zsh", "bash")
73+
shellversion?: string; // Version string of the shell
74+
uname?: string; // Output of "uname -smr" (e.g., "Darwin 23.0.0 arm64")
75+
}
76+
```
77+
78+
**When:** Sent during first `precmd` hook (on shell startup)
79+
80+
**Purpose:** Provides Wave Terminal with information about the shell environment and operating system.
81+
82+
**Example:**
83+
```bash
84+
uname_info=$(uname -smr 2>/dev/null)
85+
printf '\033]16162;M;{"shell":"zsh","shellversion":"5.9","uname":"%s"}\007' "$uname_info"
86+
```
87+
88+
---
89+
90+
### D - Done (Exit Status)
91+
92+
Reports the exit status of the previously executed command.
93+
94+
**Format:** `D;<json-data>`
95+
96+
**Data Type:**
97+
```typescript
98+
{
99+
exitcode?: number; // Exit status code of the previous command
100+
}
101+
```
102+
103+
**When:** Sent in `precmd` hook (after command completes)
104+
105+
**Purpose:** Communicates whether the previous command succeeded or failed, allowing Wave Terminal to display success/failure indicators.
106+
107+
**Example:**
108+
```bash
109+
# After command exits with status 0
110+
printf '\033]16162;D;{"exitcode":0}\007'
111+
112+
# After command exits with status 1
113+
printf '\033]16162;D;{"exitcode":1}\007'
114+
```
115+
116+
---
117+
118+
### I - Input Status
119+
120+
Reports the current state of the command line input buffer.
121+
122+
**Format:** `I;<json-data>`
123+
124+
**Data Type:**
125+
```typescript
126+
{
127+
inputempty?: boolean; // Whether the command line buffer is empty
128+
}
129+
```
130+
131+
**When:** Sent during ZLE (Zsh Line Editor) hooks when buffer state changes
132+
- `zle-line-init` - When line editor is initialized
133+
- `zle-line-pre-redraw` - Before line is redrawn
134+
135+
**Purpose:** Allows Wave Terminal to track the state of the command line input. Currently reports whether the buffer is empty, but may be extended to include additional input state information in the future.
136+
137+
**Example:**
138+
```bash
139+
# When buffer is empty
140+
I;{"inputempty":true}
141+
142+
# When buffer has content
143+
I;{"inputempty":false}
144+
```
145+
146+
### R - Reset Alternate Buffer
147+
148+
Resets the terminal if it's in alternate buffer mode.
149+
150+
**Format:** `R`
151+
152+
**When:** Can be sent at any time to ensure terminal is not stuck in alternate buffer mode
153+
154+
**Purpose:** If the terminal is currently displaying the alternate screen buffer, this command switches back to the normal buffer. This is useful for recovering from programs that crash without properly restoring the screen.
155+
156+
**Behavior:**
157+
- Checks if terminal is in alternate buffer mode (`terminal.buffer.active.type === "alternate"`)
158+
- If in alternate mode, sends `ESC [ ? 1049 l` to exit alternate buffer
159+
- If not in alternate mode, does nothing
160+
161+
**Example:**
162+
```bash
163+
R
164+
```
165+
166+
---
167+
168+
## Typical Command Flow
169+
170+
Here's the typical sequence during shell interaction:
171+
172+
```
173+
1. Shell starts
174+
→ M;<json> (metadata - shell info)
175+
176+
2. First prompt appears
177+
→ A (prompt start)
178+
179+
3. User types command and presses Enter
180+
→ I;{"inputempty":false} (input no longer empty - sent as user types)
181+
→ C;{"cmd64":"..."} (command about to execute)
182+
183+
4. Command runs and completes
184+
→ D;{"exitcode":<status>} (exit status)
185+
→ I;{"inputempty":true} (input empty again)
186+
→ A (next prompt start)
187+
188+
5. Repeat from step 3...
189+
```
190+
191+
## Implementation Notes
192+
193+
- Shell integration is **disabled** when running inside tmux or screen (`TMUX`, `STY` environment variables, or `tmux*`/`screen*` TERM values)
194+
- Commands are base64-encoded in the C sequence to safely handle special characters, newlines, and control characters
195+
- The I (input empty) command is only sent when the state changes (not on every keystroke)
196+
- The M (metadata) command is only sent once during the first precmd
197+
- The D (exit status) command is skipped during the first precmd (no previous command to report)
198+
199+
## Related Files
200+
201+
- [`pkg/util/shellutil/shellintegration/zsh_zshrc.sh`](pkg/util/shellutil/shellintegration/zsh_zshrc.sh) - Zsh shell integration implementation
202+
- Similar integrations exist for bash and other shells
203+
204+
## Standard OSC 7
205+
206+
Wave Terminal also uses the standard **OSC 7** sequence for reporting the current working directory:
207+
208+
**Format:** `7;file://<hostname><encoded_path>`
209+
210+
This is sent:
211+
- During first precmd (after metadata)
212+
- In the `chpwd` hook (whenever directory changes)
213+
214+
The path is URL-encoded to safely handle special characters.

cmd/server/main-server.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,11 @@ func startupActivityUpdate(firstLaunch bool) {
218218
}
219219
autoUpdateChannel := telemetry.AutoUpdateChannel()
220220
autoUpdateEnabled := telemetry.IsAutoUpdateEnabled()
221+
shellType, shellVersion, shellErr := shellutil.DetectShellTypeAndVersion()
222+
if shellErr != nil {
223+
shellType = "error"
224+
shellVersion = ""
225+
}
221226
props := telemetrydata.TEventProps{
222227
UserSet: &telemetrydata.TEventUserProps{
223228
ClientVersion: "v" + WaveVersion,
@@ -227,6 +232,8 @@ func startupActivityUpdate(firstLaunch bool) {
227232
ClientIsDev: wavebase.IsDevMode(),
228233
AutoUpdateChannel: autoUpdateChannel,
229234
AutoUpdateEnabled: autoUpdateEnabled,
235+
LocalShellType: shellType,
236+
LocalShellVersion: shellVersion,
230237
},
231238
UserSetOnce: &telemetrydata.TEventUserProps{
232239
ClientInitialVersion: "v" + WaveVersion,
@@ -401,8 +408,9 @@ func main() {
401408
go stdinReadWatch()
402409
go telemetryLoop()
403410
go updateTelemetryCountsLoop()
404-
startupActivityUpdate(firstLaunch) // must be after startConfigWatcher()
411+
go startupActivityUpdate(firstLaunch) // must be after startConfigWatcher()
405412
blocklogger.InitBlockLogger()
413+
go wavebase.GetSystemSummary() // get this cached (used in AI)
406414

407415
webListener, err := web.MakeTCPListener("web")
408416
if err != nil {

0 commit comments

Comments
 (0)