Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 1 addition & 21 deletions esbuild.bundle.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,7 @@ const externalSdks = [

const resolveRuntimeDynamicImports = {
name: "resolve-runtime-dynamic-imports",
setup(build) {
build.onLoad({ filter: /agents[\\/]orchestrator\.ts$/ }, async (args) => {
let contents = readFileSync(args.path, "utf8");
// Replace obfuscated RUNTIME_PKG with literal package name
contents = contents.replace(
/const RUNTIME_PKG = \["agent-contracts",\s*"runtime"\]\.join\("-"\);/,
'const RUNTIME_PKG = "agent-contracts-runtime";',
);
// Replace dynamic imports with literal strings
contents = contents.replace(
/await import\(RUNTIME_PKG\)/g,
'await import("agent-contracts-runtime")',
);
// Replace template-literal adapter imports
contents = contents.replace(
/await import\(`\$\{runtimePkg\}\/adapters\/([^`]+)`\)/g,
'await import("agent-contracts-runtime/adapters/$1")',
);
return { contents, loader: "ts" };
});
},
setup(_build) {},
};

const inlineBuildTimeConstants = {
Expand Down
46 changes: 10 additions & 36 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,9 @@
"@openai/agents": "^0.11.1",
"@types/js-yaml": "^4.0.9",
"@types/node": "^20.11.0",
"agent-contracts": "^0.33.1",
"agent-contracts": "^0.34.12",
"agent-contracts-analyzer": "file:vendor/agent-contracts-analyzer-0.1.1.tgz",
"agent-contracts-runtime": "^0.36.0",
"agent-contracts-runtime": "^0.36.6",
"chalk": "^5.3.0",
"cli-contracts": "^0.32.0",
"commander": "^12.1.0",
Expand Down
131 changes: 31 additions & 100 deletions src/agents/orchestrator.ts
Original file line number Diff line number Diff line change
@@ -1,128 +1,59 @@
import { resolve } from "node:path";
import { resolvedDsl } from "../generated/dsl/dsl-data.js";
import type { AuditConfig, AuditOptions, AuditRunResult, TaskId } from "./types.js";

export const EXIT_RUNTIME_MISSING = 11;
export const EXIT_ADAPTER_ERROR = 12;

// eslint-disable-next-line @typescript-eslint/no-explicit-any
async function createAdapter(runtimePkg: string, name: string, config: AuditConfig): Promise<any> {
switch (name) {
case "mock": {
const mod = await import(`${runtimePkg}/adapters/mock`);
return new mod.MockAdapter();
}
case "claude": {
const mod = await import(`${runtimePkg}/adapters/claude-agent-sdk`);
return new mod.ClaudeAgentSdkAdapter({
model: config.model,
tools: ["Read", "Glob", "Grep"],
permissionMode: "bypassPermissions",
});
}
case "openai": {
const mod = await import(`${runtimePkg}/adapters/openai-agents-sdk`);
return new mod.OpenAIAgentsSdkAdapter({
model: config.model ?? "o3-mini",
maxTurns: 1,
});
}
case "gemini": {
const mod = await import(`${runtimePkg}/adapters/adk-sdk`);
return new mod.AdkSdkAdapter({
apiKey: process.env.GEMINI_API_KEY,
model: config.model ?? "gemini-2.5-pro",
temperature: config.temperature,
});
}
default:
throw new Error(
`Unsupported adapter: "${name}". ` +
"Available: mock, claude, openai, gemini.",
);
}
}

export async function runAgentTask(
userRequest: string,
taskId: TaskId,
auditConfig: AuditConfig,
options: AuditOptions,
): Promise<AuditRunResult> {
const RUNTIME_PKG = ["agent-contracts", "runtime"].join("-");

// eslint-disable-next-line @typescript-eslint/no-explicit-any
let runTask: (...args: any[]) => Promise<any>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let createProgressSink: (...args: any[]) => { write: (chunk: string) => void; close: () => void };
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let agentRegistry: any, taskRegistry: any, handoffSchemas: any;

let executeTask: (taskId: string, options: any) => Promise<any>;
try {
const runtime = await import(RUNTIME_PKG);
runTask = runtime.runTask;
createProgressSink = runtime.createProgressSink;
const runtime = await import("agent-contracts-runtime");
executeTask = runtime.executeTask;
} catch {
throw Object.assign(
new Error(
"agent-contracts-runtime is not installed. " +
"Install it to use this command, or use --show-prompt to inspect the prompt.\n" +
" npm install agent-contracts-runtime",
"Install it to use this command, or use --show-prompt to inspect the prompt.\n" +
" npm install agent-contracts-runtime",
),
{ exitCode: EXIT_RUNTIME_MISSING },
);
}

let result;
try {
const dsl = await import("../generated/dsl/index.js");
agentRegistry = dsl.agentRegistry;
taskRegistry = dsl.taskRegistry;
handoffSchemas = dsl.handoffSchemas;
} catch {
agentRegistry = {};
taskRegistry = {};
handoffSchemas = {};
}

const adapterName = auditConfig.adapter ?? "mock";
let adapter;
try {
adapter = await createAdapter(RUNTIME_PKG, adapterName, auditConfig);
} catch (err) {
throw Object.assign(err as Error, { exitCode: EXIT_ADAPTER_ERROR });
}

const progressSink = options.logFile
? createProgressSink({ stderr: true, file: resolve(options.logFile), naming: "single" })
: createProgressSink({ stderr: true });

try {
const result = await runTask(adapter, taskId, {
user_request: userRequest,
}, {
result = await executeTask(taskId, {
request: userRequest,
adapter: auditConfig.adapter ?? "mock",
model: auditConfig.model,
dsl: resolvedDsl,
logFile: options.logFile,
maxFollowUps: 3,
maxRetries: 1,
progressOutput: progressSink,
agentRegistry,
taskRegistry,
handoffSchemas,
});

const outcome = result.outcome;
return {
taskId,
data: outcome.status === "success" ? outcome.data : null,
raw: (outcome.raw as string) ?? "",
prompt: userRequest,
status: outcome.status as AuditRunResult["status"],
errorMessage:
outcome.status === "error" ? outcome.message :
outcome.status === "escalation" ? outcome.reason :
outcome.status === "validation_error" ? outcome.errors?.message :
undefined,
followUpsUsed: result.follow_ups_used,
retriesUsed: result.retries_used,
};
} finally {
progressSink.close();
} catch (err) {
throw Object.assign(err as Error, { exitCode: EXIT_ADAPTER_ERROR });
}

const outcome = result.outcome;
return {
taskId,
data: outcome.status === "success" ? (outcome.data ?? null) : null,
raw: outcome.raw ?? "",
prompt: userRequest,
status: outcome.status as AuditRunResult["status"],
errorMessage:
outcome.status === "error" ? outcome.message :
outcome.status === "escalation" ? outcome.reason :
outcome.status === "validation_error" ? outcome.errors?.message :
undefined,
followUpsUsed: result.follow_ups_used,
retriesUsed: result.retries_used,
};
}
7 changes: 4 additions & 3 deletions src/generated/dsl/.manifest.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
{
"generated_at": "2026-06-03T09:09:31.255Z",
"generated_at": "2026-06-06T17:25:21.763Z",
"dsl_hash": "1c2b11132ad90a541a922748e466a4676face316dd693e03a1ef258c7d526d0e",
"generation_input_hash": "1c2b11132ad90a541a922748e466a4676face316dd693e03a1ef258c7d526d0e",
"generation_input_hash": "e2af5f5a1c268e244b1dba78076f0233e43dc1027a67a791e4ca70820c92b74c",
"files": [
"../src/generated/dsl/agents.ts",
"../src/generated/dsl/tasks.ts",
"../src/generated/dsl/workflows.ts",
"../src/generated/dsl/handoffs.ts",
"../src/generated/dsl/index.ts"
"../src/generated/dsl/index.ts",
"../src/generated/dsl/dsl-data.ts"
]
}
Loading
Loading