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
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"@nestjs/common": "^10",
"@nestjs/core": "^10",
"@nestjs/platform-express": "^10",
"@nestjs/testing": "^11.1.18",
"@nestjs/testing": "^10.4.22",
"@nx/eslint": "^22.6.4",
"@nx/jest": "^22.6.4",
"@nx/js": "^22.6.4",
Expand All @@ -42,6 +42,7 @@
"pdfkit": "^0.18.0",
"pg": "^8.20.0",
"prettier": "^3.8.1",
"reflect-metadata": "^0.2.2",
"rxjs": "^7.8.2",
"testcontainers": "^11.13.0",
"ts-jest": "^29",
Expand Down
2 changes: 1 addition & 1 deletion packages/agent-experiments/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"extends": ["../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"ignorePatterns": ["!**/*", "node_modules"],
"overrides": [
{
"files": ["*.ts"],
Expand Down
9 changes: 8 additions & 1 deletion packages/agent-experiments/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,15 @@
"pdfkit": "^0.16.0"
},
"devDependencies": {
"@grpc/grpc-js": "^1.14.3",
"@nestjs/common": "^10.4.22",
"@nestjs/core": "^10.4.22",
"@nestjs/platform-express": "^10.4.22",
"@zeroshotbuilders/commons": "^0.0.5",
"@zeroshotbuilders/commons-testing": "^0.0.5",
"@zeroshotbuilders/docling-utils": "^0.0.5"
"@zeroshotbuilders/docling-utils": "^0.0.5",
"reflect-metadata": "^0.2.2",
"rxjs": "^7.8.2"
},
"peerDependencies": {
"@nestjs/common": ">=10.0.0",
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified packages/agent-experiments/test/assets/fixtures/w2-acme-2024.pdf
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ describe("Salary Extraction Pipeline", () => {

console.log("Greenleaf Result:", JSON.stringify(result, null, 2));

expect(result.annualSalary).toBeGreaterThan(74_000);
expect(result.annualSalary).toBeLessThan(82_000);
expect(result.annualSalary).toBeGreaterThan(82_000);
expect(result.annualSalary).toBeLessThan(86_000);
expect(result.employeeName).toContain("Torres");
});

Expand Down
2 changes: 1 addition & 1 deletion packages/agentic-workflows/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"extends": ["../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"ignorePatterns": ["!**/*", "node_modules"],
"overrides": [
{
"files": ["*.ts"],
Expand Down
5 changes: 3 additions & 2 deletions packages/agentic-workflows/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@
"access": "public"
},
"dependencies": {
"@openai/agents": "^0.3.0",
"openai": "^4.77.0"
"@openai/agents": "0.3.0",
"openai": "4.77.0",
"zod": "^3.25.40"
},
"peerDependencies": {
"@nestjs/common": ">=10.0.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ export class RepositorySession implements Session {
private toContentParts(
role: "user" | "assistant" | "system",
content: string
): { type: string; text: string }[] {
) {
if (role === "user") {
return [{ type: "input_text", text: content }];
return [{ type: "input_text" as const, text: content }];
}

// assistant + system
return [{ type: "output_text", text: content }];
return [{ type: "output_text" as const, text: content }];
}

/**
Expand All @@ -51,13 +51,13 @@ export class RepositorySession implements Session {
limit
);

const items: AgentInputItem[] = dbItems.map((item) => ({
role: item.role as "user" | "assistant" | "system",
content: this.toContentParts(
item.role as "user" | "assistant" | "system",
item.content
)
}));
const items: AgentInputItem[] = dbItems.map((item) => {
const role = item.role as "user" | "assistant" | "system";
return {
role,
content: this.toContentParts(role, item.content)
} as AgentInputItem;
});

if (!limit) {
this.cachedItems = items;
Expand All @@ -75,10 +75,11 @@ export class RepositorySession implements Session {
// Down-project aggressively: only keep human-visible chat turns
const messages = items
.filter(
(item) =>
item.role === "user" ||
item.role === "assistant" ||
item.role === "system"
(item): item is AgentInputItem & { role: string; content: unknown } =>
"role" in item &&
(item.role === "user" ||
item.role === "assistant" ||
item.role === "system")
)
.map((item) => ({
role: item.role as string,
Expand Down Expand Up @@ -112,12 +113,10 @@ export class RepositorySession implements Session {
return undefined;
}

const role = poppedItem.role as "user" | "assistant" | "system";
return {
role: poppedItem.role as "user" | "assistant" | "system",
content: this.toContentParts(
poppedItem.role as "user" | "assistant" | "system",
poppedItem.content
)
};
role,
content: this.toContentParts(role, poppedItem.content)
} as AgentInputItem;
}
}
33 changes: 28 additions & 5 deletions packages/agentic-workflows/src/service/ai-agent-service-local.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
export class AiAgentServiceLocal implements AiAgentService {
private static instance: AiAgentServiceLocal = new AiAgentServiceLocal();
private static responsesByAgentName: Map<string, any[]> = new Map();
private static lastResponseByAgentName: Map<string, any> = new Map();
private static errorsByAgentName: Map<string, string> = new Map();
private static mockWorkingDir: string | undefined;

Expand Down Expand Up @@ -82,6 +83,7 @@ export class AiAgentServiceLocal implements AiAgentService {
*/
public static clearResponses(): void {
this.responsesByAgentName.clear();
this.lastResponseByAgentName.clear();
}

/**
Expand All @@ -96,6 +98,7 @@ export class AiAgentServiceLocal implements AiAgentService {
*/
public static clearAllOverrides(): void {
this.responsesByAgentName.clear();
this.lastResponseByAgentName.clear();
this.errorsByAgentName.clear();
this.mockWorkingDir = undefined;
}
Expand Down Expand Up @@ -147,10 +150,16 @@ export class AiAgentServiceLocal implements AiAgentService {
{ role: "user", content: runConfig.input },
{
role: "assistant",
content:
typeof result.output === "string"
? result.output
: JSON.stringify(result.output)
status: "completed",
content: [
{
type: "output_text",
text:
typeof result.output === "string"
? result.output
: JSON.stringify(result.output)
}
]
}
]);
}
Expand All @@ -176,14 +185,28 @@ export class AiAgentServiceLocal implements AiAgentService {
agentConfig.name
);
if (responses && responses.length > 0) {
const response = responses.shift(); // Pop first response from queue
const response = responses.shift();
AiAgentServiceLocal.lastResponseByAgentName.set(agentConfig.name, response);
return {
success: true,
output: response,
workingDir: AiAgentServiceLocal.mockWorkingDir
};
}

// If the queue is exhausted but we have a last response, repeat it.
// This supports consensus testing where 1 response is set for N runs.
const lastResponse = AiAgentServiceLocal.lastResponseByAgentName.get(
agentConfig.name
);
if (lastResponse !== undefined) {
return {
success: true,
output: lastResponse,
workingDir: AiAgentServiceLocal.mockWorkingDir
};
}

// Default mock response
return {
success: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ export class AiAgentServiceOllama implements AiAgentService {
instructions: config.instructions,
model: config.model ?? this.defaultModel,
tools: config.tools ?? [],
outputType: config.outputSchema,
outputType: config.outputSchema as any,
modelSettings: config.modelSettings,
inputGuardrails: config.inputGuardrails ?? undefined
}) as AgentType<T>;
}) as unknown as AgentType<T>;
}

