Menu
popagent
publicLatest change 4565eb356975518dfc0202eab29b56dff51e8f71 - add deterministic agent health validation by AkurAI Build
import { createTool, type ToolExecutionContext } from "@mastra/core/tools";
import { z } from "zod";
import { AGENT_CONTEXT_KEYS, agentContextValue } from "../agent-context";
import { codeIntelligence, type CodeIntelligenceService } from "../code-intelligence";
import { resolveAutonomousWorkspacePath } from "../workspace";
const relativePathSchema = z.string().trim().min(1).max(1_024);
const serviceSchema = z.object({ evidence: z.string() });
const symbolSchema = z.object({
definition: z.string(),
callers: z.string(),
callees: z.string(),
});
const impactSchema = z.object({
paths: z.array(z.string()),
branchImpact: z.string(),
files: z.array(z.object({ path: z.string(), evidence: z.string() })),
unresolved: z.array(z.string()),
});
type Service = Pick<CodeIntelligenceService, "codeContext" | "symbolContext" | "changeImpact">;
function executionRepositoryPath(context: ToolExecutionContext): string | undefined {
const source = agentContextValue(context.requestContext, AGENT_CONTEXT_KEYS.executionSource);
if (source !== "self-update" && source !== "build-maintenance") return undefined;
const path = agentContextValue(context.requestContext, AGENT_CONTEXT_KEYS.selfUpdateWorkspacePath);
if (!path) throw new Error("Autonomous workspace context is unavailable");
return resolveAutonomousWorkspacePath(path, source);
}
export function createCodeIntelligenceTools(service: Service = codeIntelligence) {
const codeContext = createTool({
id: "code-context",
description: "Preferred first repository discovery tool. Return a bounded local hybrid-search evidence pack for a behavior or concept before broad file reads. Use grep for exact exhaustive text and LSP for semantic references.",
inputSchema: z.object({
query: z.string().trim().min(1).max(2_000),
limit: z.number().int().min(1).max(20).default(8),
}),
outputSchema: serviceSchema,
execute: async ({ query, limit }, context) => {
const workspaceId = agentContextValue(context.requestContext, AGENT_CONTEXT_KEYS.workspaceId);
if (!workspaceId) throw new Error("Workspace context is required for code context");
return service.codeContext(workspaceId, query, limit, executionRepositoryPath(context), context.abortSignal);
},
});
const symbolContext = createTool({
id: "symbol-context",
description: "Inspect one known symbol through the local index: definition candidates plus direct callers and callees. Use LSP when precise type-aware references or rename safety is required.",
inputSchema: z.object({
symbol: z.string().trim().min(1).max(512),
filePath: relativePathSchema.optional(),
}),
outputSchema: symbolSchema,
execute: async ({ symbol, filePath }, context) => {
const workspaceId = agentContextValue(context.requestContext, AGENT_CONTEXT_KEYS.workspaceId);
if (!workspaceId) throw new Error("Workspace context is required for symbol context");
return service.symbolContext(
workspaceId,
symbol,
filePath,
executionRepositoryPath(context),
context.abortSignal,
);
},
});
const changeImpact = createTool({
id: "change-impact",
description: "Run bounded local blast-radius analysis before editing. Omit paths to inspect current working-tree changes; returns branch, dependency, caller/callee, and likely test evidence with unresolved edges.",
inputSchema: z.object({
paths: z.array(relativePathSchema).max(8).default([]),
}),
outputSchema: impactSchema,
execute: async ({ paths }, context) => {
const workspaceId = agentContextValue(context.requestContext, AGENT_CONTEXT_KEYS.workspaceId);
if (!workspaceId) throw new Error("Workspace context is required for change impact");
return service.changeImpact(
workspaceId,
paths,
executionRepositoryPath(context),
context.abortSignal,
);
},
});
return { codeContext, symbolContext, changeImpact };
}
export const { codeContext, symbolContext, changeImpact } = createCodeIntelligenceTools();