feat: extract pipeline core for library consumption (#282)

* feat: extract pipeline core for library consumption

* fix: chmod workspace directory for container write access

* fix: resolve playwright output dir relative to deliverables parent

* feat: add multi-provider LLM support via ProviderConfig

* fix: resolve model overrides via options.model, remove unused model env passthrough

* fix: use ANTHROPIC_AUTH_TOKEN for custom base URL and router auth

* fix: skip env-based credential validation when providerConfig is present

* fix: support large UID/GID values for AD/LDAP users in container
This commit is contained in:
ezl-keygraph
2026-04-10 04:53:36 +05:30
committed by GitHub
parent f6fd1edad6
commit 1f6dfd7e17
32 changed files with 616 additions and 106 deletions
+29 -2
View File
@@ -18,6 +18,11 @@
*/
import type { SessionMetadata } from '../audit/utils.js';
import type { CheckpointProvider } from '../interfaces/checkpoint-provider.js';
import { NoOpCheckpointProvider } from '../interfaces/checkpoint-provider.js';
import type { FindingsProvider } from '../interfaces/findings-provider.js';
import { NoOpFindingsProvider } from '../interfaces/findings-provider.js';
import type { ContainerConfig } from '../types/config.js';
import { AgentExecutionService } from './agent-execution.js';
import { ConfigLoaderService } from './config-loader.js';
import { ExploitationCheckerService } from './exploitation-checker.js';
@@ -32,6 +37,9 @@ import { ExploitationCheckerService } from './exploitation-checker.js';
*/
export interface ContainerDependencies {
readonly sessionMetadata: SessionMetadata;
readonly config: ContainerConfig;
readonly findingsProvider?: FindingsProvider;
readonly checkpointProvider?: CheckpointProvider;
}
/**
@@ -45,17 +53,25 @@ export interface ContainerDependencies {
*/
export class Container {
readonly sessionMetadata: SessionMetadata;
readonly config: ContainerConfig;
readonly agentExecution: AgentExecutionService;
readonly configLoader: ConfigLoaderService;
readonly exploitationChecker: ExploitationCheckerService;
readonly findingsProvider: FindingsProvider;
readonly checkpointProvider: CheckpointProvider;
constructor(deps: ContainerDependencies) {
this.sessionMetadata = deps.sessionMetadata;
this.config = deps.config;
// Wire services with explicit constructor injection
this.configLoader = new ConfigLoaderService();
this.exploitationChecker = new ExploitationCheckerService();
this.agentExecution = new AgentExecutionService(this.configLoader);
// Wire providers with default no-ops when not provided
this.findingsProvider = deps.findingsProvider ?? new NoOpFindingsProvider();
this.checkpointProvider = deps.checkpointProvider ?? new NoOpCheckpointProvider();
}
}
@@ -65,6 +81,12 @@ export class Container {
*/
const containers = new Map<string, Container>();
/** Default container config — OSS standalone defaults */
const DEFAULT_CONFIG: ContainerConfig = {
deliverablesSubdir: '.shannon/deliverables',
auditDir: './workspaces',
};
/**
* Get or create a Container for a workflow.
*
@@ -73,13 +95,18 @@ const containers = new Map<string, Container>();
*
* @param workflowId - Unique workflow identifier
* @param sessionMetadata - Session metadata for audit paths
* @param config - Runtime configuration (defaults to OSS standalone config)
* @returns Container instance for the workflow
*/
export function getOrCreateContainer(workflowId: string, sessionMetadata: SessionMetadata): Container {
export function getOrCreateContainer(
workflowId: string,
sessionMetadata: SessionMetadata,
config: ContainerConfig = DEFAULT_CONFIG,
): Container {
let container = containers.get(workflowId);
if (!container) {
container = new Container({ sessionMetadata });
container = new Container({ sessionMetadata, config });
containers.set(workflowId, container);
}