feat(cli): refresh the statusline ctx segment per settled provider request (#4545) - #4550

Open
me2seeks wants to merge 2 commits into
apache:mainfrom
me2seeks:feat/4545-live-ctx
Open

feat(cli): refresh the statusline ctx segment per settled provider request (#4545)#4550
me2seeks wants to merge 2 commits into
apache:mainfrom
me2seeks:feat/4545-live-ctx

Conversation

@me2seeks

Copy link
Copy Markdown
Contributor

Closes#4545.

Problem

The TUI statusline ctx used/window pct% segment only moved once per turn, when the end-of-turn token_usage event landed. During a long agentic turn — dozens of tool steps over minutes, exactly when the context grows fastest — the indicator sat frozen at the previous turn's value, hiding the signal that says "time to /compact or wrap up".

Approach

Reuse the desktop inspector's pull model instead of growing a parallel push event (design + audit: docs/tui-live-ctx-updates.md, 中文讲解 docs/tui-live-ctx-updates.zh-CN.md):

  • The Host already commits a latest-context snapshot at every settled provider request (provider-request-telemetry.ts), and context.diagnostics.query is a plain read with no busy gate — the desktop inspector refreshes from it mid-turn on trace-relevant events.
  • New packages/cli/src/tui-context-refresh.ts: the desktop trace-relevant event set (tool_start, tool_result, token_usage, …) + a restart-on-event debouncer (400 ms, same as desktop) whose revision guard lets only the latest issued query apply; a failed read leaves the last value standing.
  • pi-tui-runner.ts: observe() on the shared turn-drain onEvent (covers user-submitted and Host-attached turns alike) and on the resumeLatest loop; cancel() on teardown; a stale-session guard drops results that resolve after a switch. The query calls the driver directly — runControl's serial lock exists for mutations, and /context's mid-turn refusal is a TUI-local choice, not a protocol constraint.
  • The apply path uses the same contextRemaining = contextWindow − inputTokens formula as the token_usage path (fix(runtime): emit contextRemaining in token_usage events so the TUI ctx segment renders #1067), derived from the same settled request — the two cannot disagree. Turn-end token_usage stays the authoritative persisted record; this only enriches the live turn.

Zero protocol / runtime / persistence changes: no new event type, no billing semantics touched (#972).

Non-goals

  • Token-level updates during one streaming request: providers report input tokens only at completion, so exact mid-request values do not exist; the pre-dispatch bytes/4 estimate is too rough (base64 attachments) to show.
  • Unlocking /context mid-turn over the same query path — a free follow-up, kept out to stay small.
  • Desktop changes (already has this granularity).

Test plan

  • New unit tests tui-context-refresh.test.ts (9): event-set parity with desktop, debounce coalescing, out-of-order resolution guard, failed read keeps last value, cancel retires scheduled + in-flight queries, real-timer sanity.
  • New runner integration tests (2): ctx segment moves mid-turn while the turn is parked after tool_start (before any token_usage); a failing snapshot read leaves the segment untouched and silent.
  • Full maka-agent package suite: 732 passed, 0 failed (3 pre-existing skips); whole-repo typecheck green; biome lint/format clean; ASF header check green.

@github-actionsgithub-actionsBot added the effort/L Under 1000 readable lines label Sep 2, 2026
…quest (apache#4545)
The ctx segment only moved when the end-of-turn token_usage event landed,
so a long agentic turn burned context with the indicator frozen at the
previous turn's value. The Host already commits a latest-context snapshot
at every settled provider request (the desktop inspector's data source),
so pull it on the desktop's own signal: trace-relevant events schedule a
400ms-debounced getContextDiagnostics read, and the latest issued read
writes contextRemaining straight into the statusline usage.
- tui-context-refresh.ts: desktop's trace-relevant event set + a
restart-on-event debouncer whose revision guard lets only the latest
issued query apply; a failed read leaves the last value standing.
- pi-tui-runner.ts: observe() on the shared turn-drain onEvent (covers
user and Host-attached turns) and on resumeLatest; cancel on teardown;
stale-session guard drops pre-switch results. ctxRefreshTicker input
option injects the timer for tests.
Zero protocol/runtime changes: no new event type, no persistence or
billing semantics touched (apache#972). Turn-end token_usage stays the
authoritative persisted record.

@M4n5terM4n5ter left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed exact head 4be9222680c3a0fee115eb78d5ac567219c14516.

The new refresh lifecycle correctly coalesces settled provider-request signals, retires stale reads by revision, and fences session switches. I found one P2 display-coherence defect, detailed inline. It affects the accuracy of the context-pressure indicator but not execution or durable state, so I am approving with that follow-up comment.

The exact-head test check is green and the current-main merge result is clean.


Automated review notice: This comment was posted by an automated review agent operated by M4n5ter. It is not an independent human review and does not replace one.

return;
// Same formula the token_usage path uses (#1067), from the same
// settled request — the two cannot disagree.
state.usage.contextRemaining = Math.max(0, contextWindow - inputTokens);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Keep the diagnostics window with the remaining-token snapshot. This path reads one settled request's inputTokens and contextWindow, but stores only their difference. The statusline later subtracts that old remainder from the current mutable model-catalog window. I reproduced a settled 100k/200k snapshot followed by a catalog refresh to 500k: the UI renders ctx 400k/500k 80% instead of ctx 100k/200k 50%. Store and render the numerator/denominator from the same diagnostics snapshot, and add a regression where the diagnostics and catalog windows intentionally differ.


Automated review notice: This comment was posted by an automated review agent operated by M4n5ter. It is not an independent human review and does not replace one.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/LUnder 1000 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(cli): TUI statusline ctx segment should update per settled provider request, not just at turn end

2 participants

@me2seeks@M4n5ter
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

feat(cli): refresh the statusline ctx segment per settled provider request (#4545) - #4550

Open
me2seeks wants to merge 2 commits into
apache:mainfrom
me2seeks:feat/4545-live-ctx
Open

feat(cli): refresh the statusline ctx segment per settled provider request (#4545)#4550
me2seeks wants to merge 2 commits into
apache:mainfrom
me2seeks:feat/4545-live-ctx

Conversation

@me2seeks

Copy link
Copy Markdown
Contributor

Closes#4545.

Problem

The TUI statusline ctx used/window pct% segment only moved once per turn, when the end-of-turn token_usage event landed. During a long agentic turn — dozens of tool steps over minutes, exactly when the context grows fastest — the indicator sat frozen at the previous turn's value, hiding the signal that says "time to /compact or wrap up".

Approach

Reuse the desktop inspector's pull model instead of growing a parallel push event (design + audit: docs/tui-live-ctx-updates.md, 中文讲解 docs/tui-live-ctx-updates.zh-CN.md):

  • The Host already commits a latest-context snapshot at every settled provider request (provider-request-telemetry.ts), and context.diagnostics.query is a plain read with no busy gate — the desktop inspector refreshes from it mid-turn on trace-relevant events.
  • New packages/cli/src/tui-context-refresh.ts: the desktop trace-relevant event set (tool_start, tool_result, token_usage, …) + a restart-on-event debouncer (400 ms, same as desktop) whose revision guard lets only the latest issued query apply; a failed read leaves the last value standing.
  • pi-tui-runner.ts: observe() on the shared turn-drain onEvent (covers user-submitted and Host-attached turns alike) and on the resumeLatest loop; cancel() on teardown; a stale-session guard drops results that resolve after a switch. The query calls the driver directly — runControl's serial lock exists for mutations, and /context's mid-turn refusal is a TUI-local choice, not a protocol constraint.
  • The apply path uses the same contextRemaining = contextWindow − inputTokens formula as the token_usage path (fix(runtime): emit contextRemaining in token_usage events so the TUI ctx segment renders #1067), derived from the same settled request — the two cannot disagree. Turn-end token_usage stays the authoritative persisted record; this only enriches the live turn.

Zero protocol / runtime / persistence changes: no new event type, no billing semantics touched (#972).

Non-goals

  • Token-level updates during one streaming request: providers report input tokens only at completion, so exact mid-request values do not exist; the pre-dispatch bytes/4 estimate is too rough (base64 attachments) to show.
  • Unlocking /context mid-turn over the same query path — a free follow-up, kept out to stay small.
  • Desktop changes (already has this granularity).

Test plan

  • New unit tests tui-context-refresh.test.ts (9): event-set parity with desktop, debounce coalescing, out-of-order resolution guard, failed read keeps last value, cancel retires scheduled + in-flight queries, real-timer sanity.
  • New runner integration tests (2): ctx segment moves mid-turn while the turn is parked after tool_start (before any token_usage); a failing snapshot read leaves the segment untouched and silent.
  • Full maka-agent package suite: 732 passed, 0 failed (3 pre-existing skips); whole-repo typecheck green; biome lint/format clean; ASF header check green.

@github-actionsgithub-actionsBot added the effort/L Under 1000 readable lines label Sep 2, 2026
…quest (apache#4545)
The ctx segment only moved when the end-of-turn token_usage event landed,
so a long agentic turn burned context with the indicator frozen at the
previous turn's value. The Host already commits a latest-context snapshot
at every settled provider request (the desktop inspector's data source),
so pull it on the desktop's own signal: trace-relevant events schedule a
400ms-debounced getContextDiagnostics read, and the latest issued read
writes contextRemaining straight into the statusline usage.
- tui-context-refresh.ts: desktop's trace-relevant event set + a
restart-on-event debouncer whose revision guard lets only the latest
issued query apply; a failed read leaves the last value standing.
- pi-tui-runner.ts: observe() on the shared turn-drain onEvent (covers
user and Host-attached turns) and on resumeLatest; cancel on teardown;
stale-session guard drops pre-switch results. ctxRefreshTicker input
option injects the timer for tests.
Zero protocol/runtime changes: no new event type, no persistence or
billing semantics touched (apache#972). Turn-end token_usage stays the
authoritative persisted record.

@M4n5terM4n5ter left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed exact head 4be9222680c3a0fee115eb78d5ac567219c14516.

The new refresh lifecycle correctly coalesces settled provider-request signals, retires stale reads by revision, and fences session switches. I found one P2 display-coherence defect, detailed inline. It affects the accuracy of the context-pressure indicator but not execution or durable state, so I am approving with that follow-up comment.

The exact-head test check is green and the current-main merge result is clean.


Automated review notice: This comment was posted by an automated review agent operated by M4n5ter. It is not an independent human review and does not replace one.

return;
// Same formula the token_usage path uses (#1067), from the same
// settled request — the two cannot disagree.
state.usage.contextRemaining = Math.max(0, contextWindow - inputTokens);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Keep the diagnostics window with the remaining-token snapshot. This path reads one settled request's inputTokens and contextWindow, but stores only their difference. The statusline later subtracts that old remainder from the current mutable model-catalog window. I reproduced a settled 100k/200k snapshot followed by a catalog refresh to 500k: the UI renders ctx 400k/500k 80% instead of ctx 100k/200k 50%. Store and render the numerator/denominator from the same diagnostics snapshot, and add a regression where the diagnostics and catalog windows intentionally differ.


Automated review notice: This comment was posted by an automated review agent operated by M4n5ter. It is not an independent human review and does not replace one.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/LUnder 1000 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(cli): TUI statusline ctx segment should update per settled provider request, not just at turn end

2 participants

@me2seeks@M4n5ter
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(cli): refresh the statusline ctx segment per settled provider request (#4545) - #4550

Open
me2seeks wants to merge 2 commits into
apache:mainfrom
me2seeks:feat/4545-live-ctx
Open

feat(cli): refresh the statusline ctx segment per settled provider request (#4545)#4550
me2seeks wants to merge 2 commits into
apache:mainfrom
me2seeks:feat/4545-live-ctx

Conversation

@me2seeks

Copy link
Copy Markdown
Contributor

Closes#4545.

Problem

The TUI statusline ctx used/window pct% segment only moved once per turn, when the end-of-turn token_usage event landed. During a long agentic turn — dozens of tool steps over minutes, exactly when the context grows fastest — the indicator sat frozen at the previous turn's value, hiding the signal that says "time to /compact or wrap up".

Approach

Reuse the desktop inspector's pull model instead of growing a parallel push event (design + audit: docs/tui-live-ctx-updates.md, 中文讲解 docs/tui-live-ctx-updates.zh-CN.md):

  • The Host already commits a latest-context snapshot at every settled provider request (provider-request-telemetry.ts), and context.diagnostics.query is a plain read with no busy gate — the desktop inspector refreshes from it mid-turn on trace-relevant events.
  • New packages/cli/src/tui-context-refresh.ts: the desktop trace-relevant event set (tool_start, tool_result, token_usage, …) + a restart-on-event debouncer (400 ms, same as desktop) whose revision guard lets only the latest issued query apply; a failed read leaves the last value standing.
  • pi-tui-runner.ts: observe() on the shared turn-drain onEvent (covers user-submitted and Host-attached turns alike) and on the resumeLatest loop; cancel() on teardown; a stale-session guard drops results that resolve after a switch. The query calls the driver directly — runControl's serial lock exists for mutations, and /context's mid-turn refusal is a TUI-local choice, not a protocol constraint.
  • The apply path uses the same contextRemaining = contextWindow − inputTokens formula as the token_usage path (fix(runtime): emit contextRemaining in token_usage events so the TUI ctx segment renders #1067), derived from the same settled request — the two cannot disagree. Turn-end token_usage stays the authoritative persisted record; this only enriches the live turn.

Zero protocol / runtime / persistence changes: no new event type, no billing semantics touched (#972).

Non-goals

  • Token-level updates during one streaming request: providers report input tokens only at completion, so exact mid-request values do not exist; the pre-dispatch bytes/4 estimate is too rough (base64 attachments) to show.
  • Unlocking /context mid-turn over the same query path — a free follow-up, kept out to stay small.
  • Desktop changes (already has this granularity).

Test plan

  • New unit tests tui-context-refresh.test.ts (9): event-set parity with desktop, debounce coalescing, out-of-order resolution guard, failed read keeps last value, cancel retires scheduled + in-flight queries, real-timer sanity.
  • New runner integration tests (2): ctx segment moves mid-turn while the turn is parked after tool_start (before any token_usage); a failing snapshot read leaves the segment untouched and silent.
  • Full maka-agent package suite: 732 passed, 0 failed (3 pre-existing skips); whole-repo typecheck green; biome lint/format clean; ASF header check green.

@github-actionsgithub-actionsBot added the effort/L Under 1000 readable lines label Sep 2, 2026
…quest (apache#4545)
The ctx segment only moved when the end-of-turn token_usage event landed,
so a long agentic turn burned context with the indicator frozen at the
previous turn's value. The Host already commits a latest-context snapshot
at every settled provider request (the desktop inspector's data source),
so pull it on the desktop's own signal: trace-relevant events schedule a
400ms-debounced getContextDiagnostics read, and the latest issued read
writes contextRemaining straight into the statusline usage.
- tui-context-refresh.ts: desktop's trace-relevant event set + a
restart-on-event debouncer whose revision guard lets only the latest
issued query apply; a failed read leaves the last value standing.
- pi-tui-runner.ts: observe() on the shared turn-drain onEvent (covers
user and Host-attached turns) and on resumeLatest; cancel on teardown;
stale-session guard drops pre-switch results. ctxRefreshTicker input
option injects the timer for tests.
Zero protocol/runtime changes: no new event type, no persistence or
billing semantics touched (apache#972). Turn-end token_usage stays the
authoritative persisted record.

@M4n5terM4n5ter left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed exact head 4be9222680c3a0fee115eb78d5ac567219c14516.

The new refresh lifecycle correctly coalesces settled provider-request signals, retires stale reads by revision, and fences session switches. I found one P2 display-coherence defect, detailed inline. It affects the accuracy of the context-pressure indicator but not execution or durable state, so I am approving with that follow-up comment.

The exact-head test check is green and the current-main merge result is clean.


Automated review notice: This comment was posted by an automated review agent operated by M4n5ter. It is not an independent human review and does not replace one.

return;
// Same formula the token_usage path uses (#1067), from the same
// settled request — the two cannot disagree.
state.usage.contextRemaining = Math.max(0, contextWindow - inputTokens);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Keep the diagnostics window with the remaining-token snapshot. This path reads one settled request's inputTokens and contextWindow, but stores only their difference. The statusline later subtracts that old remainder from the current mutable model-catalog window. I reproduced a settled 100k/200k snapshot followed by a catalog refresh to 500k: the UI renders ctx 400k/500k 80% instead of ctx 100k/200k 50%. Store and render the numerator/denominator from the same diagnostics snapshot, and add a regression where the diagnostics and catalog windows intentionally differ.


Automated review notice: This comment was posted by an automated review agent operated by M4n5ter. It is not an independent human review and does not replace one.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/LUnder 1000 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(cli): TUI statusline ctx segment should update per settled provider request, not just at turn end

2 participants

@me2seeks@M4n5ter
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(cli): refresh the statusline ctx segment per settled provider request (#4545) - #4550

Open
me2seeks wants to merge 2 commits into
apache:mainfrom
me2seeks:feat/4545-live-ctx
Open

feat(cli): refresh the statusline ctx segment per settled provider request (#4545)#4550
me2seeks wants to merge 2 commits into
apache:mainfrom
me2seeks:feat/4545-live-ctx

Conversation

@me2seeks

Copy link
Copy Markdown
Contributor

Closes#4545.

Problem

The TUI statusline ctx used/window pct% segment only moved once per turn, when the end-of-turn token_usage event landed. During a long agentic turn — dozens of tool steps over minutes, exactly when the context grows fastest — the indicator sat frozen at the previous turn's value, hiding the signal that says "time to /compact or wrap up".

Approach

Reuse the desktop inspector's pull model instead of growing a parallel push event (design + audit: docs/tui-live-ctx-updates.md, 中文讲解 docs/tui-live-ctx-updates.zh-CN.md):

  • The Host already commits a latest-context snapshot at every settled provider request (provider-request-telemetry.ts), and context.diagnostics.query is a plain read with no busy gate — the desktop inspector refreshes from it mid-turn on trace-relevant events.
  • New packages/cli/src/tui-context-refresh.ts: the desktop trace-relevant event set (tool_start, tool_result, token_usage, …) + a restart-on-event debouncer (400 ms, same as desktop) whose revision guard lets only the latest issued query apply; a failed read leaves the last value standing.
  • pi-tui-runner.ts: observe() on the shared turn-drain onEvent (covers user-submitted and Host-attached turns alike) and on the resumeLatest loop; cancel() on teardown; a stale-session guard drops results that resolve after a switch. The query calls the driver directly — runControl's serial lock exists for mutations, and /context's mid-turn refusal is a TUI-local choice, not a protocol constraint.
  • The apply path uses the same contextRemaining = contextWindow − inputTokens formula as the token_usage path (fix(runtime): emit contextRemaining in token_usage events so the TUI ctx segment renders #1067), derived from the same settled request — the two cannot disagree. Turn-end token_usage stays the authoritative persisted record; this only enriches the live turn.

Zero protocol / runtime / persistence changes: no new event type, no billing semantics touched (#972).

Non-goals

  • Token-level updates during one streaming request: providers report input tokens only at completion, so exact mid-request values do not exist; the pre-dispatch bytes/4 estimate is too rough (base64 attachments) to show.
  • Unlocking /context mid-turn over the same query path — a free follow-up, kept out to stay small.
  • Desktop changes (already has this granularity).

Test plan

  • New unit tests tui-context-refresh.test.ts (9): event-set parity with desktop, debounce coalescing, out-of-order resolution guard, failed read keeps last value, cancel retires scheduled + in-flight queries, real-timer sanity.
  • New runner integration tests (2): ctx segment moves mid-turn while the turn is parked after tool_start (before any token_usage); a failing snapshot read leaves the segment untouched and silent.
  • Full maka-agent package suite: 732 passed, 0 failed (3 pre-existing skips); whole-repo typecheck green; biome lint/format clean; ASF header check green.

@github-actionsgithub-actionsBot added the effort/L Under 1000 readable lines label Sep 2, 2026
…quest (apache#4545)
The ctx segment only moved when the end-of-turn token_usage event landed,
so a long agentic turn burned context with the indicator frozen at the
previous turn's value. The Host already commits a latest-context snapshot
at every settled provider request (the desktop inspector's data source),
so pull it on the desktop's own signal: trace-relevant events schedule a
400ms-debounced getContextDiagnostics read, and the latest issued read
writes contextRemaining straight into the statusline usage.
- tui-context-refresh.ts: desktop's trace-relevant event set + a
restart-on-event debouncer whose revision guard lets only the latest
issued query apply; a failed read leaves the last value standing.
- pi-tui-runner.ts: observe() on the shared turn-drain onEvent (covers
user and Host-attached turns) and on resumeLatest; cancel on teardown;
stale-session guard drops pre-switch results. ctxRefreshTicker input
option injects the timer for tests.
Zero protocol/runtime changes: no new event type, no persistence or
billing semantics touched (apache#972). Turn-end token_usage stays the
authoritative persisted record.

@M4n5terM4n5ter left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed exact head 4be9222680c3a0fee115eb78d5ac567219c14516.

The new refresh lifecycle correctly coalesces settled provider-request signals, retires stale reads by revision, and fences session switches. I found one P2 display-coherence defect, detailed inline. It affects the accuracy of the context-pressure indicator but not execution or durable state, so I am approving with that follow-up comment.

The exact-head test check is green and the current-main merge result is clean.


Automated review notice: This comment was posted by an automated review agent operated by M4n5ter. It is not an independent human review and does not replace one.

return;
// Same formula the token_usage path uses (#1067), from the same
// settled request — the two cannot disagree.
state.usage.contextRemaining = Math.max(0, contextWindow - inputTokens);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Keep the diagnostics window with the remaining-token snapshot. This path reads one settled request's inputTokens and contextWindow, but stores only their difference. The statusline later subtracts that old remainder from the current mutable model-catalog window. I reproduced a settled 100k/200k snapshot followed by a catalog refresh to 500k: the UI renders ctx 400k/500k 80% instead of ctx 100k/200k 50%. Store and render the numerator/denominator from the same diagnostics snapshot, and add a regression where the diagnostics and catalog windows intentionally differ.


Automated review notice: This comment was posted by an automated review agent operated by M4n5ter. It is not an independent human review and does not replace one.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/LUnder 1000 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(cli): TUI statusline ctx segment should update per settled provider request, not just at turn end

2 participants

@me2seeks@M4n5ter
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

feat(cli): refresh the statusline ctx segment per settled provider request (#4545) - #4550

Open
me2seeks wants to merge 2 commits into
apache:mainfrom
me2seeks:feat/4545-live-ctx
Open

feat(cli): refresh the statusline ctx segment per settled provider request (#4545)#4550
me2seeks wants to merge 2 commits into
apache:mainfrom
me2seeks:feat/4545-live-ctx

Conversation

@me2seeks

Copy link
Copy Markdown
Contributor

Closes#4545.

Problem

The TUI statusline ctx used/window pct% segment only moved once per turn, when the end-of-turn token_usage event landed. During a long agentic turn — dozens of tool steps over minutes, exactly when the context grows fastest — the indicator sat frozen at the previous turn's value, hiding the signal that says "time to /compact or wrap up".

Approach

Reuse the desktop inspector's pull model instead of growing a parallel push event (design + audit: docs/tui-live-ctx-updates.md, 中文讲解 docs/tui-live-ctx-updates.zh-CN.md):

  • The Host already commits a latest-context snapshot at every settled provider request (provider-request-telemetry.ts), and context.diagnostics.query is a plain read with no busy gate — the desktop inspector refreshes from it mid-turn on trace-relevant events.
  • New packages/cli/src/tui-context-refresh.ts: the desktop trace-relevant event set (tool_start, tool_result, token_usage, …) + a restart-on-event debouncer (400 ms, same as desktop) whose revision guard lets only the latest issued query apply; a failed read leaves the last value standing.
  • pi-tui-runner.ts: observe() on the shared turn-drain onEvent (covers user-submitted and Host-attached turns alike) and on the resumeLatest loop; cancel() on teardown; a stale-session guard drops results that resolve after a switch. The query calls the driver directly — runControl's serial lock exists for mutations, and /context's mid-turn refusal is a TUI-local choice, not a protocol constraint.
  • The apply path uses the same contextRemaining = contextWindow − inputTokens formula as the token_usage path (fix(runtime): emit contextRemaining in token_usage events so the TUI ctx segment renders #1067), derived from the same settled request — the two cannot disagree. Turn-end token_usage stays the authoritative persisted record; this only enriches the live turn.

Zero protocol / runtime / persistence changes: no new event type, no billing semantics touched (#972).

Non-goals

  • Token-level updates during one streaming request: providers report input tokens only at completion, so exact mid-request values do not exist; the pre-dispatch bytes/4 estimate is too rough (base64 attachments) to show.
  • Unlocking /context mid-turn over the same query path — a free follow-up, kept out to stay small.
  • Desktop changes (already has this granularity).

Test plan

  • New unit tests tui-context-refresh.test.ts (9): event-set parity with desktop, debounce coalescing, out-of-order resolution guard, failed read keeps last value, cancel retires scheduled + in-flight queries, real-timer sanity.
  • New runner integration tests (2): ctx segment moves mid-turn while the turn is parked after tool_start (before any token_usage); a failing snapshot read leaves the segment untouched and silent.
  • Full maka-agent package suite: 732 passed, 0 failed (3 pre-existing skips); whole-repo typecheck green; biome lint/format clean; ASF header check green.

@github-actionsgithub-actionsBot added the effort/L Under 1000 readable lines label Sep 2, 2026
…quest (apache#4545)
The ctx segment only moved when the end-of-turn token_usage event landed,
so a long agentic turn burned context with the indicator frozen at the
previous turn's value. The Host already commits a latest-context snapshot
at every settled provider request (the desktop inspector's data source),
so pull it on the desktop's own signal: trace-relevant events schedule a
400ms-debounced getContextDiagnostics read, and the latest issued read
writes contextRemaining straight into the statusline usage.
- tui-context-refresh.ts: desktop's trace-relevant event set + a
restart-on-event debouncer whose revision guard lets only the latest
issued query apply; a failed read leaves the last value standing.
- pi-tui-runner.ts: observe() on the shared turn-drain onEvent (covers
user and Host-attached turns) and on resumeLatest; cancel on teardown;
stale-session guard drops pre-switch results. ctxRefreshTicker input
option injects the timer for tests.
Zero protocol/runtime changes: no new event type, no persistence or
billing semantics touched (apache#972). Turn-end token_usage stays the
authoritative persisted record.

@M4n5terM4n5ter left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed exact head 4be9222680c3a0fee115eb78d5ac567219c14516.

The new refresh lifecycle correctly coalesces settled provider-request signals, retires stale reads by revision, and fences session switches. I found one P2 display-coherence defect, detailed inline. It affects the accuracy of the context-pressure indicator but not execution or durable state, so I am approving with that follow-up comment.

The exact-head test check is green and the current-main merge result is clean.


Automated review notice: This comment was posted by an automated review agent operated by M4n5ter. It is not an independent human review and does not replace one.

return;
// Same formula the token_usage path uses (#1067), from the same
// settled request — the two cannot disagree.
state.usage.contextRemaining = Math.max(0, contextWindow - inputTokens);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Keep the diagnostics window with the remaining-token snapshot. This path reads one settled request's inputTokens and contextWindow, but stores only their difference. The statusline later subtracts that old remainder from the current mutable model-catalog window. I reproduced a settled 100k/200k snapshot followed by a catalog refresh to 500k: the UI renders ctx 400k/500k 80% instead of ctx 100k/200k 50%. Store and render the numerator/denominator from the same diagnostics snapshot, and add a regression where the diagnostics and catalog windows intentionally differ.


Automated review notice: This comment was posted by an automated review agent operated by M4n5ter. It is not an independent human review and does not replace one.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/LUnder 1000 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(cli): TUI statusline ctx segment should update per settled provider request, not just at turn end

2 participants

@me2seeks@M4n5ter
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(cli): refresh the statusline ctx segment per settled provider request (#4545) - #4550

Open
me2seeks wants to merge 2 commits into
apache:mainfrom
me2seeks:feat/4545-live-ctx
Open

feat(cli): refresh the statusline ctx segment per settled provider request (#4545)#4550
me2seeks wants to merge 2 commits into
apache:mainfrom
me2seeks:feat/4545-live-ctx

Conversation

@me2seeks

Copy link
Copy Markdown
Contributor

Closes#4545.

Problem

The TUI statusline ctx used/window pct% segment only moved once per turn, when the end-of-turn token_usage event landed. During a long agentic turn — dozens of tool steps over minutes, exactly when the context grows fastest — the indicator sat frozen at the previous turn's value, hiding the signal that says "time to /compact or wrap up".

Approach

Reuse the desktop inspector's pull model instead of growing a parallel push event (design + audit: docs/tui-live-ctx-updates.md, 中文讲解 docs/tui-live-ctx-updates.zh-CN.md):

  • The Host already commits a latest-context snapshot at every settled provider request (provider-request-telemetry.ts), and context.diagnostics.query is a plain read with no busy gate — the desktop inspector refreshes from it mid-turn on trace-relevant events.
  • New packages/cli/src/tui-context-refresh.ts: the desktop trace-relevant event set (tool_start, tool_result, token_usage, …) + a restart-on-event debouncer (400 ms, same as desktop) whose revision guard lets only the latest issued query apply; a failed read leaves the last value standing.
  • pi-tui-runner.ts: observe() on the shared turn-drain onEvent (covers user-submitted and Host-attached turns alike) and on the resumeLatest loop; cancel() on teardown; a stale-session guard drops results that resolve after a switch. The query calls the driver directly — runControl's serial lock exists for mutations, and /context's mid-turn refusal is a TUI-local choice, not a protocol constraint.
  • The apply path uses the same contextRemaining = contextWindow − inputTokens formula as the token_usage path (fix(runtime): emit contextRemaining in token_usage events so the TUI ctx segment renders #1067), derived from the same settled request — the two cannot disagree. Turn-end token_usage stays the authoritative persisted record; this only enriches the live turn.

Zero protocol / runtime / persistence changes: no new event type, no billing semantics touched (#972).

Non-goals

  • Token-level updates during one streaming request: providers report input tokens only at completion, so exact mid-request values do not exist; the pre-dispatch bytes/4 estimate is too rough (base64 attachments) to show.
  • Unlocking /context mid-turn over the same query path — a free follow-up, kept out to stay small.
  • Desktop changes (already has this granularity).

Test plan

  • New unit tests tui-context-refresh.test.ts (9): event-set parity with desktop, debounce coalescing, out-of-order resolution guard, failed read keeps last value, cancel retires scheduled + in-flight queries, real-timer sanity.
  • New runner integration tests (2): ctx segment moves mid-turn while the turn is parked after tool_start (before any token_usage); a failing snapshot read leaves the segment untouched and silent.
  • Full maka-agent package suite: 732 passed, 0 failed (3 pre-existing skips); whole-repo typecheck green; biome lint/format clean; ASF header check green.

@github-actionsgithub-actionsBot added the effort/L Under 1000 readable lines label Sep 2, 2026
…quest (apache#4545)
The ctx segment only moved when the end-of-turn token_usage event landed,
so a long agentic turn burned context with the indicator frozen at the
previous turn's value. The Host already commits a latest-context snapshot
at every settled provider request (the desktop inspector's data source),
so pull it on the desktop's own signal: trace-relevant events schedule a
400ms-debounced getContextDiagnostics read, and the latest issued read
writes contextRemaining straight into the statusline usage.
- tui-context-refresh.ts: desktop's trace-relevant event set + a
restart-on-event debouncer whose revision guard lets only the latest
issued query apply; a failed read leaves the last value standing.
- pi-tui-runner.ts: observe() on the shared turn-drain onEvent (covers
user and Host-attached turns) and on resumeLatest; cancel on teardown;
stale-session guard drops pre-switch results. ctxRefreshTicker input
option injects the timer for tests.
Zero protocol/runtime changes: no new event type, no persistence or
billing semantics touched (apache#972). Turn-end token_usage stays the
authoritative persisted record.

@M4n5terM4n5ter left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed exact head 4be9222680c3a0fee115eb78d5ac567219c14516.

The new refresh lifecycle correctly coalesces settled provider-request signals, retires stale reads by revision, and fences session switches. I found one P2 display-coherence defect, detailed inline. It affects the accuracy of the context-pressure indicator but not execution or durable state, so I am approving with that follow-up comment.

The exact-head test check is green and the current-main merge result is clean.


Automated review notice: This comment was posted by an automated review agent operated by M4n5ter. It is not an independent human review and does not replace one.

return;
// Same formula the token_usage path uses (#1067), from the same
// settled request — the two cannot disagree.
state.usage.contextRemaining = Math.max(0, contextWindow - inputTokens);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Keep the diagnostics window with the remaining-token snapshot. This path reads one settled request's inputTokens and contextWindow, but stores only their difference. The statusline later subtracts that old remainder from the current mutable model-catalog window. I reproduced a settled 100k/200k snapshot followed by a catalog refresh to 500k: the UI renders ctx 400k/500k 80% instead of ctx 100k/200k 50%. Store and render the numerator/denominator from the same diagnostics snapshot, and add a regression where the diagnostics and catalog windows intentionally differ.


Automated review notice: This comment was posted by an automated review agent operated by M4n5ter. It is not an independent human review and does not replace one.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/LUnder 1000 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(cli): TUI statusline ctx segment should update per settled provider request, not just at turn end

2 participants

@me2seeks@M4n5ter
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(cli): refresh the statusline ctx segment per settled provider request (#4545) - #4550

Open
me2seeks wants to merge 2 commits into
apache:mainfrom
me2seeks:feat/4545-live-ctx
Open

feat(cli): refresh the statusline ctx segment per settled provider request (#4545)#4550
me2seeks wants to merge 2 commits into
apache:mainfrom
me2seeks:feat/4545-live-ctx

Conversation

@me2seeks

Copy link
Copy Markdown
Contributor

Closes#4545.

Problem

The TUI statusline ctx used/window pct% segment only moved once per turn, when the end-of-turn token_usage event landed. During a long agentic turn — dozens of tool steps over minutes, exactly when the context grows fastest — the indicator sat frozen at the previous turn's value, hiding the signal that says "time to /compact or wrap up".

Approach

Reuse the desktop inspector's pull model instead of growing a parallel push event (design + audit: docs/tui-live-ctx-updates.md, 中文讲解 docs/tui-live-ctx-updates.zh-CN.md):

  • The Host already commits a latest-context snapshot at every settled provider request (provider-request-telemetry.ts), and context.diagnostics.query is a plain read with no busy gate — the desktop inspector refreshes from it mid-turn on trace-relevant events.
  • New packages/cli/src/tui-context-refresh.ts: the desktop trace-relevant event set (tool_start, tool_result, token_usage, …) + a restart-on-event debouncer (400 ms, same as desktop) whose revision guard lets only the latest issued query apply; a failed read leaves the last value standing.
  • pi-tui-runner.ts: observe() on the shared turn-drain onEvent (covers user-submitted and Host-attached turns alike) and on the resumeLatest loop; cancel() on teardown; a stale-session guard drops results that resolve after a switch. The query calls the driver directly — runControl's serial lock exists for mutations, and /context's mid-turn refusal is a TUI-local choice, not a protocol constraint.
  • The apply path uses the same contextRemaining = contextWindow − inputTokens formula as the token_usage path (fix(runtime): emit contextRemaining in token_usage events so the TUI ctx segment renders #1067), derived from the same settled request — the two cannot disagree. Turn-end token_usage stays the authoritative persisted record; this only enriches the live turn.

Zero protocol / runtime / persistence changes: no new event type, no billing semantics touched (#972).

Non-goals

  • Token-level updates during one streaming request: providers report input tokens only at completion, so exact mid-request values do not exist; the pre-dispatch bytes/4 estimate is too rough (base64 attachments) to show.
  • Unlocking /context mid-turn over the same query path — a free follow-up, kept out to stay small.
  • Desktop changes (already has this granularity).

Test plan

  • New unit tests tui-context-refresh.test.ts (9): event-set parity with desktop, debounce coalescing, out-of-order resolution guard, failed read keeps last value, cancel retires scheduled + in-flight queries, real-timer sanity.
  • New runner integration tests (2): ctx segment moves mid-turn while the turn is parked after tool_start (before any token_usage); a failing snapshot read leaves the segment untouched and silent.
  • Full maka-agent package suite: 732 passed, 0 failed (3 pre-existing skips); whole-repo typecheck green; biome lint/format clean; ASF header check green.

@github-actionsgithub-actionsBot added the effort/L Under 1000 readable lines label Sep 2, 2026
…quest (apache#4545)
The ctx segment only moved when the end-of-turn token_usage event landed,
so a long agentic turn burned context with the indicator frozen at the
previous turn's value. The Host already commits a latest-context snapshot
at every settled provider request (the desktop inspector's data source),
so pull it on the desktop's own signal: trace-relevant events schedule a
400ms-debounced getContextDiagnostics read, and the latest issued read
writes contextRemaining straight into the statusline usage.
- tui-context-refresh.ts: desktop's trace-relevant event set + a
restart-on-event debouncer whose revision guard lets only the latest
issued query apply; a failed read leaves the last value standing.
- pi-tui-runner.ts: observe() on the shared turn-drain onEvent (covers
user and Host-attached turns) and on resumeLatest; cancel on teardown;
stale-session guard drops pre-switch results. ctxRefreshTicker input
option injects the timer for tests.
Zero protocol/runtime changes: no new event type, no persistence or
billing semantics touched (apache#972). Turn-end token_usage stays the
authoritative persisted record.

@M4n5terM4n5ter left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed exact head 4be9222680c3a0fee115eb78d5ac567219c14516.

The new refresh lifecycle correctly coalesces settled provider-request signals, retires stale reads by revision, and fences session switches. I found one P2 display-coherence defect, detailed inline. It affects the accuracy of the context-pressure indicator but not execution or durable state, so I am approving with that follow-up comment.

The exact-head test check is green and the current-main merge result is clean.


Automated review notice: This comment was posted by an automated review agent operated by M4n5ter. It is not an independent human review and does not replace one.

return;
// Same formula the token_usage path uses (#1067), from the same
// settled request — the two cannot disagree.
state.usage.contextRemaining = Math.max(0, contextWindow - inputTokens);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Keep the diagnostics window with the remaining-token snapshot. This path reads one settled request's inputTokens and contextWindow, but stores only their difference. The statusline later subtracts that old remainder from the current mutable model-catalog window. I reproduced a settled 100k/200k snapshot followed by a catalog refresh to 500k: the UI renders ctx 400k/500k 80% instead of ctx 100k/200k 50%. Store and render the numerator/denominator from the same diagnostics snapshot, and add a regression where the diagnostics and catalog windows intentionally differ.


Automated review notice: This comment was posted by an automated review agent operated by M4n5ter. It is not an independent human review and does not replace one.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/LUnder 1000 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(cli): TUI statusline ctx segment should update per settled provider request, not just at turn end

2 participants

@me2seeks@M4n5ter
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

feat(cli): refresh the statusline ctx segment per settled provider request (#4545) - #4550

Open
me2seeks wants to merge 2 commits into
apache:mainfrom
me2seeks:feat/4545-live-ctx
Open

feat(cli): refresh the statusline ctx segment per settled provider request (#4545)#4550
me2seeks wants to merge 2 commits into
apache:mainfrom
me2seeks:feat/4545-live-ctx

Conversation

@me2seeks

Copy link
Copy Markdown
Contributor

Closes#4545.

Problem

The TUI statusline ctx used/window pct% segment only moved once per turn, when the end-of-turn token_usage event landed. During a long agentic turn — dozens of tool steps over minutes, exactly when the context grows fastest — the indicator sat frozen at the previous turn's value, hiding the signal that says "time to /compact or wrap up".

Approach

Reuse the desktop inspector's pull model instead of growing a parallel push event (design + audit: docs/tui-live-ctx-updates.md, 中文讲解 docs/tui-live-ctx-updates.zh-CN.md):

  • The Host already commits a latest-context snapshot at every settled provider request (provider-request-telemetry.ts), and context.diagnostics.query is a plain read with no busy gate — the desktop inspector refreshes from it mid-turn on trace-relevant events.
  • New packages/cli/src/tui-context-refresh.ts: the desktop trace-relevant event set (tool_start, tool_result, token_usage, …) + a restart-on-event debouncer (400 ms, same as desktop) whose revision guard lets only the latest issued query apply; a failed read leaves the last value standing.
  • pi-tui-runner.ts: observe() on the shared turn-drain onEvent (covers user-submitted and Host-attached turns alike) and on the resumeLatest loop; cancel() on teardown; a stale-session guard drops results that resolve after a switch. The query calls the driver directly — runControl's serial lock exists for mutations, and /context's mid-turn refusal is a TUI-local choice, not a protocol constraint.
  • The apply path uses the same contextRemaining = contextWindow − inputTokens formula as the token_usage path (fix(runtime): emit contextRemaining in token_usage events so the TUI ctx segment renders #1067), derived from the same settled request — the two cannot disagree. Turn-end token_usage stays the authoritative persisted record; this only enriches the live turn.

Zero protocol / runtime / persistence changes: no new event type, no billing semantics touched (#972).

Non-goals

  • Token-level updates during one streaming request: providers report input tokens only at completion, so exact mid-request values do not exist; the pre-dispatch bytes/4 estimate is too rough (base64 attachments) to show.
  • Unlocking /context mid-turn over the same query path — a free follow-up, kept out to stay small.
  • Desktop changes (already has this granularity).

Test plan

  • New unit tests tui-context-refresh.test.ts (9): event-set parity with desktop, debounce coalescing, out-of-order resolution guard, failed read keeps last value, cancel retires scheduled + in-flight queries, real-timer sanity.
  • New runner integration tests (2): ctx segment moves mid-turn while the turn is parked after tool_start (before any token_usage); a failing snapshot read leaves the segment untouched and silent.
  • Full maka-agent package suite: 732 passed, 0 failed (3 pre-existing skips); whole-repo typecheck green; biome lint/format clean; ASF header check green.

@github-actionsgithub-actionsBot added the effort/L Under 1000 readable lines label Sep 2, 2026
…quest (apache#4545)
The ctx segment only moved when the end-of-turn token_usage event landed,
so a long agentic turn burned context with the indicator frozen at the
previous turn's value. The Host already commits a latest-context snapshot
at every settled provider request (the desktop inspector's data source),
so pull it on the desktop's own signal: trace-relevant events schedule a
400ms-debounced getContextDiagnostics read, and the latest issued read
writes contextRemaining straight into the statusline usage.
- tui-context-refresh.ts: desktop's trace-relevant event set + a
restart-on-event debouncer whose revision guard lets only the latest
issued query apply; a failed read leaves the last value standing.
- pi-tui-runner.ts: observe() on the shared turn-drain onEvent (covers
user and Host-attached turns) and on resumeLatest; cancel on teardown;
stale-session guard drops pre-switch results. ctxRefreshTicker input
option injects the timer for tests.
Zero protocol/runtime changes: no new event type, no persistence or
billing semantics touched (apache#972). Turn-end token_usage stays the
authoritative persisted record.

@M4n5terM4n5ter left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed exact head 4be9222680c3a0fee115eb78d5ac567219c14516.

The new refresh lifecycle correctly coalesces settled provider-request signals, retires stale reads by revision, and fences session switches. I found one P2 display-coherence defect, detailed inline. It affects the accuracy of the context-pressure indicator but not execution or durable state, so I am approving with that follow-up comment.

The exact-head test check is green and the current-main merge result is clean.


Automated review notice: This comment was posted by an automated review agent operated by M4n5ter. It is not an independent human review and does not replace one.

return;
// Same formula the token_usage path uses (#1067), from the same
// settled request — the two cannot disagree.
state.usage.contextRemaining = Math.max(0, contextWindow - inputTokens);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Keep the diagnostics window with the remaining-token snapshot. This path reads one settled request's inputTokens and contextWindow, but stores only their difference. The statusline later subtracts that old remainder from the current mutable model-catalog window. I reproduced a settled 100k/200k snapshot followed by a catalog refresh to 500k: the UI renders ctx 400k/500k 80% instead of ctx 100k/200k 50%. Store and render the numerator/denominator from the same diagnostics snapshot, and add a regression where the diagnostics and catalog windows intentionally differ.


Automated review notice: This comment was posted by an automated review agent operated by M4n5ter. It is not an independent human review and does not replace one.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/LUnder 1000 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(cli): TUI statusline ctx segment should update per settled provider request, not just at turn end

2 participants

@me2seeks@M4n5ter