Files
elizaos--eliza/plugins/plugin-coding-tools/src/services/coding-agent-context.ts
T
wehub-resource-sync 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
chore: import upstream snapshot with attribution
2026-07-13 12:43:05 +08:00

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" };
}