public async runAgent<T>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ export class AiAgentServiceOpenai implements AiAgentService {
instructions: config.instructions,
model: config.model ?? this.defaultModel,
tools: config.tools ?? [],
outputType: config.outputSchema,
outputType: config.outputSchema as any,
modelSettings: config.modelSettings,
inputGuardrails: config.inputGuardrails ?? []
}) as AgentType<T>;
}) as unknown as AgentType<T>;
}

public async runAgent<T>(
Expand Down
42 changes: 30 additions & 12 deletions packages/agentic-workflows/src/service/ai-agent-service.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import type {
InputGuardrail,
ModelSettings,
Session,
UnknownContext
} from "@openai/agents";
import { Agent, Tool } from "@openai/agents";
import { z } from "zod";
import type {InputGuardrail, ModelSettings, Session, UnknownContext} from "@openai/agents";
import {Agent, Tool} from "@openai/agents";
import {z} from "zod";

/**
* Configuration for an AI agent run
Expand Down Expand Up @@ -39,6 +34,32 @@ export interface AgentRunResult<T = any> {
workingDir?: string;
}

/**
* Strategy for resolving consensus across multiple agent runs
*/
export enum ConsensusStrategy {
/** Most common output wins (uses equality comparison). Requires odd number of runs. */
MAJORITY = "majority",
/** All runs must produce the same output or the consensus fails. */
UNANIMOUS = "unanimous",
/** A user-provided judge function decides the winning output. */
JUDGE = "judge"
}

/**
* Result from a consensus agent run, extending AgentRunResult with multi-run metadata
*/
export interface ConsensusRunResult<T = any> extends AgentRunResult<T> {
/** All individual run results (including failures) */
runs: AgentRunResult<T>[];
/** Fraction of successful runs that agreed with the winning output (e.g. 0.8 = 4/5) */
agreement: number;
/** Total number of runs requested */
totalRuns: number;
/** Number of runs that completed successfully */
successfulRuns: number;
}

/**
* Configuration for creating an AI agent
*/
Expand All @@ -62,10 +83,7 @@ export interface AgentConfig<T = any> {
/**
* Helper type for Agent with Zod output type
*/
export type AgentType<T> = Agent<
UnknownContext,
T extends string ? undefined : z.ZodType<T>
>;
export type AgentType<T> = Agent<UnknownContext, any>;

/**
* Interface for AI agent services that abstracts the underlying provider.
Expand Down
Loading
Loading