Skip to content

Commit 0cd0efa

Browse files
committed
Merge branch 'main' into escape
2 parents 9236b27 + f76a3d0 commit 0cd0efa

11 files changed

Lines changed: 292 additions & 62 deletions

‎src/threecode.nim‎

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -642,10 +642,9 @@ proc main() =
642642
# Draw the initial chrome at the bottom of the welcome screen. On
643643
# resume with prior usage we paint bar+prompt carrying the last
644644
# response's tokens (typing-ready shape from `endTurn`). On resume
645-
# without usage we still paint the bar at zeros. On a fresh start
646-
# we paint *just* the prompt — the bar stays hidden until the first
647-
# model response brings real values to put in it. From the first
648-
# `paintBarPrompt` onward the bar+prompt are always visible.
645+
# without usage and on a fresh start we paint the bar at zeros —
646+
# the context percentage is always visible, before the first model
647+
# response just like after it.
649648
if restoredDraft.len > 0:
650649
editor.prefillText = restoredDraft
651650
if resume:
@@ -673,6 +672,10 @@ proc main() =
673672
paintInitialPrompt(prof)
674673
else:
675674
paintInitialPrompt(prof)
675+
# The startup paint is a render boundary the tty harness synchronizes
676+
# on: without the frame event the first captured frame can predate the
677+
# chrome (or miss it entirely when the PTY burst is coalesced).
678+
emitTestFrameEvent()
676679
startupTrace("first-prompt-painted")
677680
if prompt != "" and runInitialPrompt(prompt):
678681
# quit, not return: unwinding `editor` while the input thread still

‎src/threecode/fatprompt/rendering.nim‎

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -549,12 +549,6 @@ proc formatUserPromptItem*(line: string): string =
549549
## included; the controller/transcript emitter owns inter-item spacing.
550550
result.addUserEcho(line, trailingNewline = false)
551551

552-
proc promptOnlyBytes*(): string =
553-
"\r\x1b[2K" & EditorPromptBytes
554-
555-
proc promptOnlyResetBytes*(): string =
556-
"\x1b[2K" & EditorPromptBytes
557-
558552
proc clearPromptAfterPendingReceiptBytes*(): string =
559553
"\r\x1b[1A\x1b[J"
560554

‎src/threecode/fatprompt/runtime.nim‎

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -896,28 +896,40 @@ proc liveLabel*(base: string, slurped: int): string =
896896
parts.join(" ")
897897

898898
proc paintInitialPrompt*(p: Profile) =
899-
## Welcome-time paint when starting fresh. The first prompt is intentionally
900-
## prompt-only; the token bar appears after the first response has real usage
901-
## to display.
899+
## Welcome-time paint when starting fresh: gap row + token bar at zero
900+
## usage + idle prompt, the same typing-ready shape `endTurn` and the
901+
## resume path leave behind. The bar always shows the context percentage
902+
## (design contract), so it is primed at `○0%` rather than hidden until
903+
## the first response; `pendingHint` is primed with zeroed usage so the
904+
## first user submit converts the bar into a receipt row exactly like
905+
## every later turn.
902906
##
903-
## Leaves `currentBarLabel = ""` and `currentBarHasGap = false` —
904-
## the signals `readInput`, `emitUserSubmit`, and the slash-command
905-
## repaint use to detect prompt-only mode. Paints through the engine's
906-
## frame model when the live editor is anchored so `paintedFooterRows`
907-
## tracks the prompt row; the pre-input-thread path (no editor yet)
908-
## falls back to a raw paint, cleared later by the walk-up's erase.
909-
discard p
910-
emitFatPromptEvent clearBarEvent()
907+
## Paints through the engine's frame model when the live editor is
908+
## anchored so `paintedFooterRows` tracks the chrome; the
909+
## pre-input-thread path (no editor yet) falls back to a raw paint,
910+
## cleared later by the walk-up's erase.
911+
let window = contextWindowFor(p)
912+
emitFatPromptEvent setBarEvent(contextLabel(0, window),
913+
hasGap = true)
914+
emitFatPromptEvent setPendingHintEvent(Usage(), window, -1)
915+
# The gap row between the welcome's last line and the bar: the same
916+
# blank row `endTurn` and the resume path leave above the bar. Without
917+
# it the bar paints flush against the hint line, and the first
918+
# keystroke's walk-up (sized from paintedFooterRows) erases the hint
919+
# instead of the gap.
920+
termengine.syncWrite("\r\n")
911921
if liveEditorFooterAnchored():
912922
termengine.renderFooter(footerFrame(fatPromptState),
913923
inputThreadRunning, inputEditor,
914924
currentTermW())
915925
else:
916-
# Raw gap + prompt. Register the reserved gap row so the first later
917-
# walk-up (spinner/bar paint, submit erase) does not under-count and
918-
# overwrite the line above the prompt.
919-
termengine.writeRaw("\n\x1b[?25l" & promptOnlyResetBytes())
920-
termengine.noteFooterPainted(1)
926+
# Raw gap + bar + prompt. Register the reserved rows so the first
927+
# later walk-up (spinner/bar paint, submit erase) does not under-count
928+
# and overwrite the line above the prompt.
929+
termengine.syncWrite(hideRealCaretBytes() &
930+
barPromptStartupBytes(fatPromptState.footer.barLabel, currentTermW()))
931+
termengine.noteFooterPainted(
932+
footerRowsAboveEditor(fatPromptState, currentTermW()))
921933

