Refactor pipeline policies, MCP registry, and unified config/runtime
This commit is contained in:
@@ -1,99 +1,75 @@
|
||||
import "dotenv/config";
|
||||
import { query, type Options } from "@anthropic-ai/claude-agent-sdk";
|
||||
import { pathToFileURL } from "node:url";
|
||||
import { getAgentManager, getResourceProvisioningOrchestrator } from "../agents/runtime.js";
|
||||
import { loadMcpConfigFromEnv } from "../mcp.js";
|
||||
import { getConfig } from "../config.js";
|
||||
import { createSessionContext } from "./session-context.js";
|
||||
|
||||
function requiredPrompt(argv: string[]): string {
|
||||
const prompt = argv.slice(2).join(" ").trim();
|
||||
if (!prompt) {
|
||||
throw new Error("Usage: npm run claude -- \"your prompt\"");
|
||||
throw new Error('Usage: npm run claude -- "your prompt"');
|
||||
}
|
||||
return prompt;
|
||||
}
|
||||
|
||||
function buildOptions(): Options {
|
||||
function buildOptions(config = getConfig()): Options {
|
||||
return {
|
||||
maxTurns: 1,
|
||||
...(process.env.CLAUDE_MODEL ? { model: process.env.CLAUDE_MODEL } : {}),
|
||||
...(process.env.CLAUDE_CODE_PATH
|
||||
? { pathToClaudeCodeExecutable: process.env.CLAUDE_CODE_PATH }
|
||||
...(config.provider.claudeModel ? { model: config.provider.claudeModel } : {}),
|
||||
...(config.provider.claudeCodePath
|
||||
? { pathToClaudeCodeExecutable: config.provider.claudeCodePath }
|
||||
: {}),
|
||||
};
|
||||
}
|
||||
|
||||
export async function runClaudePrompt(prompt: string): Promise<void> {
|
||||
const agentManager = getAgentManager();
|
||||
const agentSession = agentManager.createSession();
|
||||
const resourceProvisioning = getResourceProvisioningOrchestrator();
|
||||
const mcp = loadMcpConfigFromEnv({
|
||||
providerHint: "claude",
|
||||
const config = getConfig();
|
||||
const sessionContext = await createSessionContext("claude", {
|
||||
prompt,
|
||||
config,
|
||||
});
|
||||
let provisionedResources:
|
||||
| Awaited<ReturnType<typeof resourceProvisioning.provisionSession>>
|
||||
| undefined;
|
||||
|
||||
try {
|
||||
provisionedResources = await resourceProvisioning.provisionSession({
|
||||
sessionId: agentSession.id,
|
||||
resources: [{ kind: "git-worktree" }, { kind: "port-range" }],
|
||||
});
|
||||
const runtimeInjection = await provisionedResources.buildRuntimeInjection({
|
||||
discoveryFileRelativePath: process.env.AGENT_DISCOVERY_FILE_RELATIVE_PATH,
|
||||
baseEnv: process.env,
|
||||
});
|
||||
const promptWithContext = provisionedResources.composePrompt(prompt, [
|
||||
`Discovery file: ${runtimeInjection.discoveryFilePath}`,
|
||||
"Resource env vars are pre-injected (AGENT_WORKTREE_PATH, AGENT_PORT_RANGE_START, AGENT_PORT_RANGE_END, AGENT_PORT_PRIMARY).",
|
||||
]);
|
||||
const finalResponse = await sessionContext.runInSession(async () => {
|
||||
const session = query({
|
||||
prompt: sessionContext.promptWithContext,
|
||||
options: {
|
||||
...buildOptions(config),
|
||||
...(sessionContext.mcp.claudeMcpServers ? { mcpServers: sessionContext.mcp.claudeMcpServers } : {}),
|
||||
cwd: sessionContext.runtimeInjection.workingDirectory,
|
||||
env: sessionContext.runtimeInjection.env,
|
||||
},
|
||||
});
|
||||
|
||||
const finalResponse = await agentSession.runAgent({
|
||||
depth: 0,
|
||||
run: async () => {
|
||||
const session = query({
|
||||
prompt: promptWithContext,
|
||||
options: {
|
||||
...buildOptions(),
|
||||
...(mcp.claudeMcpServers ? { mcpServers: mcp.claudeMcpServers } : {}),
|
||||
cwd: runtimeInjection.workingDirectory,
|
||||
env: runtimeInjection.env,
|
||||
},
|
||||
});
|
||||
let result = "";
|
||||
|
||||
let result = "";
|
||||
|
||||
try {
|
||||
for await (const message of session) {
|
||||
if (message.type === "result" && message.subtype === "success") {
|
||||
result = message.result.trim();
|
||||
}
|
||||
|
||||
if (message.type === "result" && message.subtype !== "success") {
|
||||
const detail = message.errors.join("; ");
|
||||
throw new Error(
|
||||
`Claude query failed (${message.subtype})${detail ? `: ${detail}` : ""}`,
|
||||
);
|
||||
}
|
||||
try {
|
||||
for await (const message of session) {
|
||||
if (message.type === "result" && message.subtype === "success") {
|
||||
result = message.result.trim();
|
||||
}
|
||||
} finally {
|
||||
session.close();
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
throw new Error("Claude run completed without a final result.");
|
||||
if (message.type === "result" && message.subtype !== "success") {
|
||||
const detail = message.errors.join("; ");
|
||||
throw new Error(
|
||||
`Claude query failed (${message.subtype})${detail ? `: ${detail}` : ""}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
session.close();
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
if (!result) {
|
||||
throw new Error("Claude run completed without a final result.");
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
console.log(finalResponse);
|
||||
} finally {
|
||||
if (provisionedResources) {
|
||||
await provisionedResources.release();
|
||||
}
|
||||
agentSession.close();
|
||||
await sessionContext.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user