SPB Git

Repository Public

deps.ts 4.0 KB 90 lines typescript

1/** Dependencies of the agent loop. Everything has a production default; tests inject fakes. */2import { getKernel, type Kernel } from '@aos/kernel';3import { catalogueEntry, getProvider, type ProviderAdapter } from '@aos/providers';4import type { Provider } from '@aos/shared';5import { TOOLS, type Tool } from '@aos/tools';67/** Tunables of the loop (CONTRACT §5). Changing one mid-run changes the logic's decisions: keep them stable per deployment. */8export interface EngineLimits {9  /** Consecutive turns without a tool call tolerated before the run ends `partial`. */10  maxNudges: number;11  /** Consecutive `max_tokens` / `pause` stops without a tool call before the run ends `partial`. */12  maxContinuations: number;13  /** Identical tool call + identical result, N times in a row ⇒ stall. */14  stallRepeat: number;15  /** Model turns without a successful write / commit / criterion change ⇒ stall. */16  stallTurns: number;17  /** Fraction of the usd / turn / wall budget at which the model gets its single final summarising turn. */18  finalTurnFraction: number;19  /** Fractions of the model's context window: operator note to wrap up, then `partial`. */20  contextWarnFraction: number;21  contextStopFraction: number;22  /** Durable back-off (ms) before re-trying a model call that failed with a retryable provider error. */23  modelRetryDelaysMs: number[];24  /** Project instruction file cap (bytes). */25  instructionsMaxBytes: number;26}2728export const DEFAULT_LIMITS: EngineLimits = {29  maxNudges: 2,30  maxContinuations: 3,31  stallRepeat: 3,32  stallTurns: 15,33  finalTurnFraction: 0.9,34  contextWarnFraction: 0.7,35  contextStopFraction: 0.9,36  modelRetryDelaysMs: [30_000, 120_000, 300_000],37  instructionsMaxBytes: 32 * 1024,38};3940export interface EngineDeps {41  /** Default: the process-wide kernel (DATABASE_URL / AOS_DATA_DIR). */42  kernel?: Kernel;43  /** Default: `getProvider` (API keys read from the environment on first use). */44  provider?: (id: Provider) => ProviderAdapter;45  /** Default: the `@aos/tools` registry. Order of this record = order presented to the model. */46  tools?: Record<string, Tool>;47  /** Context window (tokens) of a model; null = unknown ⇒ no context guard. Default: the provider catalogue. */48  contextWindow?: (provider: Provider, model: string) => number | null;49  /** Default: env AOS_WORKSPACE_ROOT. Sibling project directories under it are unreadable from the sandbox. */50  workspaceRoot?: string;51  /** Extra absolute paths the sandboxed shell must not read. Default: env AOS_SANDBOX_EXTRA_DENY_READ (comma list). */52  extraDenyRead?: string[];53  /** Deny the owner's ~/Desktop, ~/Documents, ~/Downloads to the sandbox when they exist. Default true. */54  denyOwnerFolders?: boolean;55  /** Test hook: path of the sandbox launcher (proves fail-closed behaviour). */56  sandboxExecPath?: string;57  limits?: Partial<EngineLimits>;58  maxOutputTokens?: number;59}6061export interface ResolvedDeps {62  kernel: Kernel;63  provider: (id: Provider) => ProviderAdapter;64  tools: Record<string, Tool>;65  contextWindow: (provider: Provider, model: string) => number | null;66  workspaceRoot: string | null;67  extraDenyRead: string[];68  denyOwnerFolders: boolean;69  sandboxExecPath: string | undefined;70  limits: EngineLimits;71  maxOutputTokens: number | undefined;72}7374const commaList = (v: string | undefined): string[] => (v ?? '').split(',').map((s) => s.trim()).filter((s) => s.length > 0);7576export function resolveDeps(deps: EngineDeps = {}): ResolvedDeps {77  return {78    kernel: deps.kernel ?? getKernel(),79    provider: deps.provider ?? getProvider,80    tools: deps.tools ?? TOOLS,81    contextWindow: deps.contextWindow ?? ((p, m) => catalogueEntry(p, m)?.contextTokens ?? null),82    workspaceRoot: deps.workspaceRoot ?? process.env.AOS_WORKSPACE_ROOT ?? null,83    extraDenyRead: deps.extraDenyRead ?? commaList(process.env.AOS_SANDBOX_EXTRA_DENY_READ),84    denyOwnerFolders: deps.denyOwnerFolders ?? true,85    sandboxExecPath: deps.sandboxExecPath,86    limits: { ...DEFAULT_LIMITS, ...(deps.limits ?? {}) },87    maxOutputTokens: deps.maxOutputTokens,88  };89}90
Files main
Menu

Theme