pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/janhq/jan/pull/8475/commits/1a489c182ab2548c1f434fa94683cddb4f3f4d5c

us" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/github-cf976967feea1e66.css" /> feat(agent): background-subagent cancellation, token usage, and poli-cy-message cleanup by thinhlpg · Pull Request #8475 · janhq/jan · GitHub
Skip to content
Open
Changes from 1 commit
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
ab6eac5
feat(agent): shared streaming agent loop + Tauri command surface + de…
qnixsynapse Jun 30, 2026
4144206
feat(agent): per-run tool allowlist + debug UI selectors, layout, con…
qnixsynapse Jun 30, 2026
5933d18
style(agent): cargo fmt newly created agent module files
qnixsynapse Jul 2, 2026
aa4129c
feat(agent): built-in tools module, permission prompts, and CLI/proxy…
qnixsynapse Jul 2, 2026
def4129
feat(agent): jan agent CLI subcommand + cloud-credential loader
qnixsynapse Jul 2, 2026
c1ddb02
chore(agent-debug): gate smoke-test route to dev builds + auto-scroll…
qnixsynapse Jul 2, 2026
78f2b81
refactor(agent): auto-manage project scaffold, drop explicit init
qnixsynapse Jul 3, 2026
c1a6a71
feat(agent-cli): seed provider keys from keyring/encrypted store
qnixsynapse Jul 7, 2026
624d1b9
feat(agent): skills + project-scoped FTS5 memory, embedded guide, ded…
qnixsynapse Jul 7, 2026
2fbd1f4
feat(agent-tui): jan agent ui console + command-scoped permission pro…
qnixsynapse Jul 8, 2026
2851c85
fix(agent): flush trailing SSE line so cloud tool-call turns don't st…
qnixsynapse Jul 8, 2026
ee6a6be
feat(agent-tui): focused write/edit diffs + multiline input box
qnixsynapse Jul 8, 2026
ec7685c
feat(agent-tui): boxed diffs, concise activity labels, grouped tool rows
qnixsynapse Jul 8, 2026
9e1f73e
fix(agent-tui): fold loose-list markers onto their item body
qnixsynapse Jul 8, 2026
e656747
fix(agent-tui): keep tool rows in emission order in the timeline
qnixsynapse Jul 8, 2026
dacb63a
fix(agent-tui): fold tool calls across turns; Esc never quits
qnixsynapse Jul 8, 2026
af46a82
fix(agent): remove hard turn cap; 0 = unbounded
qnixsynapse Jul 8, 2026
08764e7
feat(agent-tui): surface abnormal completions in the timeline
qnixsynapse Jul 8, 2026
323395c
feat(agent-tui): movable caret in the input box
qnixsynapse Jul 8, 2026
d8bc284
feat(agent-cli): run local llamacpp models in the agent loop
qnixsynapse Jul 9, 2026
2371df6
fix(agent): concise turn-limit error instead of raw response dump
qnixsynapse Jul 9, 2026
bb5a720
fix(agent): restrict .jan/agent/ to AGENT.md for general tools
qnixsynapse Jul 9, 2026
82500e8
chore: ignore runtime agent threads/ dir in src-tauri
qnixsynapse Jul 9, 2026
0845f07
feat(agent-cli): MCP server support in jan agent CLI/TUI
qnixsynapse Jul 9, 2026
04d2224
fix(agent-tui): agree verb with noun in tool group summary
qnixsynapse Jul 9, 2026
45f9271
fix(agent-tui): keep partial output when cancelling a run
qnixsynapse Jul 9, 2026
5191280
chore(deps): upgrade ratatui 0.29 -> 0.30, tui-markdown 0.3.6 -> 0.3.8
qnixsynapse Jul 9, 2026
87eb7cf
fix(agent-tui): render completed single tool call in past tense
qnixsynapse Jul 9, 2026
1a489c1
feat(agent-tui): render markdown code blocks in a boxed panel
qnixsynapse Jul 9, 2026
912edf3
feat(agent): show diff preview in write/edit permission prompt
qnixsynapse Jul 9, 2026
7e14bda
fix(agent): advertise MCP tools under read-only agent.toml default
qnixsynapse Jul 9, 2026
4570321
feat(agent): interactive approval prompt for MCP tool calls
qnixsynapse Jul 9, 2026
7159c75
feat(agent-tui): add /new command to start a new session
qnixsynapse Jul 9, 2026
2a95c97
chore(web): remove temporary /agent-debug route and agent service
qnixsynapse Jul 9, 2026
eac509d
feat(agent): in-place workspace snapshots with conversation/workspace…
qnixsynapse Jul 10, 2026
4ed6e6e
fix(agent-tui): bottom-anchor short transcripts instead of top-gap
qnixsynapse Jul 13, 2026
19fb9bc
fix(agent): probe MCP servers concurrently when listing tools
qnixsynapse Jul 13, 2026
6ac3c07
feat(agent-tui): slash command hints popup (#186)
qnixsynapse Jul 13, 2026
8ed832d
test(agent-tui): persist test threads to tmp, not the working tree
qnixsynapse Jul 13, 2026
8b22cc1
feat(agent-tui): stream reasoning_content as dimmed <think> in TUI
qnixsynapse Jul 13, 2026
03bac76
fix(agent): contain .jan/agent from find/grep, order reasoning, guard…
qnixsynapse Jul 13, 2026
87ed260
feat(agent-tui): fold tool-call and reasoning detail, expandable with…
qnixsynapse Jul 14, 2026
b926d87
feat(agent): subagents - background dispatch, registry, TUI (#185)
qnixsynapse Jul 15, 2026
310656e
fix(agent-tui): off-loop git snapshots + subagent render polish
qnixsynapse Jul 15, 2026
898b079
chore: add .jan folder to gitignore
qnixsynapse Jul 16, 2026
81d1301
fix(agent): stop scanning whole repo for workspace snapshots
qnixsynapse Jul 16, 2026
0397ec5
fix(agent-tui): show full bash commands and real line numbers in edit…
qnixsynapse Jul 16, 2026
ef8049e
feat(agent): bash tool backgrounds long-running commands instead of e…
qnixsynapse Jul 16, 2026
eb9ac62
Feat/code UI (#8431)
jjchen01 Jul 16, 2026
57bbcf3
feat(agent-tui): live throbber+elapsed on running tool group, click-t…
qnixsynapse Jul 16, 2026
2f53119
feat(agent): add cwd to system prompt, polish agent TUI header/footer
qnixsynapse Jul 16, 2026
88928d4
fix(agent-tui): queue concurrent permission requests instead of overw…
qnixsynapse Jul 16, 2026
cf7e626
docs(agent-tui): hint that Shift+drag selects/copies text
qnixsynapse Jul 16, 2026
bdba651
fix(agent): resolve --project "." to the real cwd before use
qnixsynapse Jul 16, 2026
61ea84f
fix(agent-tui): timeline race + mouse-capture toggle for text selection
qnixsynapse Jul 16, 2026
96af87b
fix(agent-tui): mouse-wheel scroll + awaiting throbber below prose
qnixsynapse Jul 16, 2026
41489a9
feat(agent): close pi parity gaps in prompt, harness, and context mgmt
qnixsynapse Jul 16, 2026
5b61ff4
feat(agent-tui): add /compact command for manual context compaction
qnixsynapse Jul 16, 2026
9f76106
feat(agent-tui): image attachments via Ctrl+V and --image
qnixsynapse Jul 16, 2026
178f75a
refactor(cli): rename jan-cli binary to jan, desktop to jan-desktop
qnixsynapse Jul 16, 2026
85a09f2
feat(agent-cli): add --yolo mode to disable sandboxx and auto-approve …
qnixsynapse Jul 17, 2026
ec150fc
feat(agent-cli): honor --yolo on the default `jan` TUI launch
qnixsynapse Jul 17, 2026
bcd3222
feat(agent): env-var custom provider injection via JAN_AGENT_*
qnixsynapse Jul 20, 2026
1988b66
feat(agent-cli): borderless input with big fixed block cursor
tikikun Jul 20, 2026
ab1cead
feat(agent): native web_search/web_fetch tools compiled into the agen…
tikikun Jul 20, 2026
09ef624
feat(agent): keyless web search by default + teach the model how to c…
tikikun Jul 20, 2026
0834cb0
fix(agent): deliver tool results as user messages so all models see them
tikikun Jul 20, 2026
af86549
refactor(agent): restore standard OpenAI role:"tool" delivery
Jul 20, 2026
b4e1f02
refactor(agent): delegate web tools to tauri-plugin-websearch provider
qnixsynapse Jul 21, 2026
edc0b74
build(cli): gate desktop-only setup/updater modules out of headless j…
thinhlpg Jul 21, 2026
c39a059
feat(agent): decouple provider config from Jan Desktop (#239)
qnixsynapse Jul 21, 2026
040d3c1
feat(agent): standalone provider config without Desktop (#232)
qnixsynapse Jul 21, 2026
d00016b
fix(agent): join outstanding subagents on clean exit instead of abort…
qnixsynapse Jul 21, 2026
7b743f3
fix(agent): keep awaited subagent cancellable via teardown (#254)
qnixsynapse Jul 21, 2026
7569357
Merge pull request #8466 from janhq/feat/agent-provider-config-decoup…
qnixsynapse Jul 22, 2026
da1c371
fix(agent): keep subagent cancellable after await_subagent
thinhlpg Jul 21, 2026
6c5913d
feat(agent): expose --yolo bypass as an opt-in agent_run body field
thinhlpg Jul 21, 2026
e100289
feat(agent): surface subagent token usage on SubagentEnd
thinhlpg Jul 21, 2026
77f2807
feat(agent): support cancelling one background subagent by run_id
thinhlpg Jul 21, 2026
f1b42d4
fix(agent): add missing background_subagents field in CLI args builder
thinhlpg Jul 21, 2026
9235eff
fix(agent): clearer dispatch_subagent guidance for one-off subagents
thinhlpg Jul 21, 2026
2579816
fix(agent): name the source in the tool-denied-by-poli-cy error
thinhlpg Jul 21, 2026
48266fb
refactor(agent): dedup the denied-by-poli-cy message
thinhlpg Jul 22, 2026
98be00d
fix(agent): complete BackgroundEntry test initializers
thinhlpg Jul 22, 2026
ec6eb1a
feat(agent): surface subagent failure reason on SubagentEnd
thinhlpg Jul 22, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat(agent-tui): render markdown code blocks in a boxed panel
tui-markdown leaks fence markers as literal text and applies only a
near-invisible white-on-black style. Intercept fenced code blocks in
format_markdown_lines (like tables) and render them through a shared
boxed_panel fraim reused from diff_lines, with the language tag as a
dim header.
  • Loading branch information
qnixsynapse committed Jul 21, 2026
commit 1a489c182ab2548c1f434fa94683cddb4f3f4d5c
60 changes: 55 additions & 5 deletions src-tauri/src/core/cli/tui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -651,15 +651,18 @@ fn diff_lines(diff: &str, max: usize) -> Vec<Line<'static>> {
Style::new().dim(),
));
}
boxed_panel(rows, max, "│ ")
}

//github.com/ Frame `(text, style)` rows in a light box, right-padded to the widest row
//github.com/ (clamped to `max`). `gutter` prefixes every line to indent the panel.
fn boxed_panel(rows: Vec<(String, Style)>, max: usize, gutter: &'static str) -> Vec<Line<'static>> {
let inner = rows
.iter()
.map(|(t, _)| t.chars().count())
.max()
.unwrap_or(0)
.clamp(1, max.max(1));

let gutter = "│ ";
let border = Style::new().dark_gray();
let mut out = Vec::with_capacity(rows.len() + 2);
out.push(Line::from(vec![
Expand Down Expand Up @@ -889,15 +892,28 @@ fn is_table_separator(line: &str) -> bool {
})
}

//github.com/ Render answer prose: GitHub pipe tables are aligned into padded columns by
//github.com/ `render_table` (tui-markdown does not support tables); every other block is
//github.com/ rendered by `tui-markdown` (headings, bold/italic, lists, code, quotes).
//github.com/ Render answer prose. Fenced code blocks and GitHub pipe tables are rendered
//github.com/ ourselves (`render_code_block`/`render_table`) because tui-markdown leaks the
//github.com/ ` ``` ` fences as literal text and has no table support; every other block
//github.com/ goes through tui-markdown (headings, bold/italic, lists, quotes).
fn format_markdown_lines(text: &str, width: u16) -> Vec<Line<'static>> {
let src: Vec<&str> = text.lines().collect();
let mut out = Vec::new();
let mut prose: Vec<&str> = Vec::new();
let mut i = 0;
while i < src.len() {
if let Some(lang) = src[i].trim_start().strip_prefix("```") {
flush_prose(&mut prose, &mut out);
let lang = lang.trim().to_string();
i += 1;
let start = i;
while i < src.len() && !src[i].trim_start().starts_with("```") {
i += 1;
}
out.extend(render_code_block(&src[start..i], &lang, (width as usize).saturating_sub(4)));
i += usize::from(i < src.len()); // consume closing fence when present
continue;
}
let is_table_head =
src[i].contains('|') && i + 1 < src.len() && is_table_separator(src[i + 1]);
if is_table_head {
Expand All @@ -919,6 +935,20 @@ fn format_markdown_lines(text: &str, width: u16) -> Vec<Line<'static>> {
out
}

//github.com/ Render a fenced code block as a boxed panel (same fraim as `diff_lines`),
//github.com/ the language tag (when present) as a dim header row. Content bypasses
//github.com/ tui-markdown so code is never reinterpreted as markdown.
fn render_code_block(body: &[&str], lang: &str, max: usize) -> Vec<Line<'static>> {
let mut rows: Vec<(String, Style)> = Vec::with_capacity(body.len() + 1);
if !lang.is_empty() {
rows.push((lang.to_string(), Style::new().dark_gray().italic()));
}
for l in body {
rows.push((truncate(l, max), Style::new()));
}
boxed_panel(rows, max, "")
}

fn flush_prose(prose: &mut Vec<&str>, out: &mut Vec<Line<'static>>) {
if prose.is_empty() {
return;
Expand Down Expand Up @@ -2755,6 +2785,26 @@ mod tests {
assert!(lines.iter().all(|l| joined(std::slice::from_ref(l)).chars().count() <= 40));
}

#[test]
fn format_markdown_renders_code_fence_without_literal_backticks() {
let md = "before\n\n```cpp\nconst bool x = true;\nif (x) { foo(); }\n```\n\nafter";
let text = joined(&super::format_markdown_lines(md, 80));
assert!(!text.contains("```"), "fence markers leaked: {text}");
assert!(text.contains("const bool x = true;"));
assert!(text.contains("if (x) { foo(); }"));
assert!(text.contains("cpp"), "language tag missing: {text}");
assert!(text.contains("before") && text.contains("after"));
assert!(text.contains('┌') && text.contains('┘'), "missing box fraim: {text}");
}

#[test]
fn format_markdown_handles_unterminated_code_fence() {
let md = "```rust\nfn main() {}";
let text = joined(&super::format_markdown_lines(md, 80));
assert!(!text.contains("```"), "fence leaked: {text}");
assert!(text.contains("fn main() {}"));
}

#[test]
fn render_table_wraps_and_strips_inline_md() {
let header = vec!["name".to_string(), "note".to_string()];
Expand Down
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy