refactor: return complete tool results inline

This commit is contained in:
morluto committed 2026-09-29 07:08:46 +08:00
1 parent 2160d4fae5
commit 0d96275b68
535 files changed
+4084 -13537

No files matched your search

+3 -63
View File
@@ -4,7 +4,6 @@ import {
type ApplicationNode,
type JavaScriptApplicationGraph,
} from "./javascriptApplicationGraph.js";
import type { TraceApplicationFeatureInput } from "./javascriptFeatureTraceSchemas.js";
interface AdjacencyEntry {
readonly edge: ApplicationEdge;
@@ -16,73 +15,33 @@ interface Predecessor {
readonly edgeId: string;
}
/** Bounded graph projection plus the first deterministic path to each node. */
/** Complete reachable graph projection plus the first deterministic path to each node. */
export interface ApplicationFeatureTraversal {
readonly nodes: ApplicationNode[];
readonly edges: ApplicationEdge[];
readonly depths: ReadonlyMap<string, number>;
readonly predecessors: ReadonlyMap<string, Predecessor>;
readonly frontierNodeIds: string[];
readonly omittedNodeCount: number;
readonly omittedEdgeCount: number;
}
/** Traverse a JAG without treating edge inference as observed reachability. */
export const traverseApplicationFeature = (
graph: JavaScriptApplicationGraph,
seedNodeIds: readonly string[],
direction: TraceApplicationFeatureInput["direction"],
limits: TraceApplicationFeatureInput["limits"],
direction: "outgoing" | "incoming" | "both",
): ApplicationFeatureTraversal => {
const nodeById = new Map(graph.nodes.map((node) => [node.node_id, node]));
const adjacency = buildAdjacency(graph.edges, direction);
const visited = new Set(seedNodeIds);
const retainedEdges = new Map<string, ApplicationEdge>();
const omittedNodes = new Set<string>();
const omittedEdges = new Set<string>();
const frontier = new Set<string>();
const depths = new Map(seedNodeIds.map((nodeId) => [nodeId, 0]));
const predecessors = new Map<string, Predecessor>();
const queue = [...seedNodeIds];
for (let offset = 0; offset < queue.length; offset += 1) {
const current = queue[offset];
if (current === undefined) continue;
const depth = depths.get(current) ?? 0;
for (const entry of adjacency.get(current) ?? []) {
if (depth >= limits.max_depth) {
recordOmission({
entry,
current,
omittedNodes,
omittedEdges,
frontier,
});
continue;
}
if (!visited.has(entry.nextNodeId) && visited.size >= limits.max_nodes) {
recordOmission({
entry,
current,
omittedNodes,
omittedEdges,
frontier,
});
continue;
}
if (
!retainedEdges.has(entry.edge.edge_id) &&
retainedEdges.size >= limits.max_edges
) {
omittedEdges.add(entry.edge.edge_id);
frontier.add(current);
frontier.add(entry.nextNodeId);
continue;
}
retainedEdges.set(entry.edge.edge_id, entry.edge);
if (visited.has(entry.nextNodeId)) continue;
if (!nodeById.has(entry.nextNodeId)) continue;
visited.add(entry.nextNodeId);
depths.set(entry.nextNodeId, depth + 1);
predecessors.set(entry.nextNodeId, {
previousNodeId: current,
edgeId: entry.edge.edge_id,
@@ -98,17 +57,13 @@ export const traverseApplicationFeature = (
edges: [...retainedEdges.values()].sort((left, right) =>
compareCodePoints(left.edge_id, right.edge_id),
),
depths,
predecessors,
frontierNodeIds: [...frontier].sort(compareCodePoints),
omittedNodeCount: omittedNodes.size,
omittedEdgeCount: omittedEdges.size,
};
};
const buildAdjacency = (
edges: readonly ApplicationEdge[],
direction: TraceApplicationFeatureInput["direction"],
direction: "outgoing" | "incoming" | "both",
): ReadonlyMap<string, AdjacencyEntry[]> => {
const adjacency = new Map<string, AdjacencyEntry[]>();
for (const edge of edges) {
@@ -140,18 +95,3 @@ const addAdjacency = (
): void => {
adjacency.set(nodeId, [...(adjacency.get(nodeId) ?? []), entry]);
};
interface OmissionContext {
readonly entry: AdjacencyEntry;
readonly current: string;
readonly omittedNodes: Set<string>;
readonly omittedEdges: Set<string>;
readonly frontier: Set<string>;
}
const recordOmission = (context: OmissionContext): void => {
context.omittedNodes.add(context.entry.nextNodeId);
context.omittedEdges.add(context.entry.edge.edge_id);
context.frontier.add(context.current);
context.frontier.add(context.entry.nextNodeId);
};