list_files with_metadata mode, deeper JSON outline, MCP connector descriptions in prompt
Nightly Build / build (push) Has been cancelled

- list_files: new with_metadata parameter returns {path, line_count?, size}
  per entry (both disk and memory-docs) so the agent can spot large files
  worth outlining before reading
- ast_outline: replaced flat tree-sitter JSON walker with a recursive one
  that shows nested keys at every depth, with inline scalar values and
  container summaries
- message_builder: format active MCP connectors as a table with description
  instead of a bare bullet list
- read_file description now hints to use get_ast_outline first
- tools.md: agent guidance to outline before reading
This commit is contained in:
2026-07-22 22:32:43 +01:00
parent e71990347d
commit 7769b6689d
6 changed files with 325 additions and 19 deletions
+31
View File
@@ -34,6 +34,16 @@ pub struct MemoryHit {
pub snippet: String,
}
/// A directory listing row carrying cheap size metadata. `line_count` and
/// `byte_len` are computed in SQL (`LENGTH` / newline count) so the note body
/// never leaves the database.
#[derive(Debug, Clone, sqlx::FromRow)]
pub struct MemoryEntryMeta {
pub path: String,
pub line_count: i64,
pub byte_len: i64,
}
const SELECT: &str = "SELECT id, path, content, created_at, updated_at FROM memory_docs";
/// Fetch one note by its exact path.
@@ -84,6 +94,27 @@ pub async fn list(pool: &SqlitePool, prefix: &str) -> Result<Vec<MemoryEntry>> {
Ok(rows)
}
/// Like [`list`], but each row also carries a line count and byte length,
/// computed in SQL so the body is never transferred. Line count matches the
/// on-disk convention: an empty note is 0 lines, otherwise newline-count + 1.
pub async fn list_with_metadata(pool: &SqlitePool, prefix: &str) -> Result<Vec<MemoryEntryMeta>> {
let pattern = format!("{}%", escape_like(prefix));
let rows = sqlx::query_as::<_, MemoryEntryMeta>(
"SELECT path,
CASE WHEN content = '' THEN 0
ELSE LENGTH(content) - LENGTH(REPLACE(content, char(10), '')) + 1
END AS line_count,
LENGTH(CAST(content AS BLOB)) AS byte_len
FROM memory_docs
WHERE path LIKE ? ESCAPE '\\'
ORDER BY updated_at DESC",
)
.bind(pattern)
.fetch_all(pool)
.await?;
Ok(rows)
}
/// Full-text search over note bodies and paths, best match first. `query` is
/// FTS5 MATCH syntax; `snippet` is a short excerpt of the body with the matched
/// terms wrapped in `[` … `]`.