-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathls.rs
More file actions
115 lines (102 loc) · 3.75 KB
/
Copy pathls.rs
File metadata and controls
115 lines (102 loc) · 3.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// Copyright (c) 2026 vectorless developers
// SPDX-License-Identifier: Apache-2.0
//! `ls` — list children of the current node.
use crate::agent::config::DocContext;
use crate::agent::state::WorkerState;
use super::super::ToolResult;
/// Execute `ls` — list children of the current node.
pub fn ls(ctx: &DocContext, state: &WorkerState) -> ToolResult {
let mut output = String::new();
if let Some(entry) = ctx.nav_entry(state.current_node) {
output.push_str(&format!("Current section: {}\n", entry.overview));
if !entry.question_hints.is_empty() {
output.push_str(&format!(
"Can answer: {}\n",
entry.question_hints.join(", ")
));
}
output.push('\n');
}
match ctx.ls(state.current_node) {
Some(routes) => {
if routes.is_empty() {
output
.push_str("(leaf node — no children)\nUse cd .. to go back or done to finish.");
return ToolResult::ok(output);
}
for (i, route) in routes.iter().enumerate() {
output.push_str(&format!(
"[{}] {} — {} ({} leaves)",
i + 1,
route.title,
route.description,
route.leaf_count
));
if let Some(nav) = ctx.nav_entry(route.node_id) {
if !nav.question_hints.is_empty() {
output.push_str(&format!(
"\n Can answer: {}",
nav.question_hints.join(", ")
));
}
if !nav.topic_tags.is_empty() {
output.push_str(&format!("\n Topics: {}", nav.topic_tags.join(", ")));
}
}
output.push('\n');
}
ToolResult::ok(output)
}
None => {
output.push_str(
"(no navigation data for this node)\nUse cat to read content or cd .. to go back.",
);
ToolResult::ok(output)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::document::{ChildRoute, DocumentTree, NavigationIndex, NodeId};
fn build_test_tree() -> (DocumentTree, NavigationIndex, NodeId, NodeId, NodeId) {
let mut tree = DocumentTree::new("Root", "root content");
let root = tree.root();
let c1 = tree.add_child(root, "Getting Started", "gs content");
let c2 = tree.add_child(root, "API Reference", "api content");
let mut nav = NavigationIndex::new();
nav.add_child_routes(
root,
vec![
ChildRoute {
node_id: c1,
title: "Getting Started".to_string(),
description: "Setup guide".to_string(),
leaf_count: 3,
},
ChildRoute {
node_id: c2,
title: "API Reference".to_string(),
description: "API docs".to_string(),
leaf_count: 7,
},
],
);
(tree, nav, root, c1, c2)
}
#[test]
fn test_ls_shows_children() {
let (tree, nav, root, _, _) = build_test_tree();
let ctx = DocContext {
tree: &tree,
nav_index: &nav,
reasoning_index: &crate::document::ReasoningIndex::default(),
doc_name: "test",
};
let state = WorkerState::new(root, 8);
let result = ls(&ctx, &state);
assert!(result.success);
assert!(result.feedback.contains("Getting Started"));
assert!(result.feedback.contains("API Reference"));
}
}