Files
ask262/agent_tools/section_retriever.ts
T
bendtherules ff1c97af44 fix(agent-tools, setup): standardize metadata keys to lowercase and update HTML ingestion
- Renamed `partIndex`/`totalParts` to `partindex`/`totalparts` in `section_retriever.ts`, `spec_retriever.ts`, and document creation logic.
- Adjusted sorting logic to use the new `partindex` field.
- Updated metadata handling and string interpolation to reference the lowercase keys.
- Fixed import path for `HTMLTextSplitter` and moved the file to `setup/textsplitters/HtmlTextSplitter.ts`.
- Added HTML preprocessing utilities (`addNewlinesAfterBlocks`, `convertTablesToMarkdown`) in ingestion workflow.
- Integrated table-to‑markdown conversion and newline insertion to improve text splitting and document structure.
2026-04-04 12:33:05 +05:30

76 lines
2.4 KiB
TypeScript

/**
* Section chunk retriever tool.
* Retrieves all text chunks from a specific specification section by sectionid.
*/
import type { Table } from "@lancedb/lancedb";
import { DynamicStructuredTool } from "@langchain/core/tools";
import { z } from "zod";
const sectionRetrieverSchema = z.object({
sectionId: z
.string()
.describe("The section ID (e.g., 'sec-if-statement') to fetch chunks for"),
});
/**
* Creates the section retriever tool.
* @param table - LanceDB table containing spec vectors
*/
export function createSectionRetrieverTool(table: Table) {
return new DynamicStructuredTool({
name: "fetch_section_chunks",
description:
"Retrieves all text chunks from a specific specification section by sectionid. " +
"Supports recursive fetching - if a section has children, it will fetch all descendants. " +
"Use this to get complete content when you see 'Subsection available' or 'partial section' references.",
schema: sectionRetrieverSchema,
func: async ({ sectionId }) => {
const allDocs: string[] = [];
const queue: string[] = [sectionId];
const visited = new Set<string>();
while (queue.length > 0) {
const currentId = queue.shift()!;
if (visited.has(currentId)) continue;
visited.add(currentId);
const results = await table
.query()
.where(`sectionid = '${currentId}'`)
.limit(100)
.toArray();
// Sort by partindex to maintain order (nulls last for single-part sections)
const sortedResults = results.sort((a: unknown, b: unknown) => {
const aIndex = (a as { partindex?: number }).partindex ?? Infinity;
const bIndex = (b as { partindex?: number }).partindex ?? Infinity;
return aIndex - bIndex;
});
for (const result of sortedResults) {
const typedResult = result as {
text?: string;
childrensectionids?: string[];
sectiontitle?: string;
};
if (typedResult.text) {
allDocs.push(typedResult.text);
}
// Add children to queue for recursive fetching
if (
typedResult.childrensectionids &&
Array.isArray(typedResult.childrensectionids)
) {
queue.push(...typedResult.childrensectionids);
}
}
}
return allDocs.join("\n\n---\n\n");
},
});
}