-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patharchitecture.ts
More file actions
81 lines (75 loc) · 2.95 KB
/
Copy patharchitecture.ts
File metadata and controls
81 lines (75 loc) · 2.95 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
import { gateway } from "@ai-sdk/gateway";
import { Output, stepCountIs, ToolLoopAgent } from "ai";
import { z } from "zod";
import { mergeBashAndClawTools } from "@/lib/agents/helpers/merge-tools";
import { registerAgent } from "@/lib/agents/registry";
import { createOnStepFinish } from "@/lib/agents/step-hooks";
import type { AgentContext, AgentDefinition, AgentResult } from "@/lib/agents/types";
import { type Finding, FindingSchema } from "@/lib/analysis/types";
import { injectSkills } from "@/lib/skills";
const OutputSchema = z.object({
findings: z.array(FindingSchema),
summary: z.string(),
});
const AGENT_NAME = "architecture" as const;
const REQUIRED_SKILLS = ["architecture-patterns"] as const;
const architectureAgent: AgentDefinition = {
name: AGENT_NAME,
description:
"Dependency graphs, circular imports, coupling, blast radius, and Mermaid architecture diagrams.",
requiredSkills: [...REQUIRED_SKILLS],
requiredTools: ["fs:read", "shell:exec"],
maxSteps: 20,
dependsOn: [],
async execute(context: AgentContext): Promise<AgentResult> {
const start = Date.now();
const modelRef = `${context.config.model.provider}/${context.config.model.model}`;
const baseInstructions = [
"You are a software architect reviewing structural impact of the PR.",
"Use dependency_graph and generate_diagram tools. Put Mermaid in dataFlow.mermaidDiagram when useful.",
"Findings use category 'architecture'. Describe blast radius and coupling; severity by risk of change ripple.",
].join("\n");
const instructions = injectSkills(baseInstructions, AGENT_NAME, [...REQUIRED_SKILLS]);
const prompt = [
"## Diff",
context.recon.diff.slice(0, 100_000),
"",
"## Dependency graph (heuristic)",
context.recon.dependencyGraph
? JSON.stringify(context.recon.dependencyGraph, null, 2).slice(0, 40_000)
: "(none)",
].join("\n");
const tools = await mergeBashAndClawTools(context);
const maxSteps = Math.min(20, context.config.scanning.maxSteps);
const onStepFinish = createOnStepFinish(AGENT_NAME, context);
try {
const loop = new ToolLoopAgent({
model: gateway(modelRef),
tools,
output: Output.object({ schema: OutputSchema }),
stopWhen: stepCountIs(maxSteps),
instructions,
onStepFinish,
});
const result = await loop.generate({
prompt,
abortSignal: context.abortSignal,
});
return {
agentName: AGENT_NAME,
findings: result.output.findings as Finding[],
summary: result.output.summary,
durationMs: Date.now() - start,
};
} catch (err) {
return {
agentName: AGENT_NAME,
findings: [],
summary: `Architecture agent failed: ${err instanceof Error ? err.message : String(err)}`,
durationMs: Date.now() - start,
error: err instanceof Error ? err.message : String(err),
};
}
},
};
registerAgent(architectureAgent);