426e9eeabd
Voice Workbench / headless workbench (mocked backends) (push) Has been cancelled
Voice Workbench / real acoustic lane (nightly, provisioned only) (push) Has been cancelled
ci / test (push) Has been cancelled
ci / lint-and-format (push) Has been cancelled
ci / build (push) Has been cancelled
ci / dev-startup (push) Has been cancelled
gitleaks / gitleaks (push) Has been cancelled
Markdown Links / Relative Markdown Links (push) Has been cancelled
Quality (Extended) / Homepage Build (PR smoke) (push) Has been cancelled
Quality (Extended) / Comment-only diff guard (push) Has been cancelled
Quality (Extended) / Format + Type Safety Ratchet (push) Has been cancelled
Quality (Extended) / Develop Gate (secret scan + UI determinism) (push) Has been cancelled
Quality (Extended) / Develop Gate (lint) (push) Has been cancelled
Chat shell gestures / Chat shell gesture + parity e2e (push) Has been cancelled
Cloud Gateway Discord / Test (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx @biomejs/biome check packages/lifeops-bench/src, benchmark-lint) (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx vitest run --config packages/lifeops-bench/vitest.config.ts --root packages/lifeops-bench --passWithNoTests, benchmark-tests) (push) Has been cancelled
Build Agent Image / build-and-push (push) Has been cancelled
Dev Smoke / bun run dev onboarding chat (push) Has been cancelled
Dev Smoke / Vite HMR dependency-level smoke (push) Has been cancelled
Electrobun Submodule Guard / electrobun gitlink is fetchable (push) Has been cancelled
Publish @elizaos/example-code / check_npm (push) Has been cancelled
Publish @elizaos/example-code / publish_npm (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / verify_version (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / publish_npm (push) Has been cancelled
Sandbox Live Smoke / Sandbox live smoke (push) Has been cancelled
Snap Build & Test / Build Snap (amd64) (push) Has been cancelled
Snap Build & Test / Build Snap (arm64) (push) Has been cancelled
Test Packaging / elizaos CLI global-install smoke (node + bun) (push) Has been cancelled
Cloud Gateway Webhook / Test (push) Has been cancelled
Cloud Tests / lint-and-types (push) Has been cancelled
Cloud Tests / unit-tests (push) Has been cancelled
Cloud Tests / integration-tests (push) Has been cancelled
Cloud Tests / e2e-tests (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Apps Worker (Product 2) / Determine environment (push) Has been cancelled
Deploy Apps Worker (Product 2) / Deploy apps worker to apps-control host (${{ needs.determine-env.outputs.environment }}) (push) Has been cancelled
Deploy Eliza Provisioning Worker / Determine environment (push) Has been cancelled
Deploy Eliza Provisioning Worker / Deploy worker to Hetzner host (${{ needs.determine-env.outputs.environment }} @ ${{ needs.determine-env.outputs.deployment_sha }}) (push) Has been cancelled
Dev Smoke / Classify changed paths (push) Has been cancelled
supply-chain / sbom (push) Has been cancelled
supply-chain / vulnerability-scan (push) Has been cancelled
Build, Push & Deploy to Phala Cloud / build-and-push (push) Has been cancelled
Test Packaging / Validate Packaging Configs (push) Has been cancelled
Test Packaging / Build & Test PyPI Package (push) Has been cancelled
Test Packaging / PyPI on Python ${{ matrix.python }} (push) Has been cancelled
Test Packaging / Pack & Test JS Tarballs (push) Has been cancelled
UI Fixture E2E / ui-fixture-e2e (push) Has been cancelled
UI Fixture E2E / fixture-e2e (push) Has been cancelled
UI Story Gate / story-gate (push) Has been cancelled
vault-ci / test (macos-latest) (push) Has been cancelled
vault-ci / test (ubuntu-latest) (push) Has been cancelled
vault-ci / test (windows-latest) (push) Has been cancelled
vault-ci / app-core wiring tests (push) Has been cancelled
verify-patches / verify patches/CHECKSUMS.sha256 (push) Has been cancelled
Voice Benchmark Smoke / voice-emotion fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voiceagentbench fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench-quality unit smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench TypeScript unit (no audio) (push) Has been cancelled
Voice Benchmark Smoke / voice bench smoke summary (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/app-core test bun run --cwd packages/elizaos test bun run --cwd packages/cloud/shared test], app-and-cli) (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/scenario-runner test bun run --cwd packages/vault test bun run --cwd packages/security test bun run --cwd plugins/plugin-coding-tools test], framework-packages) (push) Has been cancelled
Windows CI / windows ([bun run --cwd plugins/plugin-elizacloud test bun run --cwd plugins/plugin-discord test bun run --cwd plugins/plugin-anthropic test bun run --cwd plugins/plugin-openai test bun run --cwd plugins/plugin-app-control test bun run --cwd plugins/pl… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run build --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/agent --concurrency=4 node packages/scripts/run-bash-linux-only.mjs scripts/verify-riscv64-buildpaths.sh node packages/scripts/run… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run typecheck --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/cloud-shared --concurrency=4 bun run --cwd packages/core test bun run --cwd packages/shared test], core-runtime, 75) (push) Has been cancelled
356 lines
12 KiB
TypeScript
356 lines
12 KiB
TypeScript
/**
|
|
* Coding agent context types and validation.
|
|
*
|
|
* Provides Zod schemas and TypeScript types for validating coding agent
|
|
* context objects used in the autonomous coding loop: code generation,
|
|
* execution, error capture, iterative self-correction, and human-in-the-loop
|
|
* feedback injection.
|
|
*
|
|
* @module services/coding-agent-context
|
|
*/
|
|
|
|
import { z } from "zod";
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Zod Schemas
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/** Schema for a single file operation within a coding iteration. */
|
|
export const FileOperationSchema = z.object({
|
|
type: z.enum(["read", "write", "edit", "list", "search"]),
|
|
target: z.string().min(1, "File operation target must not be empty"),
|
|
/** Size in bytes for write/edit operations. */
|
|
size: z.number().int().nonnegative().optional(),
|
|
});
|
|
|
|
/** Schema for a shell command result captured during execution. */
|
|
export const CommandResultSchema = z.object({
|
|
command: z.string().min(1),
|
|
exitCode: z.number().int(),
|
|
stdout: z.string(),
|
|
stderr: z.string(),
|
|
/** Working directory where the command was executed. */
|
|
executedIn: z.string().min(1),
|
|
/** Duration in milliseconds. */
|
|
durationMs: z.number().nonnegative().optional(),
|
|
success: z.boolean(),
|
|
});
|
|
|
|
/** Schema for an error captured during code execution. */
|
|
export const CapturedErrorSchema = z.object({
|
|
/** Error category: compile, runtime, test, lint, or other. */
|
|
category: z.enum(["compile", "runtime", "test", "lint", "other"]),
|
|
/** Human-readable error message. */
|
|
message: z.string().min(1),
|
|
/** File path where the error occurred (if applicable). */
|
|
filePath: z.string().optional(),
|
|
/** Line number where the error occurred (if applicable). */
|
|
line: z.number().int().positive().optional(),
|
|
/** Raw error output from the tool/command. */
|
|
raw: z.string().optional(),
|
|
});
|
|
|
|
/** Schema for human feedback injected into the coding loop. */
|
|
export const HumanFeedbackSchema = z.object({
|
|
/** Unique feedback identifier. */
|
|
id: z.string().min(1),
|
|
/** Timestamp when feedback was received. */
|
|
timestamp: z.number().int().positive(),
|
|
/** The feedback text from the user. */
|
|
text: z.string().min(1),
|
|
/** The context/iteration the feedback applies to. */
|
|
iterationRef: z.number().int().nonnegative().optional(),
|
|
/** Feedback type: correction, guidance, approval, rejection. */
|
|
type: z.enum(["correction", "guidance", "approval", "rejection"]),
|
|
});
|
|
|
|
/** Schema for a single iteration of the coding agent loop. */
|
|
export const CodingIterationSchema = z.object({
|
|
/** Zero-based iteration index. */
|
|
index: z.number().int().nonnegative(),
|
|
/** Timestamp when this iteration started. */
|
|
startedAt: z.number().int().positive(),
|
|
/** Timestamp when this iteration completed. */
|
|
completedAt: z.number().int().positive().optional(),
|
|
/** Code generation output (the generated/modified code). */
|
|
generatedCode: z.string().optional(),
|
|
/** File operations performed during this iteration. */
|
|
fileOperations: z.array(FileOperationSchema).default([]),
|
|
/** Commands executed during this iteration. */
|
|
commandResults: z.array(CommandResultSchema).default([]),
|
|
/** Errors captured during this iteration. */
|
|
errors: z.array(CapturedErrorSchema).default([]),
|
|
/** Human feedback applied at this iteration. */
|
|
feedback: z.array(HumanFeedbackSchema).default([]),
|
|
/** Whether this iteration resolved all errors from the previous one. */
|
|
selfCorrected: z.boolean().default(false),
|
|
/** Summary of what changed in this iteration. */
|
|
summary: z.string().optional(),
|
|
});
|
|
|
|
/** Schema for the connector type used by the coding agent. */
|
|
export const ConnectorTypeSchema = z.enum([
|
|
"local-fs",
|
|
"git-repo",
|
|
"api",
|
|
"browser",
|
|
"sandbox",
|
|
]);
|
|
|
|
/** Schema for connector configuration. */
|
|
export const ConnectorConfigSchema = z.object({
|
|
type: ConnectorTypeSchema,
|
|
/** Base path / URL for the connector. */
|
|
basePath: z.string().min(1),
|
|
/** Whether the connector is currently available. */
|
|
available: z.boolean().default(true),
|
|
/** Connector-specific metadata. */
|
|
metadata: z.record(z.string(), z.string()).optional(),
|
|
});
|
|
|
|
/** Interaction mode for the coding session. */
|
|
export const InteractionModeSchema = z.enum([
|
|
"fully-automated",
|
|
"human-in-the-loop",
|
|
"manual-guidance",
|
|
]);
|
|
|
|
/** Schema for the full coding agent context. */
|
|
export const CodingAgentContextSchema = z.object({
|
|
/** Unique session identifier. */
|
|
sessionId: z.string().min(1),
|
|
/** Task description / goal for the coding session. */
|
|
taskDescription: z.string().min(1),
|
|
/** Working directory for file operations. */
|
|
workingDirectory: z.string().min(1),
|
|
/** Connector configuration for accessing code. */
|
|
connector: ConnectorConfigSchema,
|
|
/** Interaction mode for this session. */
|
|
interactionMode: InteractionModeSchema,
|
|
/** Maximum iterations before the loop stops. */
|
|
maxIterations: z.number().int().positive().default(10),
|
|
/** Whether the loop is currently active. */
|
|
active: z.boolean().default(true),
|
|
/** All iterations of the coding loop. */
|
|
iterations: z.array(CodingIterationSchema).default([]),
|
|
/** All human feedback collected during the session. */
|
|
allFeedback: z.array(HumanFeedbackSchema).default([]),
|
|
/** Timestamp when the session was created. */
|
|
createdAt: z.number().int().positive(),
|
|
/** Timestamp when the session was last updated. */
|
|
updatedAt: z.number().int().positive().optional(),
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// TypeScript Types (inferred from schemas)
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export type FileOperation = z.infer<typeof FileOperationSchema>;
|
|
export type CommandResult = z.infer<typeof CommandResultSchema>;
|
|
export type CapturedError = z.infer<typeof CapturedErrorSchema>;
|
|
export type HumanFeedback = z.infer<typeof HumanFeedbackSchema>;
|
|
export type CodingIteration = z.infer<typeof CodingIterationSchema>;
|
|
export type ConnectorType = z.infer<typeof ConnectorTypeSchema>;
|
|
export type ConnectorConfig = z.infer<typeof ConnectorConfigSchema>;
|
|
export type InteractionMode = z.infer<typeof InteractionModeSchema>;
|
|
export type CodingAgentContext = z.infer<typeof CodingAgentContextSchema>;
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Validation helpers
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/** Result of a validation operation. */
|
|
export type ValidationResult<T> =
|
|
| { ok: true; data: T }
|
|
| { ok: false; errors: Array<{ path: string; message: string }> };
|
|
|
|
function formatValidationErrors(
|
|
issues: Array<{ path: Array<unknown>; message: string }>,
|
|
): Array<{ path: string; message: string }> {
|
|
return issues.map((issue) => ({
|
|
path: issue.path.join("."),
|
|
message: issue.message,
|
|
}));
|
|
}
|
|
|
|
/**
|
|
* Validate a coding agent context object.
|
|
* Returns a typed result with either the validated data or an array of errors.
|
|
*/
|
|
export function validateCodingAgentContext(
|
|
input: Record<string, unknown>,
|
|
): ValidationResult<CodingAgentContext> {
|
|
const result = CodingAgentContextSchema.safeParse(input);
|
|
if (result.success) {
|
|
return { ok: true, data: result.data };
|
|
}
|
|
return { ok: false, errors: formatValidationErrors(result.error.issues) };
|
|
}
|
|
|
|
/**
|
|
* Validate a single coding iteration.
|
|
*/
|
|
export function validateCodingIteration(
|
|
input: Record<string, unknown>,
|
|
): ValidationResult<CodingIteration> {
|
|
const result = CodingIterationSchema.safeParse(input);
|
|
if (result.success) {
|
|
return { ok: true, data: result.data };
|
|
}
|
|
return { ok: false, errors: formatValidationErrors(result.error.issues) };
|
|
}
|
|
|
|
/**
|
|
* Validate human feedback input.
|
|
*/
|
|
export function validateHumanFeedback(
|
|
input: Record<string, unknown>,
|
|
): ValidationResult<HumanFeedback> {
|
|
const result = HumanFeedbackSchema.safeParse(input);
|
|
if (result.success) {
|
|
return { ok: true, data: result.data };
|
|
}
|
|
return { ok: false, errors: formatValidationErrors(result.error.issues) };
|
|
}
|
|
|
|
/**
|
|
* Validate a connector configuration.
|
|
*/
|
|
export function validateConnectorConfig(
|
|
input: Record<string, unknown>,
|
|
): ValidationResult<ConnectorConfig> {
|
|
const result = ConnectorConfigSchema.safeParse(input);
|
|
if (result.success) {
|
|
return { ok: true, data: result.data };
|
|
}
|
|
return { ok: false, errors: formatValidationErrors(result.error.issues) };
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Context helpers
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/**
|
|
* Create a new coding agent context with sensible defaults.
|
|
*/
|
|
export function createCodingAgentContext(params: {
|
|
sessionId: string;
|
|
taskDescription: string;
|
|
workingDirectory: string;
|
|
connectorType: ConnectorType;
|
|
connectorBasePath: string;
|
|
interactionMode?: InteractionMode;
|
|
maxIterations?: number;
|
|
}): CodingAgentContext {
|
|
const now = Date.now();
|
|
return {
|
|
sessionId: params.sessionId,
|
|
taskDescription: params.taskDescription,
|
|
workingDirectory: params.workingDirectory,
|
|
connector: {
|
|
type: params.connectorType,
|
|
basePath: params.connectorBasePath,
|
|
available: true,
|
|
},
|
|
interactionMode: params.interactionMode ?? "fully-automated",
|
|
maxIterations: params.maxIterations ?? 10,
|
|
active: true,
|
|
iterations: [],
|
|
allFeedback: [],
|
|
createdAt: now,
|
|
updatedAt: now,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Check if the coding agent context has reached its iteration limit.
|
|
*/
|
|
export function hasReachedMaxIterations(ctx: CodingAgentContext): boolean {
|
|
return ctx.iterations.length >= ctx.maxIterations;
|
|
}
|
|
|
|
/**
|
|
* Check if the latest iteration resolved all errors.
|
|
*/
|
|
export function isLastIterationClean(ctx: CodingAgentContext): boolean {
|
|
if (ctx.iterations.length === 0) return true;
|
|
const last = ctx.iterations[ctx.iterations.length - 1];
|
|
if (!last) return true;
|
|
return last.errors.length === 0;
|
|
}
|
|
|
|
/**
|
|
* Get all unresolved errors from the latest iteration.
|
|
*/
|
|
export function getUnresolvedErrors(ctx: CodingAgentContext): CapturedError[] {
|
|
if (ctx.iterations.length === 0) return [];
|
|
const last = ctx.iterations[ctx.iterations.length - 1];
|
|
if (!last) return [];
|
|
return last.errors;
|
|
}
|
|
|
|
/**
|
|
* Add an iteration to the context and update the timestamp.
|
|
*/
|
|
export function addIteration(
|
|
ctx: CodingAgentContext,
|
|
iteration: CodingIteration,
|
|
): CodingAgentContext {
|
|
return {
|
|
...ctx,
|
|
iterations: [...ctx.iterations, iteration],
|
|
updatedAt: Date.now(),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Inject human feedback into the context.
|
|
*/
|
|
export function injectFeedback(
|
|
ctx: CodingAgentContext,
|
|
feedback: HumanFeedback,
|
|
): CodingAgentContext {
|
|
return {
|
|
...ctx,
|
|
allFeedback: [...ctx.allFeedback, feedback],
|
|
updatedAt: Date.now(),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Determine if the coding loop should continue based on context state.
|
|
*/
|
|
export function shouldContinueLoop(ctx: CodingAgentContext): {
|
|
shouldContinue: boolean;
|
|
reason: string;
|
|
} {
|
|
if (!ctx.active) {
|
|
return { shouldContinue: false, reason: "Session is no longer active" };
|
|
}
|
|
|
|
if (hasReachedMaxIterations(ctx)) {
|
|
return {
|
|
shouldContinue: false,
|
|
reason: `Reached maximum iterations (${ctx.maxIterations})`,
|
|
};
|
|
}
|
|
|
|
if (isLastIterationClean(ctx) && ctx.iterations.length > 0) {
|
|
return {
|
|
shouldContinue: false,
|
|
reason: "Last iteration completed without errors",
|
|
};
|
|
}
|
|
|
|
// Check for human rejection feedback that should halt the loop
|
|
const lastFeedback = ctx.allFeedback[ctx.allFeedback.length - 1];
|
|
if (lastFeedback?.type === "rejection") {
|
|
return {
|
|
shouldContinue: false,
|
|
reason: "User rejected the last iteration",
|
|
};
|
|
}
|
|
|
|
return { shouldContinue: true, reason: "Errors to resolve or work to do" };
|
|
}
|