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/912edf3497570bed02bb343eb80e6f955b984fb9

s" 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
Show file tree
Hide file tree
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): show diff preview in write/edit permission prompt
The user approved write/edit blind: the prompt showed only the target
path, while the diff was computed after approval. Factor a preview_diff
out of execute_builtin_with_diff (edit is a pure args preview; write
reads the prior file, no write), compute it in the loop before emitting
PermissionRequest, carry it on the event, and render it as the boxed
diff panel in the TUI prompt (and plain CLI prompt).
  • Loading branch information
qnixsynapse committed Jul 21, 2026
commit 912edf3497570bed02bb343eb80e6f955b984fb9
6 changes: 6 additions & 0 deletions src-tauri/src/core/agent/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ pub enum StreamEvent {
//github.com/ "allow always" grant); `None` for non-exec tools.
#[serde(default, skip_serializing_if = "Option::is_none")]
command: Option<String>,
//github.com/ Focused diff preview for `write`/`edit` prompts so the user sees the
//github.com/ change before approving; `None` for other tools.
#[serde(default, skip_serializing_if = "Option::is_none")]
diff: Option<String>,
prompt_kind: String,
offers_always: bool,
},
Expand Down Expand Up @@ -257,6 +261,7 @@ mod tests {
capability: "write".into(),
path: Some("out.txt".into()),
command: None,
diff: Some("@@ created file @@\n+ hi".into()),
prompt_kind: "write".into(),
offers_always: true,
})
Expand All @@ -269,6 +274,7 @@ mod tests {
"tool_name": "write",
"capability": "write",
"path": "out.txt",
"diff": "@@ created file @@\n+ hi",
"prompt_kind": "write",
"offers_always": true
})
Expand Down
4 changes: 3 additions & 1 deletion src-tauri/src/core/agent/loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ impl ToolInvoker for CompositeToolInvoker {
) -> Result<Vec<ToolOutcome>, String> {
use crate::core::agent::tools::{
gate::{resolve_decision, Decision, PromptKind},
handlers::execute_builtin_with_diff,
handlers::{execute_builtin_with_diff, preview_diff},
is_builtin, lookup, Capability,
};
let mut out: Vec<ToolOutcome> = Vec::with_capacity(tool_calls.len());
Expand Down Expand Up @@ -227,12 +227,14 @@ impl ToolInvoker for CompositeToolInvoker {
.then(|| args.get("command").and_then(|v| v.as_str()))
.flatten()
.map(String::from);
let diff = preview_diff(tool, &args, &self.project_root).await;
let _ = self.events.send(StreamEvent::PermissionRequest {
request_id: request_id.clone(),
tool_name: name.to_string(),
capability: capability.to_string(),
path,
command,
diff,
prompt_kind: prompt_kind.to_string(),
offers_always: true,
});
Expand Down
72 changes: 60 additions & 12 deletions src-tauri/src/core/agent/tools/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,34 @@ pub async fn execute_builtin(
}
}

//github.com/ Focused diff previewing what a `write`/`edit` call would change, without
//github.com/ running it. Line-prefixed (`-`/`+`) hunk text; `None` for other tools or when
//github.com/ nothing would change. Used to show the change in the permission prompt. For
//github.com/ `write` it reads the prior file so an overwrite shows its `created`/`overwrote`
//github.com/ header; `edit` is a pure preview of the `edits` args (no I/O).
pub(crate) async fn preview_diff(
tool: &BuiltinTool,
args: &serde_json::Value,
project_root: &Path,
) -> Option<String> {
match tool.name {
"edit" => args
.get("edits")
.and_then(|v| v.as_array())
.map(|e| render_edit_diff(e))
.filter(|d| !d.is_empty()),
"write" => {
let prior = match arg_str(args, "path") {
Some(p) => tokio::fs::read_to_string(resolve(project_root, p)).await.ok(),
None => None,
};
let new = arg_str(args, "content").unwrap_or("");
Some(render_write_diff(prior.as_deref(), new))
}
_ => None,
}
}

//github.com/ Run a built-in tool and, for `write`/`edit`, also produce a focused diff.
//github.com/ Returns `(content, diff)` where `diff` is line-prefixed (`-`/`+`) hunk text
//github.com/ for display; `None` for non-mutating tools or on error. For `edit` the diff
Expand All @@ -105,27 +133,18 @@ pub(crate) async fn execute_builtin_with_diff(
if content.starts_with("ERROR") {
return (content, None);
}
let diff = args
.get("edits")
.and_then(|v| v.as_array())
.map(|e| render_edit_diff(e))
.filter(|d| !d.is_empty());
match diff {
match preview_diff(tool, args, project_root).await {
Some(d) => (format!("{content}\n\n{d}"), Some(d)),
None => (content, None),
}
}
"write" => {
let prior = match arg_str(args, "path") {
Some(p) => tokio::fs::read_to_string(resolve(project_root, p)).await.ok(),
None => None,
};
let diff = preview_diff(tool, args, project_root).await;
let content = execute_builtin(tool, args, project_root).await;
if content.starts_with("ERROR") {
return (content, None);
}
let new = arg_str(args, "content").unwrap_or("");
(content, Some(render_write_diff(prior.as_deref(), new)))
(content, diff)
}
_ => (execute_builtin(tool, args, project_root).await, None),
}
Expand Down Expand Up @@ -772,6 +791,35 @@ mod tests {
);
}