922934
proc paintResumedBarPrompt*(label: string) =
923935
## Startup paint for --resume with prior usage: bar + idle prompt in the

‎testdata/fixtures/tty/bash_tool_visual_test.txt‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,20 @@
99

1010
type a prompt. :help for commands. :q or Ctrl-D to exit.
1111

12+
○0%
13+
❯
14+
===== 0 =====
15+
16+
╭─╮
17+
─┤ 3code v0.5.0-bash1-0453a5d8-unstaged the economical coding agent
18+
╰─╯
19+
20+
provider stub
21+
model stub-model
22+
23+
type a prompt. :help for commands. :q or Ctrl-D to exit.
24+
25+
○0%
1226
❯ run bash checks
1327
===== 392 =====
1428

‎testdata/fixtures/tty/harness_commands.txt‎

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99

1010
type a prompt. :help for commands. :q or Ctrl-D to exit.
1111

12+
○0%
1213
❯ :help
1314
===== 0 =====
14-
:reasoning list reasoning levels for current model (* marks active)
1515
:reasoning X switch reasoning level (low / medium / high)
1616
:streaming show streaming mode (on = live output, off = request/response)
1717
:streaming on|off toggle SSE streaming (off is the reliable fallback for flaky SSE)
@@ -50,9 +50,9 @@ input:
5050
ctrl+l clear the screen
5151
@path inline file contents (e.g. @src/foo.nim)
5252

53+
○0%
5354
❯
5455
===== 0 =====
55-
:reasoning list reasoning levels for current model (* marks active)
5656
:reasoning X switch reasoning level (low / medium / high)
5757
:streaming show streaming mode (on = live output, off = request/response)
5858
:streaming on|off toggle SSE streaming (off is the reliable fallback for flaky SSE)
@@ -91,9 +91,9 @@ input:
9191
ctrl+l clear the screen
9292
@path inline file contents (e.g. @src/foo.nim)
9393

94+
○0%
9495
❯ :provider
9596
===== 0 =====
96-
:notify on|off toggle turn-end desktop notification
9797
:retry show patient-retry mode (on = ~36h hold for outages/limits)
9898
:retry on|off toggle patient retry of 429/5xx/network errors
9999
:prompt show the active system prompt
@@ -132,9 +132,9 @@ input:
132132
stub [stub-model]
133133
alt
134134

135+
○0%
135136
❯
136137
===== 0 =====
137-
:notify on|off toggle turn-end desktop notification
138138
:retry show patient-retry mode (on = ~36h hold for outages/limits)
139139
:retry on|off toggle patient retry of 429/5xx/network errors
140140
:prompt show the active system prompt
@@ -173,9 +173,9 @@ input:
173173
stub [stub-model]
174174
alt
175175

176+
○0%
176177
❯ :model
177178
===== 0 =====
178-
:log list all tool calls this session
179179
:sessions list recent sessions saved in this directory (max 20)
180180
:summarize collapse old turns into a synthetic recap (meta model call)
181181
:version show the running 3code version
@@ -214,9 +214,9 @@ alt
214214
stub-model [stub]
215215
stub-large
216216

217+
○0%
217218
❯
218219
===== 0 =====
219-
:log list all tool calls this session
220220
:sessions list recent sessions saved in this directory (max 20)
221221
:summarize collapse old turns into a synthetic recap (meta model call)
222222
:version show the running 3code version
@@ -255,9 +255,9 @@ alt
255255
stub-model [stub]
256256
stub-large
257257

258+
○0%
258259
❯ :reasoning
259260
===== 0 =====
260-
:sandbox show (same)
261261
:sandbox on|off toggle sandbox enforcement (off = bash unconfined)
262262
:sandbox allow T add a writable/connectable rule (allow T)
263263
:sandbox readonly P add a read-only rule (readonly P)
@@ -296,9 +296,9 @@ stub-large
296296
reasoning: (none)
297297
experimental: level is free-form, type any value
298298

299+
○0%
299300
❯
300301
===== 0 =====
301-
:sandbox show (same)
302302
:sandbox on|off toggle sandbox enforcement (off = bash unconfined)
303303
:sandbox allow T add a writable/connectable rule (allow T)
304304
:sandbox readonly P add a read-only rule (readonly P)
@@ -337,6 +337,7 @@ stub-large
337337
reasoning: (none)
338338
experimental: level is free-form, type any value
339339

340+
○0%
340341
❯ :model stub-large
341342
===== 0 =====
342343
:sandbox edit open the policy file in $VISUAL/$EDITOR, reload on quit

‎testdata/fixtures/tty/multiline.txt‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,20 @@
99

1010
type a prompt. :help for commands. :q or Ctrl-D to exit.
1111

12+
○0%
13+
❯
14+
===== 0 =====
15+
16+
╭─╮
17+
─┤ 3code v0.5.0-bash1-0453a5d8-unstaged the economical coding agent
18+
╰─╯
19+
20+
provider stub
21+
model stub-model
22+
23+
type a prompt. :help for commands. :q or Ctrl-D to exit.
24+
25+
○0%
1226
❯ first line
1327
===== 436 =====
1428

@@ -21,6 +35,7 @@
2135

2236
type a prompt. :help for commands. :q or Ctrl-D to exit.
2337

38+
○0%
2439
❯ first line
2540

2641
===== 504 =====
@@ -34,6 +49,7 @@
3449

3550
type a prompt. :help for commands. :q or Ctrl-D to exit.
3651

52+
○0%
3753
❯ first line
3854
second line
3955
===== 659 =====

‎testdata/fixtures/tty/other_tools_visual_test.txt‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,20 @@
99

1010
type a prompt. :help for commands. :q or Ctrl-D to exit.
1111

12+
○0%
13+
❯
14+
===== 0 =====
15+
16+
╭─╮
17+
─┤ 3code v0.6.0-filename-805c0e7e-unstaged the economical coding agent
18+
╰─╯
19+
20+
provider stub
21+
model stub-model
22+
23+
type a prompt. :help for commands. :q or Ctrl-D to exit.
24+
25+
○0%
1226
❯ run other tool checks
1327
===== 786 =====
1428

‎testdata/fixtures/tty/simple.txt‎

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,20 @@
99

1010
type a prompt. :help for commands. :q or Ctrl-D to exit.
1111

12+
○0%
13+
❯
14+
===== 0 =====
15+
16+
╭─╮
17+
─┤ 3code v0.5.0-bash1-0453a5d8-unstaged the economical coding agent
18+
╰─╯
19+
20+
provider stub
21+
model stub-model
22+
23+
type a prompt. :help for commands. :q or Ctrl-D to exit.
24+
25+
○0%
1226
❯ This is a test prompt
1327
===== 623 =====
1428

@@ -20,7 +34,6 @@
2034
model stub-model
2135

2236
type a prompt. :help for commands. :q or Ctrl-D to exit.
23-
2437
❯ This is a test prompt
2538
… Thinking about the test prompt
2639
⣿ ○0% ↓7 0s
@@ -35,7 +48,6 @@
3548
model stub-model
3649

3750
type a prompt. :help for commands. :q or Ctrl-D to exit.
38-
3951
❯ This is a test prompt
4052

4153
● This is a test response.
@@ -52,7 +64,6 @@
5264
model stub-model
5365

5466
type a prompt. :help for commands. :q or Ctrl-D to exit.
55-
5667
❯ This is a test prompt
5768

5869
● This is a test response.
@@ -69,7 +80,6 @@
6980
model stub-model
7081

7182
type a prompt. :help for commands. :q or Ctrl-D to exit.
72-
7383
❯ This is a test prompt
7484

7585
● This is a test response.

0 commit comments

Comments
 (0)