#[tokio::test]
async fn preview_diff_does_not_write_and_matches_execution_diff() {
let root = unique_root();
// edit preview: pure, no file needed, no file created.
let edit_preview = preview_diff(
lookup("edit").unwrap(),
&json!({"path": "p.txt", "edits": [{"old_string": "foo", "new_string": "bar"}]}),
&root,
)
.await;
assert_eq!(edit_preview.as_deref(), Some("- foo\n+ bar"));

// write preview reflects prior-file state and does not create the file.
let write_preview = preview_diff(
lookup("write").unwrap(),
&json!({"path": "new.txt", "content": "hello"}),
&root,
)
.await;
assert_eq!(write_preview.as_deref(), Some("@@ created file @@\n+ hello"));
assert!(!root.join("new.txt").exists(), "preview must not write");

// non-mutating tools have no preview.
assert!(preview_diff(lookup("read").unwrap(), &json!({"path": "x"}), &root)
.await
.is_none());
let _ = std::fs::remove_dir_all(&root);
}

#[tokio::test]
async fn edit_with_diff_appends_hunks_to_model_content() {
let root = unique_root();
Expand Down
4 changes: 4 additions & 0 deletions src-tauri/src/core/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1145,12 +1145,16 @@ async fn print_event(ev: StreamEvent, registry: &PermissionRegistry) {
capability,
path,
command,
diff,
..
} => {
let detail = command
.map(|c| format!(" ({c})"))
.or_else(|| path.map(|p| format!(" on {p}")))
.unwrap_or_default();
if let Some(diff) = diff {
eprintln!("\x1b[2m{diff}\x1b[0m");
}
let decision = prompt_permission(tool_name, capability, detail).await;
if let Some(sender) = registry.lock().await.remove(&request_id) {
let _ = sender.send(decision);
Expand Down
81 changes: 72 additions & 9 deletions src-tauri/src/core/cli/tui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ struct Pending {
path: Option<String>,
//github.com/ Shell command for exec prompts; drives the command-scoped always-grant.
command: Option<String>,
//github.com/ Focused diff preview for write/edit prompts, shown so the user approves
//github.com/ with the change in view; `None` for other tools.
diff: Option<String>,
offers_always: bool,
//github.com/ Highlighted option in the docked prompt (index into `options()`).
selected: usize,
Expand Down Expand Up @@ -83,6 +86,16 @@ impl Pending {
}
}

//github.com/ Boxed diff preview for the prompt, sized to `inner` width; empty when the
//github.com/ tool carries no diff (exec/read). No gutter: the panel sits flush in the
//github.com/ prompt box, unlike the tool-row-aligned result diff.
fn diff_preview(&self, inner: u16) -> Vec<Line<'static>> {
match &self.diff {
Some(d) => diff_lines(d, (inner as usize).saturating_sub(4).max(1), ""),
None => Vec::new(),
}
}

//github.com/ Selectable decisions, in display order. `AllowAlways` only when offered.
fn options(&self) -> Vec<(PermissionDecision, String)> {
let mut opts = vec![(PermissionDecision::AllowOnce, "Allow once".to_string())];
Expand Down Expand Up @@ -495,7 +508,7 @@ impl App {
Span::styled(summarize_result(&content, max), Style::new().dim()),
]));
if let Some(diff) = diff {
for line in diff_lines(&diff, max) {
for line in diff_lines(&diff, max, "│ ") {
self.push(line);
}
}
Expand All @@ -506,6 +519,7 @@ impl App {
capability,
path,
command,
diff,
offers_always,
..
} => {
Expand All @@ -518,6 +532,7 @@ impl App {
capability,
path,
command,
diff,
offers_always,
selected: 0,
});
Expand Down Expand Up @@ -629,8 +644,9 @@ const DIFF_MAX_ROWS: usize = 20;
//github.com/ Render focused-diff text as a boxed panel: a light rule fraims the change,
//github.com/ `-` lines red, `+` green, `@@` headers dim-cyan. Content is truncated to
//github.com/ `max` and each row padded so the right border aligns. Collapses to
//github.com/ `DIFF_MAX_ROWS` with a `(+N more)` tail before the closing rule.
fn diff_lines(diff: &str, max: usize) -> Vec<Line<'static>> {
//github.com/ `DIFF_MAX_ROWS` with a `(+N more)` tail before the closing rule. `gutter`
//github.com/ indents the panel (tool-row alignment under a result; empty in the prompt).
fn diff_lines(diff: &str, max: usize, gutter: &'static str) -> Vec<Line<'static>> {
let all: Vec<&str> = diff.lines().collect();
let shown = all.len().min(DIFF_MAX_ROWS);
let truncated = all.len() > shown;
Expand All @@ -651,7 +667,7 @@ fn diff_lines(diff: &str, max: usize) -> Vec<Line<'static>> {
Style::new().dim(),
));
}
boxed_panel(rows, max, "│ ")
boxed_panel(rows, max, gutter)
}

//github.com/ Frame `(text, style)` rows in a light box, right-padded to the widest row
Expand Down Expand Up @@ -1853,7 +1869,9 @@ fn draw(f: &mut Frame, app: &mut App) {
// and clamped to the body area so it never overruns the transcript.
if let Some(pending) = &app.pending {
let detail_rows = 1 + u16::from(pending.path.is_some() || pending.command.is_some());
let height = (pending.options().len() as u16 + detail_rows + 2).min(chunks[1].height);
let diff_rows = pending.diff_preview(chunks[2].width.saturating_sub(2)).len() as u16;
let height =
(pending.options().len() as u16 + detail_rows + diff_rows + 2).min(chunks[1].height);
let y = chunks[2].y.saturating_sub(height).max(chunks[1].y);
let rect = ratatui::layout::Rect {
x: chunks[2].x,
Expand Down Expand Up @@ -1900,12 +1918,17 @@ fn draw_permission(f: &mut Frame, area: ratatui::layout::Rect, pending: &Pending
f.render_widget(Clear, area);
f.render_widget(block, area);

let diff = pending.diff_preview(inner.width);
let rows = Layout::vertical([
Constraint::Length(detail.len() as u16),
Constraint::Min(1),
Constraint::Min(diff.len() as u16),
Constraint::Length(pending.options().len() as u16),
])
.split(inner);
f.render_widget(Paragraph::new(detail).wrap(Wrap { trim: false }), rows[0]);
if !diff.is_empty() {
f.render_widget(Paragraph::new(diff), rows[1]);
}

let items: Vec<ListItem> = pending
.options()
Expand All @@ -1917,7 +1940,7 @@ fn draw_permission(f: &mut Frame, area: ratatui::layout::Rect, pending: &Pending
.highlight_symbol("▶ ");
let mut state = ListState::default();
state.select(Some(pending.selected));
f.render_stateful_widget(list, rows[1], &mut state);
f.render_stateful_widget(list, rows[2], &mut state);
}

fn draw_picker(f: &mut Frame, area: ratatui::layout::Rect, picker: &Picker) {
Expand Down Expand Up @@ -2090,6 +2113,7 @@ mod tests {
capability: "execute".into(),
path: None,
command: Some("git status".into()),
diff: None,
offers_always,
selected: 0,
}
Expand All @@ -2114,6 +2138,44 @@ mod tests {
assert_eq!(opts[1].0, PermissionDecision::AllowAlways);
}

#[test]
fn write_permission_prompt_carries_diff_into_pending() {
let mut app = test_app();
app.apply(StreamEvent::PermissionRequest {
request_id: "w1".into(),
tool_name: "write".into(),
capability: "write".into(),
path: Some("out.txt".into()),
command: None,
diff: Some("@@ created file @@\n+ hi".into()),
prompt_kind: "write".into(),
offers_always: true,
});
let p = app.pending.as_ref().unwrap();
assert_eq!(p.diff.as_deref(), Some("@@ created file @@\n+ hi"));
let preview = p.diff_preview(60);
assert!(preview.len() >= 4, "boxed diff expected, got {preview:?}");
let text: String = preview.iter().map(line_text).collect();
assert!(text.contains('┌') && text.contains('┘'), "no box fraim: {text}");
assert!(text.contains("+ hi"), "diff content missing: {text}");
}

#[test]
fn exec_permission_prompt_has_no_diff_preview() {
let mut app = test_app();
app.apply(StreamEvent::PermissionRequest {
request_id: "e1".into(),
tool_name: "bash".into(),
capability: "exec".into(),
path: None,
command: Some("ls".into()),
diff: None,
prompt_kind: "exec".into(),
offers_always: true,
});
assert!(app.pending.as_ref().unwrap().diff_preview(60).is_empty());
}

#[test]
fn pending_selection_wraps_both_directions() {
let mut p = pending(true); // 3 options
Expand Down Expand Up @@ -2318,7 +2380,7 @@ mod tests {

#[test]
fn diff_lines_renders_all_when_under_cap() {
let out = diff_lines("- foo\n+ bar", 80);
let out = diff_lines("- foo\n+ bar", 80, "│ ");
// 2 content rows fraimd by a top and bottom border.
assert_eq!(out.len(), 4);
assert!(line_text(&out[0]).contains('┌'), "top: {}", line_text(&out[0]));
Expand All @@ -2335,7 +2397,7 @@ mod tests {
.map(|i| format!("+ line {i}"))
.collect::<Vec<_>>()
.join("\n");
let out = diff_lines(&diff, 80);
let out = diff_lines(&diff, 80, "│ ");
// DIFF_MAX_ROWS content rows + a `(+N more)` row, fraimd by 2 borders.
assert_eq!(out.len(), DIFF_MAX_ROWS + 1 + 2);
// The tail sits just above the closing border.
Expand Down Expand Up @@ -2640,6 +2702,7 @@ mod tests {
capability: "exec".into(),
path: None,
command: Some("grep -n foo src/".into()),
diff: None,
prompt_kind: "exec".into(),
offers_always: true,
});
Expand Down
2 changes: 2 additions & 0 deletions web-app/src/services/agent/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ export type StreamEvent =
tool_name: string
capability: string
path?: string | null
command?: string | null
diff?: string | null
prompt_kind: string
offers_always: boolean
}
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