Documentation
¶
Overview ¶
Package agent implements the agentic scan engine that powers the autopilot, swarm, and query modes. It owns prompt templates and rendering, context enrichment, the autopilot pipeline and swarm runners, structured output parsing (findings, HTTP records, attack plans, triage results, source analysis), and ingestion of results into the database. All AI dispatch is routed through the in-process olium engine via olium_adapter.go; there are no subprocess SDK backends. See docs/agentic-scan/agent-mode.md.
Index ¶
- Constants
- Variables
- func ApplyAuthOverrideToAudit(inv *agenttypes.AuditDriverInvocation, o agenttypes.AuthOverride)
- func AuditDriverCLIAvailable(a AuditDriverAgent) (string, bool)
- func CleanupOrphanedProcesses(sessionsDir string) int
- func CleanupStaleTempDirs()
- func CopySkillsToSessionDir(sessionDir string)
- func DriverIncludesAudit(driver string) bool
- func DriverIncludesPiolium(driver string) bool
- func EnsureSessionDir(baseDir, agenticScanUUID string) (string, error)
- func ExtraHeadersFromAuth(cfg *AgentSessionConfig) map[string]string
- func FirstMode(modes []string) string
- func ForceAuditDriverAgent(inv *AuditDriverInvocation, agentOverride string)
- func IsMultiDriverAudit(driver string) bool
- func IsProcessAlive(pid int) bool
- func IsSharedAuditMode(mode string) bool
- func IsValidAuditDriver(driver string) bool
- func IsValidAuditDriverAgent(s string) bool
- func IsValidAuditDriverMode(mode string) bool
- func IsValidAuditDriverPlatform(platform string) bool
- func JoinModes(modes []string) string
- func ParseModesCSV(s string) []string
- func PiAuthEnv(o agenttypes.AuthOverride) []string
- func RecordsForPrefixes(records []*httpmsg.HttpRequestResponse, prefixes []string) []*httpmsg.HttpRequestResponse
- func RefusalError(verdict GuardrailVerdict) error
- func RemoveRunPID(sessionDir string)
- func ResolveAuditAgentConfig(noAudit bool, mode string, sourcePath string, agentCfg config.AuditAgentConfig) *config.AuditAgentConfig
- func ResolveAuditDriverIntensity(intensity agenttypes.Intensity, current agenttypes.AuditDriverIntensityPreset, ...) agenttypes.AuditDriverIntensityPreset
- func ResolveAuthAgent(providerOrAgentOverride, oliumProvider string) string
- func ResolveAutopilotIntensity(intensity agenttypes.Intensity, current agenttypes.AutopilotIntensityPreset, ...) agenttypes.AutopilotIntensityPreset
- func ResolveModulesFromPlan(tags []string, ids []string) []string
- func ResolveNativeScanIntensity(intensityStr string) (profileName string, resolvedIntensity string, err error)
- func ResolvePioliumAuditConfig(mode, sourcePath string) *config.AuditAgentConfig
- func ResolveSwarmIntensity(intensity agenttypes.Intensity, current agenttypes.SwarmIntensityPreset, ...) agenttypes.SwarmIntensityPreset
- func RunAuditDriverInteractive(ctx context.Context, cfg AuditAgentConfig) error
- func SwarmPhaseDescription(phase string) string
- func SwarmPhasePrompt(phase string) string
- func ToHTTPRequestResponse(rec AgentHTTPRecord) (*httpmsg.HttpRequestResponse, error)
- func ValidateAuditDriverInvocation(inv AuditDriverInvocation) error
- func ValidateAuditDriverMode(driver, mode string, ...) error
- func ValidateAuditDriverModes(driver string, modes []string, ...) (auditChain, pioliumChain []string, err error)
- func ValidateAuthOverride(o agenttypes.AuthOverride) error
- func WrapProviderWithSemaphore(cfg *config.OliumConfig, p provider.Provider) provider.Provider
- func WriteAuthConfigYAML(sessionDir string, cfg *AgentSessionConfig) (string, error)
- func WriteCheckpointToDir(sessionDir string, cp *SwarmCheckpoint) error
- func WriteExtensionsToSessionDir(extensions []GeneratedExtension, sessionDir string) (string, error)
- func WriteExtensionsToTempDir(extensions []GeneratedExtension, prefix string) (string, error)
- func WriteRunPID(sessionDir string) error
- func WriteSwarmCoverageReport(sessionDir string, report *SwarmCoverageReport) string
- type AgentExpectResponse
- type AgentExtensionsOutput
- type AgentExtractRule
- type AgentFinding
- type AgentFindingsOutput
- type AgentHTTPRecord
- type AgentHTTPRecordsOutput
- type AgentLoginFlow
- type AgentRuntime
- type AgentSession
- type AgentSessionConfig
- type AgentSessionEntry
- type AppIntent
- type AttackPlan
- type AuditAgentConfig
- type AuditAgentStatus
- type AuditAgenticScanner
- func (r *AuditAgenticScanner) AgenticScanUUID() string
- func (r *AuditAgenticScanner) Cancel()
- func (r *AuditAgenticScanner) CostSummary() ScanCost
- func (r *AuditAgenticScanner) Done() <-chan struct{}
- func (r *AuditAgenticScanner) FindingStats() FindingStats
- func (r *AuditAgenticScanner) Harness() HarnessSpec
- func (r *AuditAgenticScanner) ProcessStartedAt() time.Time
- func (r *AuditAgenticScanner) Start(ctx context.Context) error
- func (r *AuditAgenticScanner) Status() *AuditAgentStatus
- func (r *AuditAgenticScanner) Wait() error
- type AuditDriverAgent
- type AuditDriverAuthFlags
- type AuditDriverCfgInput
- type AuditDriverIntensityPreset
- type AuditDriverInvocation
- type AuditRunner
- type AuthOverride
- type AutopilotArtifactSpec
- type AutopilotAuthFlow
- type AutopilotContextBundle
- type AutopilotExecutionPlan
- type AutopilotFindingSummary
- type AutopilotIntensityPreset
- type AutopilotPipelineConfig
- type AutopilotPipelineResult
- type AutopilotPipelineRunner
- type AutopilotPlanTask
- type AutopilotPreparedAuth
- type AutopilotRouteSummary
- type AutopilotTriageParams
- type AutopilotVerificationReport
- type BatchProvenance
- type BurpBridgeToolSpec
- type CoverageProbe
- type CoverageProbeResult
- type CoverageReportInputs
- type Engine
- func (e *Engine) InvalidateContextCache()
- func (e *Engine) Preflight(agentName string) error
- func (e *Engine) ResetTokenUsage()
- func (e *Engine) Run(ctx context.Context, opts Options) (*Result, error)
- func (e *Engine) RunOnOliumEngine(ctx context.Context, opts Options, sess AgentSession) (*Result, error)
- func (e *Engine) RunSourceAnalysisParallel(ctx context.Context, cfg SourceAnalysisConfig) (saResult *SourceAnalysisResult, rawOutput string, renderedPrompt string, ...)
- func (e *Engine) RunWithExtra(ctx context.Context, opts Options, extra map[string]string) (*Result, error)
- func (e *Engine) RunWithExtraSkills(ctx context.Context, opts Options, extra map[string]string, ...) (*Result, error)
- func (e *Engine) RunWithSkills(ctx context.Context, opts Options, reg *skill.Registry) (*Result, error)
- func (e *Engine) SetContextCache(cache *agentprompt.ContextCache)
- func (e *Engine) TokenUsage() agenttypes.TokenUsage
- type ExploitationEvidence
- type ExtensionMergeResult
- type FindingStats
- type FollowUpScan
- type GeneratedExtension
- type GuardrailVerdict
- type HarnessSpec
- type InputType
- type Intensity
- type IntentCredentialSet
- type IntentParseConfig
- type IntentParseOption
- type InvalidExtension
- type Options
- type PioliumChainScanner
- func (p *PioliumChainScanner) AgenticScanUUID() string
- func (p *PioliumChainScanner) Cancel()
- func (p *PioliumChainScanner) CostSummary() ScanCost
- func (p *PioliumChainScanner) Done() <-chan struct{}
- func (p *PioliumChainScanner) FindingStats() FindingStats
- func (p *PioliumChainScanner) Start(ctx context.Context) error
- func (p *PioliumChainScanner) Status() *AuditAgentStatus
- func (p *PioliumChainScanner) Wait() error
- type PioliumSweepEntry
- type PioliumSweepResult
- type PlanCoverage
- type PlannedEndpoint
- type PrefixCoverage
- type ProbeConfig
- type ProgressEvent
- type PromptTemplate
- type QuickCheck
- type QuickCheckLintIssue
- type QuickCheckMatch
- type QuickCheckRequest
- type RecordSpec
- type RepairConfig
- type Result
- type RetryConfig
- type RunPID
- type ScanCost
- type ScanFunc
- type ScanIntent
- func ParseAndResolveIntent(ctx context.Context, engine *Engine, prompt string, opts ...IntentParseOption) (*ScanIntent, error)
- func ParseScanIntent(ctx context.Context, engine *Engine, prompt string, opts ...IntentParseOption) (*ScanIntent, error)
- func ParseScanIntentWithSetup(ctx context.Context, engine *Engine, prompt string, sessionsDir string) (*ScanIntent, error)
- func ResolveIntentApps(intent *ScanIntent) *ScanIntent
- type ScanRequest
- type SessionSpec
- type SetupCleanup
- type Snippet
- type SourceAnalysisConfig
- type SourceAnalysisResult
- type SwarmCheckpoint
- type SwarmConfig
- type SwarmCoveragePlan
- type SwarmCoverageReport
- type SwarmIntensityPreset
- type SwarmPlan
- type SwarmResult
- type SwarmRunner
- type TemplateData
- type TokenUsage
- type TriageConfirmResult
- type TriageLoopConfig
- type TriageLoopResult
- type TriageResult
- type TriagedFinding
- type VerifyCandidatesConfig
- type VerifyCandidatesResult
- type VigToolSpec
Constants ¶
const ( AuditDriverAgentClaude = agenttypes.AuditDriverAgentClaude AuditDriverAgentCodex = agenttypes.AuditDriverAgentCodex )
const ( // Evidence status EvidenceStatusExploited = agenttypes.EvidenceStatusExploited EvidenceStatusBlocked = agenttypes.EvidenceStatusBlocked EvidenceStatusFalsePositive = agenttypes.EvidenceStatusFalsePositive // InputType InputTypeURL = agenttypes.InputTypeURL InputTypeCurl = agenttypes.InputTypeCurl InputTypeBurp = agenttypes.InputTypeBurp InputTypeRaw = agenttypes.InputTypeRaw InputTypeBase64 = agenttypes.InputTypeBase64 InputTypeRecordUUID = agenttypes.InputTypeRecordUUID InputTypeUnknown = agenttypes.InputTypeUnknown // Intensity IntensityQuick = agenttypes.IntensityQuick IntensityBalanced = agenttypes.IntensityBalanced IntensityDeep = agenttypes.IntensityDeep // Triage confirm verdict + template identifiers TriageVerdictConfirmed = agenttypes.TriageVerdictConfirmed TriageVerdictFalsePositive = agenttypes.TriageVerdictFalsePositive TriageConfirmTemplateID = agenttypes.TriageConfirmTemplateID TriageConfirmOutputSchema = agenttypes.TriageConfirmOutputSchema // SwarmPhase SwarmPhaseNormalize = agenttypes.SwarmPhaseNormalize SwarmPhaseAuth = agenttypes.SwarmPhaseAuth SwarmPhaseSourceAnalysis = agenttypes.SwarmPhaseSourceAnalysis SwarmPhaseCodeAudit = agenttypes.SwarmPhaseCodeAudit SwarmPhaseDiscover = agenttypes.SwarmPhaseDiscover SwarmPhaseRecon = agenttypes.SwarmPhaseRecon SwarmPhasePlan = agenttypes.SwarmPhasePlan SwarmPhaseExtension = agenttypes.SwarmPhaseExtension SwarmPhaseScan = agenttypes.SwarmPhaseScan SwarmPhaseDiscoverReentry = agenttypes.SwarmPhaseDiscoverReentry SwarmPhaseReplanOnEmpty = agenttypes.SwarmPhaseReplanOnEmpty SwarmPhaseTriage = agenttypes.SwarmPhaseTriage SwarmPhaseRescan = agenttypes.SwarmPhaseRescan RecordSourceDiscoverReentry = agenttypes.RecordSourceDiscoverReentry )
Re-export constants. Go type aliases preserve constant compatibility for typed constants, but untyped string constants must be re-declared.
const ( AuditDriverPiolium = "piolium" AuditDriverAudit = "audit" AuditDriverBoth = "both" // AuditDriverAuto is the default. A preflight picks the leg: when the // resolved coding-agent CLI (claude or codex) is on PATH, the audit // binary is embedded, and the mode chain holds at least one // audit-supported mode, audit runs and piolium is never consulted. // If any of those checks fails, audit is skipped without ever being // launched and piolium runs as the fallback. // // A mid-run audit failure is deliberately NOT a fallback trigger: // once audit starts, its outcome is the run's outcome. Because a // clean audit run never consults piolium, a missing piolium runtime // is not reported up front. AuditDriverAuto = "auto" )
Audit driver IDs for the unified `vigolium agent audit` and `POST /api/agent/run/audit` dispatcher. The JSON `driver` field on `AgentAuditRequest` accepts these values verbatim, and `vigolium agent audit --driver=...` mirrors the same set, so they live here as the single source of truth shared by CLI and server packages.
const ( SwarmPromptPlan = "agent-swarm-plan" SwarmPromptExtensions = "agent-swarm-extensions" SwarmPromptCodeAudit = "swarm-code-audit" SwarmPromptTriage = "agent-swarm-triage" SwarmPromptAuth = "agent-swarm-auth" )
Prompt template constants for the agent swarm mode.
const AuditDedupTimeout = 30 * time.Second
AuditDedupTimeout caps the post-pass project-wide findings dedup so a large findings table can't stall the orchestrator's exit. Failure is logged-and-swallowed; the audit still reports completion.
const DefaultAuditSyncInterval = 30 * time.Second
DefaultAuditSyncInterval is the per-runner audit-state.json sync cadence used by every audit dispatcher entry point.
const PlatformAuditBin = "audit"
PlatformAuditBin identifies the embedded vigolium-audit binary as the audit runner. vigolium-audit dispatches to claude or codex internally; the per-run agent comes from AuditAgentConfig.AuditDriverInvocation.
const PlatformPi = "pi"
PlatformPi is the Pi runtime platform — runs piolium via `pi --mode json`.
Variables ¶
var ( NormalizeSwarmPhase = agenttypes.NormalizeSwarmPhase PhaseSkipped = agenttypes.PhaseSkipped WithSessionsDir = agenttypes.WithSessionsDir ValidateIntensity = agenttypes.ValidateIntensity NativeScanIntensityProfiles = agenttypes.NativeScanIntensityProfiles )
Re-export functions with external consumers.
var ( CleanupSessionDirs = authsession.CleanupSessionDirs AgentSessionConfigToSessions = authsession.AgentSessionConfigToSessions )
Re-export backend utilities with external consumers. These are session / auth-header helpers that survived the subprocess removal.
var ( ParseFindings = parsing.ParseFindings ParseHTTPRecords = parsing.ParseHTTPRecords ParseTriageConfirmResult = parsing.ParseTriageConfirmResult ToDBFinding = parsing.ToDBFinding )
Re-export parsing functions with external consumers.
var ( TargetURLFromInput = agentinput.TargetURLFromInput ParsePlanFile = agentinput.ParsePlanFile )
Re-export input functions with external consumers.
var ( ListTemplates = agentprompt.ListTemplates ResolveTemplatePath = agentprompt.ResolveTemplatePath )
Re-export prompt functions with external consumers.
var ( // WithCloneDepth sets the git clone depth for remote sources. WithCloneDepth = source.WithCloneDepth // ResolveSourceAndDiff resolves a --source and optional --diff into a local // path, changed-file list, and diff context. ResolveSourceAndDiff = source.ResolveSourceAndDiff // DetectTargetFromSource infers a running app URL from a source tree. DetectTargetFromSource = source.DetectTargetFromSource )
var ErrPromptRefused = errors.New("prompt refused by guardrail")
ErrPromptRefused is returned when the safety classifier rejects a prompt. Wrapped with the verdict reason so callers can errors.Is + read the cause.
Functions ¶
func ApplyAuthOverrideToAudit ¶
func ApplyAuthOverrideToAudit(inv *agenttypes.AuditDriverInvocation, o agenttypes.AuthOverride)
ApplyAuthOverrideToAudit folds a BYOK override into an AuditDriverInvocation in-place. When the override is empty the invocation is unchanged (preserving the agent.olium.* derived auth). When set, the override REPLACES whatever the resolver derived from olium config — including clearing fields the override doesn't touch, so a half-set audit auth from olium (e.g. an OAuthCredFile) doesn't leak into a run where the operator passed --oauth-token.
func AuditDriverCLIAvailable ¶
func AuditDriverCLIAvailable(a AuditDriverAgent) (string, bool)
AuditDriverCLIAvailable reports whether the coding-agent CLI that vigolium-audit will drive (claude or codex) is on PATH for the given resolved agent. Empty defaults to claude (vigolium-audit's own default). Used by --driver=auto to skip the audit leg without launching the embedded binary when its required CLI is missing.
func CleanupOrphanedProcesses ¶
CleanupOrphanedProcesses scans session directories for run.pid files and cleans up orphaned agent processes.
A run.pid records the OWNING vigolium process's PID/PGID. An "orphan" is a run whose owner has DIED but which may have left agent subprocesses alive in its process group. So:
- If the recorded PID is still ALIVE it is NOT an orphan — it is either a legitimately running concurrent vigolium instance or an unrelated process that reused the PID. Either way we must not kill it. (The previous logic killed alive PIDs, so starting a second run could terminate a live first run or an unrelated process after PID reuse.)
- If the recorded PID is DEAD, the run is orphaned: reap any subprocesses that outlived it in its process group, then remove the stale PID file.
Returns the number of sessions cleaned up.
func CleanupStaleTempDirs ¶
func CleanupStaleTempDirs()
CleanupStaleTempDirs removes orphaned vigolium temp directories older than 24 hours.
func CopySkillsToSessionDir ¶
func CopySkillsToSessionDir(sessionDir string)
CopySkillsToSessionDir copies embedded skill files to the session directory so the agent can discover them from its working directory.
func DriverIncludesAudit ¶
DriverIncludesAudit reports whether the audit driver runs audit.
func DriverIncludesPiolium ¶
DriverIncludesPiolium reports whether the audit driver may run piolium. For "auto" piolium only runs as an audit fallback, but it is still in the potential driver set, so mode/auth validation treats it as included.
func EnsureSessionDir ¶
EnsureSessionDir creates the session directory for a given run ID under the specified base directory. If baseDir is empty, defaults to ~/.vigolium/agent-sessions/. Returns the absolute path to the created directory.
func ExtraHeadersFromAuth ¶
func ExtraHeadersFromAuth(cfg *AgentSessionConfig) map[string]string
ExtraHeadersFromAuth returns the primary session's static headers as a map. Login entries are ignored — replaying logins is the auth phase's job, not recon's.
func FirstMode ¶
FirstMode returns the first mode of a chain, or "" for an empty chain. Used to keep AuditAgentConfig.Mode populated alongside Modes for the single-mode consumers that never chain.
func ForceAuditDriverAgent ¶
func ForceAuditDriverAgent(inv *AuditDriverInvocation, agentOverride string)
ForceAuditDriverAgent layers the CLI --agent flag on top of an already resolved invocation. It is a *pure agent selector*: when agentOverride is a valid audit agent (claude|codex) it replaces inv.Agent only, leaving the provider-derived auth on inv untouched. This is what makes `--provider <p> --agent <a>` keep <p>'s BYOK auth while running agent <a>. An empty or invalid override is a no-op, so the resolver's provider-derived agent stands (callers validate up front and surface a clear error for genuinely bad input).
func IsMultiDriverAudit ¶
IsMultiDriverAudit reports whether the driver can dispatch both harnesses in one run (so per-driver auth overrides are allowed, the shared-mode restriction applies, and a missing single runtime is a warning rather than a hard error). True for "both" and "auto".
func IsProcessAlive ¶
IsProcessAlive checks whether a process with the given PID is still running.
func IsSharedAuditMode ¶
IsSharedAuditMode returns true when the given audit mode is supported by both audit and piolium harnesses. Used by the unified audit dispatcher to validate `--driver=both` runs, where the same mode is dispatched to each driver in turn.
func IsValidAuditDriver ¶
IsValidAuditDriver reports whether driver is a recognized audit driver.
func IsValidAuditDriverAgent ¶
IsValidAuditDriverAgent reports whether s is a recognized audit `--agent` value (claude|codex). Used by CLI / REST validation of the --provider override.
func IsValidAuditDriverMode ¶
IsValidAuditDriverMode reports whether mode is a recognized audit mode.
func IsValidAuditDriverPlatform ¶
IsValidAuditDriverPlatform reports whether platform is a recognized audit agent identifier. Same set as IsValidAuditDriverAgent plus the empty string, which is treated as "inherit agent from olium config" by the resolver.
func JoinModes ¶
JoinModes renders a mode chain back to the comma-separated form audit's `--modes` flag expects and the audit banner / DB Mode column display.
func ParseModesCSV ¶
ParseModesCSV splits a comma-separated --modes value into a clean, order-preserving, de-duplicated slice. Whitespace around each token is trimmed and empty tokens are dropped. A bare "" returns nil so callers can fall back to the single --mode / intensity-derived value.
func PiAuthEnv ¶
func PiAuthEnv(o agenttypes.AuthOverride) []string
PiAuthEnv maps the BYOK override into the env vars `pi`'s provider drivers honor.
For api_key / oauth_token: returns one or two KEY=VALUE entries the caller should append to the pi subprocess env. The function never sets the env in-process — vigolium injects per-subprocess so concurrent runs don't trample one another.
For oauth_cred_file: returns nil. Codex doesn't read the file from an env var; vigolium stages it under <pi-agent-dir>/auth.json (handled by the launcher in pkg/agent/audit_agent.go) so the codex provider picks it up via its standard read path.
Returns nil for an empty override (no env injection needed).
func RecordsForPrefixes ¶
func RecordsForPrefixes(records []*httpmsg.HttpRequestResponse, prefixes []string) []*httpmsg.HttpRequestResponse
func RefusalError ¶
func RefusalError(verdict GuardrailVerdict) error
RefusalError wraps ErrPromptRefused with the verdict reason. Callers that want errors.Is(err, ErrPromptRefused) get it for free.
func RemoveRunPID ¶
func RemoveRunPID(sessionDir string)
RemoveRunPID removes the run.pid file from the session directory. Best-effort: errors are logged but not returned.
func ResolveAuditAgentConfig ¶
func ResolveAuditAgentConfig(noAudit bool, mode string, sourcePath string, agentCfg config.AuditAgentConfig) *config.AuditAgentConfig
Audit is enabled by default when source code is available. Pass noAudit=true to force-disable it (--no-audit flag). When the passed mode is empty it falls back to agentCfg.EffectiveMode() (balanced by default). Returns nil when the audit agent should not run.
func ResolveAuditDriverIntensity ¶
func ResolveAuditDriverIntensity(intensity agenttypes.Intensity, current agenttypes.AuditDriverIntensityPreset, changed map[string]bool) agenttypes.AuditDriverIntensityPreset
ResolveAuditDriverIntensity merges intensity preset values with user-provided overrides. The changed map indicates which fields were explicitly set by the user (CLI flag or API field). Explicit values in current take precedence over the preset.
Note: audit also accepts operational modes (revisit, confirm, merge, diff, status, mock) that are not intensity-driven. Callers must pass changed["mode"]=true (or changed["modes"]=true for a chain) when the user supplied an explicit --mode / --modes field, which then bypasses the preset's chain entirely.
Mode and Modes are kept consistent on the result: Mode is always Modes[0] so single-mode consumers stay correct even when a chain preset is selected.
func ResolveAuthAgent ¶
ResolveAuthAgent picks the audit-style agent identity ("claude" or "codex") that BYOK creds should target, given the optional CLI/REST override and the configured olium provider. Centralized so the CLI, REST, and any future entry point all answer "is this a claude or codex key?" the same way.
CLI and REST feed semantically different inputs here:
- CLI passes --provider, a provider name like "openai-codex-oauth" → mapped via auditAgentSelFromProvider.
- REST passes req.Agent, a direct agent name ("claude" | "codex") validated upstream by IsValidAuditDriverPlatform.
We accept both forms: a direct agent name short-circuits the provider-prefix mapping, so REST's `agent:"codex"` correctly resolves to "codex" instead of falling through to the default ("claude") and silently bypassing the validator's oauth_token-needs-claude rule.
Precedence:
- providerOrAgentOverride (--provider or req.Agent)
- oliumProvider → auditAgentSelFromProvider
- Default → "claude"
func ResolveAutopilotIntensity ¶
func ResolveAutopilotIntensity(intensity agenttypes.Intensity, current agenttypes.AutopilotIntensityPreset, changed map[string]bool) agenttypes.AutopilotIntensityPreset
ResolveAutopilotIntensity merges intensity preset values with user-provided overrides. The changed map indicates which fields were explicitly set by the user (CLI flag or API field). Explicit values in current take precedence over the preset.
func ResolveModulesFromPlan ¶
ResolveModulesFromPlan converts agent-suggested tags and IDs into a deduplicated module ID list. Falls back to ["all"] when no modules are resolved.
func ResolveNativeScanIntensity ¶
func ResolveNativeScanIntensity(intensityStr string) (profileName string, resolvedIntensity string, err error)
ResolveNativeScanIntensity validates the intensity string and returns the corresponding scanning profile name. It also sets opts.Intensity for logging.
func ResolvePioliumAuditConfig ¶
func ResolvePioliumAuditConfig(mode, sourcePath string) *config.AuditAgentConfig
ResolvePioliumAuditConfig is the piolium counterpart of ResolveAuditAgentConfig: returns nil when the audit should not run (mode empty/"off" or no source). The returned cfg is intentionally minimal — Platform and StreamDecoder are auto-installed inside StartAuditAgent based on the harness it receives.
func ResolveSwarmIntensity ¶
func ResolveSwarmIntensity(intensity agenttypes.Intensity, current agenttypes.SwarmIntensityPreset, changed map[string]bool) agenttypes.SwarmIntensityPreset
ResolveSwarmIntensity merges intensity preset values with user-provided overrides. The changed map indicates which fields were explicitly set by the user (CLI flag or API field). Explicit values in current take precedence over the preset.
func RunAuditDriverInteractive ¶
func RunAuditDriverInteractive(ctx context.Context, cfg AuditAgentConfig) error
RunAuditDriverInteractive launches the embedded vigolium-audit binary in interactive mode (`-i`) attached to the caller's terminal, then blocks until it exits.
This is the "drop into the coding agent" path: audit's `-i` installs its harness (agent defs + slash commands) into the coding agent and hands the terminal to the user, who drives the audit themselves inside Claude/Codex. Because the operator owns the session, vigolium does NOT decode an NDJSON stream, create an AgenticScan row, or auto-import findings here — audit writes its results to <source>/audit/ and the operator imports them afterward (`vigolium import <source>/audit`).
The command is built through the same buildAuditAgentCommand path as a headless run so --target / --mode|--modes / --agent / auth flags stay identical; the only differences are stream=false (no --json — interactive replaces the machine log) and the appended -i.
func SwarmPhaseDescription ¶
SwarmPhaseDescription returns a short description of what a swarm phase does.
func SwarmPhasePrompt ¶
SwarmPhasePrompt returns the prompt template name for a given swarm phase, if any.
func ToHTTPRequestResponse ¶
func ToHTTPRequestResponse(rec AgentHTTPRecord) (*httpmsg.HttpRequestResponse, error)
ToHTTPRequestResponse converts an AgentHTTPRecord to an httpmsg.HttpRequestResponse.
func ValidateAuditDriverInvocation ¶
func ValidateAuditDriverInvocation(inv AuditDriverInvocation) error
ValidateAuditDriverInvocation checks that the resolved auth is usable by the resolved agent. A pure agent selector — the `--agent` flag or agent.audit.default_agent — flips inv.Agent while deliberately keeping the provider/BYOK-derived auth, so it can pair codex with an Anthropic OAuth token (claude-only), which vigolium-audit rejects mid-run. Catching it here turns that into a clear pre-flight error.
Only the OAuthToken→claude rule is enforced, mirroring ValidateAuthOverride: API keys are agent-agnostic at this layer, and a codex cred file paired with claude is left to vigolium-audit so the documented "--agent keeps the resolved auth" contract is preserved. Returns nil when no auth is set or it is compatible.
func ValidateAuditDriverMode ¶
func ValidateAuditDriverMode(driver, mode string, modeIsValidForPiolium, modeIsValidForAudit func(string) bool) error
ValidateAuditDriverMode returns an error when mode is not valid for the given audit driver. driver=both restricts to the shared set so both runners can dispatch the same mode without coercion surprises; single-driver invocations accept the driver's full mode set.
modeIsValidForPiolium and modeIsValidForAudit are injected to avoid dragging the piolium and audit driver-specific validators into pkg/agent's import graph.
func ValidateAuditDriverModes ¶
func ValidateAuditDriverModes(driver string, modes []string, modeIsValidForPiolium, modeIsValidForAudit func(string) bool) (auditChain, pioliumChain []string, err error)
ValidateAuditDriverModes validates a mode chain for the given driver and returns the per-driver filtered chains (audit's modes first, then piolium's). A mode invalid for BOTH drivers is always an error (typo guard). For an explicit single driver every mode must be valid for that driver — silently dropping one the operator asked for would be surprising. For multi-driver paths (auto/both) each mode only has to be valid for at least one driver; per-driver-unsupported modes are skipped on that driver's leg.
func ValidateAuthOverride ¶
func ValidateAuthOverride(o agenttypes.AuthOverride) error
ValidateAuthOverride enforces the BYOK rules shared by CLI and REST:
- At most one of APIKey / OAuthToken / OAuthCredFile is set. Mixing them is almost always an operator mistake and the harness can only honor one at a time anyway.
- OAuthToken requires the claude side. OpenAI/codex has no equivalent bearer token form (codex uses cred files), so this catches the cross-wire of pasting an Anthropic OAuth token into a codex run.
The Agent field on the override drives rule 2. Empty defaults to claude (matches audit's own default + the audit resolver's behavior).
Returns nil for an entirely-empty override, since "inherit ambient agent.olium.* config" is the documented no-op behavior.
func WrapProviderWithSemaphore ¶
WrapProviderWithSemaphore returns a provider.Provider that gates each Stream call through the shared oliumProviderSem. Use this around the resolved provider before passing it into long-running loops (autopilot) so their per-turn LLM calls participate in the same process-wide cap as the swarm/source-analysis paths — without this, autopilot bypasses the limiter and N concurrent sessions can flood the provider with 429s.
The slot is held only for the duration of one Stream (one model turn), not the whole run, so a multi-hour autopilot doesn't pin a slot.
func WriteAuthConfigYAML ¶
func WriteAuthConfigYAML(sessionDir string, cfg *AgentSessionConfig) (string, error)
func WriteCheckpointToDir ¶
func WriteCheckpointToDir(sessionDir string, cp *SwarmCheckpoint) error
WriteCheckpointToDir persists a SwarmCheckpoint to the session directory (exported for CLI use).
func WriteExtensionsToSessionDir ¶
func WriteExtensionsToSessionDir(extensions []GeneratedExtension, sessionDir string) (string, error)
WriteExtensionsToSessionDir writes generated JavaScript extensions to <sessionDir>/extensions/ and returns the extensions subdirectory path.
func WriteExtensionsToTempDir ¶
func WriteExtensionsToTempDir(extensions []GeneratedExtension, prefix string) (string, error)
WriteExtensionsToTempDir writes generated JavaScript extensions to a temporary directory and returns the directory path. Caller is responsible for cleanup.
func WriteRunPID ¶
WriteRunPID writes a run.pid JSON file to the given session directory.
func WriteSwarmCoverageReport ¶
func WriteSwarmCoverageReport(sessionDir string, report *SwarmCoverageReport) string
WriteSwarmCoverageReport writes the report to {sessionDir}/coverage.json and returns the path. I/O errors are logged and "" returned — a serialization hiccup must not fail a 12-hour scan.
Types ¶
type AgentExtensionsOutput ¶
type AgentExtensionsOutput = agenttypes.AgentExtensionsOutput
Pipeline types
type AgentFindingsOutput ¶
type AgentFindingsOutput = agenttypes.AgentFindingsOutput
Findings & HTTP records
type AgentHTTPRecordsOutput ¶
type AgentHTTPRecordsOutput = agenttypes.AgentHTTPRecordsOutput
Findings & HTTP records
type AgentRuntime ¶
type AgentRuntime interface {
// RunPrompt runs one prompt on a fresh session. When sourcePath is set it is
// appended to the system prompt so the agent knows it has filesystem access
// to local source. Text deltas mirror to streamWriter and reasoning deltas to
// thinkingWriter when those are non-nil. When rec.SessionDir is set, the
// fresh engine records a Pi-style JSONL transcript (flushed before return).
RunPrompt(ctx context.Context, cfg *config.OliumConfig, prompt string, streamWriter, thinkingWriter io.Writer, sourcePath string, verbose bool, rec RecordSpec) (oliumRunOutput, error)
// RunOnSession runs one prompt reusing an existing session's warm prefix.
// Unlike RunPrompt it takes no RecordSpec: a reused session's transcript
// recorder (if any) is attached once when the session is built
// (NewSessionWithSpec with a RecordSpec) and spans all of its prompts, then
// flushed by AgentSession.Close().
RunOnSession(ctx context.Context, cfg *config.OliumConfig, sess AgentSession, prompt string, streamWriter, thinkingWriter io.Writer, verbose bool) (oliumRunOutput, error)
// NewSession builds a reusable session without running anything. Equivalent
// to NewSessionWithSpec with the standard tool-enabled spec.
NewSession(cfg *config.OliumConfig, sourcePath string) (AgentSession, error)
// NewSessionWithSpec builds a session from an explicit SessionSpec, for
// specialized flows that need a custom system prompt, turn cap, or tool set.
NewSessionWithSpec(cfg *config.OliumConfig, spec SessionSpec) (AgentSession, error)
}
AgentRuntime abstracts AI dispatch so the agent engine depends on an interface rather than the concrete olium runtime. The default implementation (oliumRuntime) is backed by the in-process olium engine; tests can substitute a fake. This is the single seam between agent orchestration and the LLM runtime: concrete olium types live behind it (here and in olium_adapter.go), keeping the rest of pkg/agent free of a hard dependency on one runtime.
type AgentSession ¶
type AgentSession interface {
Fork() AgentSession
Close() error
}
AgentSession is an opaque, reusable agent conversation whose prefix (system prompt, tool definitions, prior turns) stays warm across prompts so the provider's prompt cache hits. Fork returns a child that shares the prefix but runs independently — used for parallel sub-runs such as the source-analysis fan-out.
Close flushes and releases any per-session artifact (notably the Pi-style JSONL transcript recorder): the recorder buffers the final assistant turn until the run ends, so a session built with a RecordSpec must be Closed for that turn to land. Sessions without a recorder Close to a no-op. Forks carry no recorder (concurrent sub-runs would interleave one file), so closing a fork is always a no-op.
type AgentSessionConfig ¶
type AgentSessionConfig = agenttypes.AgentSessionConfig
Pipeline types
func RepairInvalidSessionConfig ¶
func RepairInvalidSessionConfig(ctx context.Context, engine *Engine, original *AgentSessionConfig, targetURL string, cfg RepairConfig) *AgentSessionConfig
RepairInvalidSessionConfig uses an LLM to fix garbled session config entries. It stays in the root package because it depends on *Engine.
func SynthesizeAuthConfig ¶
func SynthesizeAuthConfig(cookies []string, headers []string, loginCurl string) (*AgentSessionConfig, error)
SynthesizeAuthConfig builds a single-session AgentSessionConfig from operator-supplied cookies, headers, and/or a login-curl. Returns (nil, nil) when all inputs are empty so callers can fall through to browser-auth or no-auth.
type AuditAgentConfig ¶
type AuditAgentConfig = agenttypes.AuditAgentConfig
Audit types
func BuildAuditDriverCfg ¶
func BuildAuditDriverCfg(in AuditDriverCfgInput) AuditAgentConfig
BuildAuditDriverCfg assembles the AuditAgentConfig that drives an audit run. Used by every entry point that launches audit (CLI agent dispatcher, server combined dispatcher) so the platform / invocation plumbing stays in one place.
type AuditAgenticScanner ¶
type AuditAgenticScanner struct {
// contains filtered or unexported fields
}
AuditAgenticScanner manages an vigolium-audit running as a background agent process. It launches the agent (Claude or Codex), periodically syncs audit-state.json and findings to the vigolium session dir, and imports findings into the database when complete.
func NewAuditAgenticScanner ¶
func NewAuditAgenticScanner(cfg AuditAgentConfig, repo *database.Repository) *AuditAgenticScanner
NewAuditAgenticScanner creates a new runner for the background vigolium-audit.
The AgenticScan DB row's UUID is derived as follows:
- Standalone audit (ParentAgenticScanUUID empty, SessionDir set): UUID is filepath.Base(cfg.SessionDir). This gives the invariant that `vigolium log <uuid>` and `vigolium log ls` resolve the session's runtime.log via the conventional `{sessions_dir}/{uuid}/` path.
- Nested audit (ParentAgenticScanUUID set, e.g. spawned by autopilot/swarm): a fresh UUID is generated. The parent already owns a row at filepath.Base(SessionDir), so the child must differ to avoid a primary-key collision on create. Resolution back to runtime.log relies on the child row's persisted SessionDir column instead.
- No SessionDir: a fresh UUID is generated.
func StartAuditAgent ¶
func StartAuditAgent(ctx context.Context, agentCfg config.AuditAgentConfig, harness HarnessSpec, sourcePath, sessionDir, projectUUID, scanUUID, parentAgenticScanUUID string, repo *database.Repository, streamWriter io.Writer) (*AuditAgenticScanner, error)
StartAuditAgent creates and starts a background audit run for the given harness (audit or piolium). Returns nil runner when the cfg is disabled or sourcePath is empty. When streamWriter is non-nil, audit output is streamed in real-time. Harness-specific bits (Platform=pi + StreamDecoder for piolium) are auto-installed when harness.Name == "piolium".
func (*AuditAgenticScanner) AgenticScanUUID ¶
func (r *AuditAgenticScanner) AgenticScanUUID() string
AgenticScanUUID returns the UUID of the AgenticScan row this runner owns. Useful for tests and callers that need to look up the row after Wait().
func (*AuditAgenticScanner) Cancel ¶
func (r *AuditAgenticScanner) Cancel()
Cancel stops the audit process. Sends SIGTERM first, then SIGKILL after a grace period.
func (*AuditAgenticScanner) CostSummary ¶
func (r *AuditAgenticScanner) CostSummary() ScanCost
CostSummary returns the priced token summary for this audit run. The zero value is returned when the run is still active, used an unsupported backend, or the backend transcript could not be parsed.
func (*AuditAgenticScanner) Done ¶
func (r *AuditAgenticScanner) Done() <-chan struct{}
Done returns a channel that closes when the audit finishes.
func (*AuditAgenticScanner) FindingStats ¶
func (r *AuditAgenticScanner) FindingStats() FindingStats
FindingStats returns the summary of findings parsed and imported by this audit run. Only populated after monitor() has completed.
func (*AuditAgenticScanner) Harness ¶
func (r *AuditAgenticScanner) Harness() HarnessSpec
Harness returns the harness spec the runner was configured with. Lets callers label output and tag findings without re-reading config or hard-coding harness names like "piolium" / "audit".
func (*AuditAgenticScanner) ProcessStartedAt ¶
func (r *AuditAgenticScanner) ProcessStartedAt() time.Time
ProcessStartedAt returns the wall time the audit subprocess was launched. Used to disambiguate codex rollouts (when multiple share a cwd) and to classify early-runtime failures for the audit fallback path. Returns the zero time if Start has not been called.
func (*AuditAgenticScanner) Start ¶
func (r *AuditAgenticScanner) Start(ctx context.Context) error
Start launches the audit harness (vigolium-audit binary or piolium via `pi`) as a background process. The harness selection drives binary resolution, argv construction, and stream decoding.
On any failure path AFTER BYOK staging has run (codex auth.json copy) but BEFORE cmd.Start() succeeds, the staged file must be cleaned up here — monitor() never runs in that case. Past that point, monitor's deferred cleanup owns the restore.
func (*AuditAgenticScanner) Status ¶
func (r *AuditAgenticScanner) Status() *AuditAgentStatus
Status returns a summary of the current audit state.
func (*AuditAgenticScanner) Wait ¶
func (r *AuditAgenticScanner) Wait() error
Wait blocks until the audit finishes.
type AuditDriverAuthFlags ¶
type AuditDriverAuthFlags = agenttypes.AuditDriverAuthFlags
Audit invocation
type AuditDriverCfgInput ¶
type AuditDriverCfgInput struct {
Mode string
Modes []string
SourcePath string
SessionDir string
ProjectUUID string
ScanUUID string
ParentAgenticScanUUID string
Invocation AuditDriverInvocation
Stream bool
StreamWriter io.Writer
// ShowThinking opts into rendering agent thinking blocks (audit NDJSON
// `thinking` events) in the live stream. Off by default; controlled by
// `vigolium agent audit --show-thinking`.
ShowThinking bool
// KeepRaw maps to vigolium-audit's `--keep-raw`: opt out of the
// deep/confirm auto-prune so raw scanner output, draft findings, and
// intermediate workspaces stay on disk for manual review. Audit-only;
// ignored for the piolium harness.
KeepRaw bool
// KeepSourceOutputDir suppresses the post-run cleanup of
// <source>/vigolium-results/ from the source tree (a session copy is
// always synced regardless). The CLI sets it from --keep-raw/--clean-raw
// so the on-disk results can be reviewed or re-imported. Audit-only.
KeepSourceOutputDir bool
// AuthOverride carries the resolved BYOK bundle for this run. It is
// already folded into Invocation.Auth by the caller (via
// ResolveAuditDriverInvocation's variadic override or
// ApplyAuthOverrideToAudit), so audit's argv reflects it. The
// field is also stored on AuditAgentConfig so the launcher can match
// audit's auth to whatever staging/env injection the piolium driver
// would do (currently only piolium consumes it; audit stays argv-only).
AuthOverride AuthOverride
}
AuditDriverCfgInput collects everything BuildAuditDriverCfg needs to produce a runnable AuditAgentConfig. The embedded vigolium-audit binary self-contains its content bundle, so there is no plugin-dir extraction step anymore. Invocation carries the resolved agent + auth (resolved from olium config / CLI override by the caller via ResolveAuditDriverInvocation). Stream toggles audit's `--json` mode so the streaming goroutine can capture the result event for cost reporting.
type AuditDriverIntensityPreset ¶
type AuditDriverIntensityPreset = agenttypes.AuditDriverIntensityPreset
Intensity types
type AuditDriverInvocation ¶
type AuditDriverInvocation = agenttypes.AuditDriverInvocation
Audit invocation
func ResolveAuditDriverInvocation ¶
func ResolveAuditDriverInvocation(olium config.OliumConfig, providerOverride string, authOverride ...AuthOverride) AuditDriverInvocation
ResolveAuditDriverInvocation derives the vigolium-audit agent + auth tuple from the configured olium provider and an optional override.
Precedence:
- providerOverride (CLI flag like --provider) — wins outright.
- olium.Provider — anthropic-* → claude, openai-* → codex.
- Default — claude (matches vigolium-audit's own default).
Auth selection follows the resolved provider:
- anthropic-api-key → APIKey from olium.LLMAPIKey
- anthropic-oauth → OAuthToken from olium.OAuthToken
- anthropic-cli → no override (subscription auth)
- openai-api-key → APIKey from olium.LLMAPIKey
- openai-codex-oauth → OAuthCredFile from olium.OAuthCredPath
- vertex providers → no override (audit doesn't authenticate against Vertex itself; the user routes through Anthropic/OpenAI via audit's own provider-detection path)
authOverride (variadic for backwards compatibility) supplies a per-run BYOK bundle from the audit CLI/REST surface. When non-empty, it REPLACES the olium-derived auth wholesale (see ApplyAuthOverrideToAudit) — the resolved agent (claude/codex) still comes from providerOverride/olium. Only the first element is consulted; extras are ignored.
type AuditRunner ¶
type AuditRunner interface {
Start(ctx context.Context) error
Wait() error
Done() <-chan struct{}
Cancel()
Status() *AuditAgentStatus
FindingStats() FindingStats
CostSummary() ScanCost
AgenticScanUUID() string
}
AuditRunner is the common surface the audit dispatchers (CLI driverPlan, REST driverResult, single-driver runner) consume. Both the single-subprocess *AuditAgenticScanner and the multi-mode *PioliumChainScanner satisfy it, so a piolium mode chain is a drop-in for a single piolium run.
func NewAuditRunner ¶
func NewAuditRunner(cfg AuditAgentConfig, repo *database.Repository) AuditRunner
NewAuditRunner returns the right runner for cfg. audit owns its own chaining natively (`--modes` is rendered in buildAuditAgentCommand, one subprocess, one row), so only a multi-mode piolium run needs the Go loop. Everything else stays a plain single-subprocess scanner.
type AuthOverride ¶
type AuthOverride = agenttypes.AuthOverride
Audit BYOK auth override (CLI/REST → audit flags + piolium env)
type AutopilotArtifactSpec ¶
type AutopilotArtifactSpec struct {
BriefPath string `json:"brief_path"`
ContextPath string `json:"context_path"`
PlanPath string `json:"plan_path"`
FindingsPath string `json:"findings_path"`
DismissedPath string `json:"dismissed_path"`
VisitedEndpointsPath string `json:"visited_endpoints_path"`
ArtifactsPath string `json:"artifacts_path"`
SessionConfigPath string `json:"session_config_path"`
AuthStatePath string `json:"auth_state_path"`
AuthHeadersPath string `json:"auth_headers_path"`
BrowserSessionPath string `json:"browser_session_path"`
EvidenceDir string `json:"evidence_dir"`
VerificationPath string `json:"verification_path"`
}
type AutopilotAuthFlow ¶
type AutopilotContextBundle ¶
type AutopilotContextBundle struct {
Version string `json:"version"`
Mode string `json:"mode"`
TargetURL string `json:"target,omitempty"`
SourcePath string `json:"source_path,omitempty"`
DiffRef string `json:"diff_ref,omitempty"`
ChangedFiles []string `json:"changed_files,omitempty"`
Routes []AutopilotRouteSummary `json:"routes,omitempty"`
AuthFlows []AutopilotAuthFlow `json:"auth_flows,omitempty"`
Findings []AutopilotFindingSummary `json:"findings,omitempty"`
Priorities []string `json:"priorities,omitempty"`
AuditDriverAvailable bool `json:"audit_available"`
AuditDriverStatus string `json:"audit_status,omitempty"`
PreparedAuth *AutopilotPreparedAuth `json:"prepared_auth,omitempty"`
BrowserDecision string `json:"browser_decision,omitempty"`
BrowserReason string `json:"browser_reason,omitempty"`
Warnings []string `json:"warnings,omitempty"`
}
type AutopilotExecutionPlan ¶
type AutopilotExecutionPlan struct {
AuthRequired bool `json:"auth_required"`
AuthPrepared bool `json:"auth_prepared,omitempty"`
BrowserMode string `json:"browser_mode,omitempty"`
BrowserReason string `json:"browser_reason,omitempty"`
Budgets map[string]int `json:"budgets,omitempty"`
Tasks []AutopilotPlanTask `json:"tasks,omitempty"`
StopCriteria []string `json:"stop_criteria,omitempty"`
Warnings []string `json:"warnings,omitempty"`
ArtifactPolicy AutopilotArtifactSpec `json:"artifact_policy"`
}
type AutopilotFindingSummary ¶
type AutopilotFindingSummary struct {
ID string `json:"id,omitempty"`
Title string `json:"title"`
Severity string `json:"severity,omitempty"`
Confidence string `json:"confidence,omitempty"`
Action string `json:"action,omitempty"`
Kind string `json:"kind,omitempty"`
Route string `json:"route,omitempty"`
Locations []string `json:"locations,omitempty"`
}
type AutopilotIntensityPreset ¶
type AutopilotIntensityPreset = agenttypes.AutopilotIntensityPreset
Intensity types
type AutopilotPipelineConfig ¶
type AutopilotPipelineConfig struct {
TargetURL string
SourcePath string
Files []string
Instruction string
Focus string
// Skill selection forwarded to the operator agent's planner-driven
// loading. SkillNames/SkillTags force-include; NoSkillFilter loads the
// full set; AlwaysOnSkills are kept regardless of selection.
SkillNames []string
SkillTags []string
NoSkillFilter bool
AlwaysOnSkills []string
// SystemPrompt, when non-empty, fully replaces the built-in autopilot
// system prompt at the olium runtime layer. Empty falls back to
// agent.olium.system_prompt in settings, then to the embedded persona.
SystemPrompt string
AgentName string
MaxCommands int
DryRun bool
ShowPrompt bool
// Triage, when true, runs an AI triage pass over the findings after the
// operator loop completes — classifying each as confirmed (→ "triaged")
// or "false_positive" and writing the verdict back, scoped to this run.
// Pure classification: no native rescan.
Triage bool
SessionsDir string
SessionDir string
ProjectUUID string
ScanUUID string
ParentAgenticScanUUID string
StreamWriter io.Writer
ProgressCallback func(phase string, message string)
// Audit is the audit-cfg slot — backed by either audit or piolium per
// AuditHarness. Field name is legacy; the runtime is harness-agnostic.
Audit *config.AuditAgentConfig
// AuditHarness selects which harness backs the Audit cfg. Zero-valued
// defaults to audit for backward compat.
AuditHarness HarnessSpec
// BrowserEnabled indicates whether agent-browser is available for the agent.
BrowserEnabled bool
// BrowserBinaryPath is agent.browser.binary_path for the typed browser_auth
// adapter; empty resolves agent-browser on PATH.
BrowserBinaryPath string
// BrowserRequested preserves explicit user intent even when heuristics are weak.
BrowserRequested bool
// RequiresBrowser means auth/setup should prefer browser assistance over HTTP-only preparation.
RequiresBrowser bool
// KeepBrowserEnabled forces the browser tool to stay available even when the
// browser-usage heuristic would deprioritize it (browser_unneeded). Unlike
// BrowserRequested it does NOT signal explicit user intent, so it only guards
// tool availability and never arms the browser-auth preflight or changes the
// planning hint. Set by the CLI autopilot path (browser is always-on for
// autopilot); the server leaves it false to keep its opt-in behavior.
KeepBrowserEnabled bool
// Credentials carries compact credentials extracted from the prompt or flag input.
Credentials string
// CredentialSets carries structured role/account pairs extracted from prompt input.
CredentialSets []agenttypes.IntentCredentialSet
// AuthRequired means auth should be prepared before operator launch.
AuthRequired bool
// BrowserStartURL is an explicit login/start URL for browser-based flows.
BrowserStartURL string
// FocusRoutes are protected or browser-focused routes named by the user.
FocusRoutes []string
// SessionConfig is the prepared session config for authenticated scanning.
SessionConfig *AgentSessionConfig
// AuthHeaders are hydrated headers ready for immediate use.
AuthHeaders map[string]string
// PreparedAuth summarizes the auth preparation outcome.
PreparedAuth *AutopilotPreparedAuth
// DiffContext holds parsed diff information for focused scanning.
// When set, the agent prompt includes changed file list and patch content.
DiffContext *agenttypes.DiffContext
ContextBundle *AutopilotContextBundle
Plan *AutopilotExecutionPlan
Artifacts AutopilotArtifactSpec
// PreflightDiscovery enables a discovery + Swagger/OpenAPI ingestion
// pass before the operator agent starts. The records land in the
// project DB so the agent's first turn can `list_findings` and
// `query_records` against real attack surface instead of starting
// blank. Skipped silently when TargetURL is empty. Default true via
// the CLI/API wirers; explicitly settable to false to disable.
PreflightDiscovery bool
// PostHaltVerify enables the autopilot's post-halt coverage
// verification loop. After the model calls halt_scan, the runner
// runs another discovery + spec ingest pass, diffs new routes
// against the pre-halt snapshot, and re-enters the agent once if
// the gap meets PostHaltGapThreshold. Default true via the wirers.
PostHaltVerify bool
// PostHaltGapThreshold is the minimum number of new (method, URL)
// signatures the post-halt probe must turn up before the agent is
// re-entered. 0 = autopilot default (5).
PostHaltGapThreshold int
}
AutopilotPipelineConfig configures the autopilot pipeline.
type AutopilotPipelineResult ¶
type AutopilotPipelineResult = agenttypes.AutopilotPipelineResult
Autopilot types
type AutopilotPipelineRunner ¶
type AutopilotPipelineRunner struct {
// contains filtered or unexported fields
}
AutopilotPipelineRunner orchestrates the autopilot pipeline.
func NewAutopilotPipelineRunner ¶
func NewAutopilotPipelineRunner(engine *Engine, repo *database.Repository) *AutopilotPipelineRunner
NewAutopilotPipelineRunner creates a new autopilot pipeline runner.
func (*AutopilotPipelineRunner) RunAutonomous ¶
func (r *AutopilotPipelineRunner) RunAutonomous(ctx context.Context, cfg AutopilotPipelineConfig) (*AutopilotPipelineResult, error)
RunAutonomous executes the autopilot pipeline: 1. Run vigolium-audit first when source context is available 2. Freeze context into native plan + artifacts 3. Launch the autonomous operator agent with full tool access
type AutopilotPlanTask ¶
type AutopilotPreparedAuth ¶
type AutopilotPreparedAuth struct {
Requested bool `json:"requested"`
Source string `json:"source,omitempty"`
SessionConfig string `json:"session_config_path,omitempty"`
SessionCount int `json:"session_count,omitempty"`
Hydrated bool `json:"hydrated"`
HeaderCount int `json:"header_count,omitempty"`
AuthRequired bool `json:"auth_required"`
RequiresBrowser bool `json:"requires_browser,omitempty"`
BrowserStartURL string `json:"browser_start_url,omitempty"`
FocusRoutes []string `json:"focus_routes,omitempty"`
ProtectedRoutes []string `json:"protected_routes,omitempty"`
Notes []string `json:"notes,omitempty"`
}
type AutopilotRouteSummary ¶
type AutopilotTriageParams ¶
type AutopilotTriageParams struct {
TargetURL string
SourcePath string
ScanUUID string
ProjectUUID string
AgenticScanUUID string // verdicts are written back scoped to this run
SessionDir string
StreamWriter io.Writer
Verbose bool
}
AutopilotTriageParams configures the post-scan triage pass.
type BurpBridgeToolSpec ¶
type BurpBridgeToolSpec struct {
ProjectUUID string
}
BurpBridgeToolSpec registers only the live, read-only Burp bridge tools. It is separate from VigToolSpec so ordinary query agents do not receive replay_request or attack_kit merely because the bridge is available.
type CoverageProbe ¶
type CoverageProbe struct {
// Target is the URL/hostname to probe. Required.
Target string
// ProjectUUID scopes the resulting http_records to the same project as
// the autopilot run. Required.
ProjectUUID string
// AgenticScanUUID, when set, is recorded on the underlying Scan rows so
// coverage-pass artifacts can be traced back to the parent autopilot
// run.
AgenticScanUUID string
// ConfigPath optionally overrides the path to vigolium-configs.yaml so
// the pass uses the same settings as the surrounding scan.
ConfigPath string
// Repo is the DB handle used for the snapshot diff. Required.
Repo *database.Repository
// Concurrency overrides the worker count. 0 = settings default.
Concurrency int
}
CoverageProbe runs a single deterministic discovery + OpenAPI/Swagger ingestion pass against a target, then snapshots the resulting http_record signatures. Used in two places:
- Pre-flight (pipeline runner, before the agent starts) — populates the project DB so the agent inherits known surface instead of starting blank.
- Post-halt verification (autopilot.Run, after the model calls halt_scan) — re-runs the probe to surface any routes/specs the agent missed, then diffs against the pre-halt snapshot to decide whether a re-entry is warranted.
All probe activity goes through runner.LaunchScan, which writes records to the project DB using the same model the agent's own tools use. The agent's query_records / inspect_record tools see them transparently on the next turn.
func (*CoverageProbe) Run ¶
func (p *CoverageProbe) Run(ctx context.Context) (*CoverageProbeResult, error)
func (*CoverageProbe) SnapshotSignatures ¶
func (p *CoverageProbe) SnapshotSignatures(ctx context.Context) ([]string, error)
SnapshotSignatures captures the current set of (method, URL) signatures for the probe's target host without running any scans. Used by callers that need a pre-run baseline independent of Run() — e.g. the autopilot post-halt loop snapshots when the agent starts so it can compare against what the model + the post-halt probe produced.
func (*CoverageProbe) Validate ¶
func (p *CoverageProbe) Validate() error
Validate returns nil iff the probe has the minimum information needed to run. Caller-side check so the higher-level pipeline can short-circuit rather than enter LaunchScan and fail mid-stream.
type CoverageProbeResult ¶
type CoverageProbeResult struct {
// DiscoveryScanUUID is the Scan row created by the discovery pass. Empty
// on a probe that skipped discovery (e.g. snapshot-only call).
DiscoveryScanUUID string
// SpecIngestScanUUID is the Scan row created by the OpenAPI/Swagger
// ingestion pass. Empty when ingestion was skipped or no spec was
// found.
SpecIngestScanUUID string
// SignaturesBefore is the set of (method, URL) signatures present in
// the project for Target's hostname when Run() started.
SignaturesBefore []string
// SignaturesAfter is the same set after both passes completed.
SignaturesAfter []string
// NewSignatures = SignaturesAfter - SignaturesBefore. Sorted for
// stable output.
NewSignatures []string
}
CoverageProbeResult summarizes a single coverage pass.
type CoverageReportInputs ¶
type Engine ¶
type Engine struct {
// contains filtered or unexported fields
}
Engine orchestrates AI agent runs: context gathering, prompt rendering, agent execution, output parsing, and result ingestion. Dispatch happens through the in-process olium engine; no subprocess pools are involved.
func NewEngine ¶
func NewEngine(settings *config.Settings, repo *database.Repository) *Engine
NewEngine creates a new agent engine backed by the in-process olium runtime.
func (*Engine) InvalidateContextCache ¶
func (e *Engine) InvalidateContextCache()
InvalidateContextCache clears the context cache. Call after phases that modify scan data (native scan, rescan).
func (*Engine) Preflight ¶
Preflight verifies the olium provider is resolvable AND that credentials actually work by issuing a tiny ping prompt. Call this before starting a multi-phase pipeline so credential / network problems fail fast (within ~5 seconds) instead of after a minute of normalize + discovery work. agentName is retained for call-site compatibility; it no longer affects dispatch.
The ping is bounded by a hard 5s timeout; transient ping failures are returned as errors so the caller can decide whether to bail or continue (CLI usually bails, server endpoints typically continue and let the real first-call failure surface in the run record).
func (*Engine) ResetTokenUsage ¶
func (e *Engine) ResetTokenUsage()
ResetTokenUsage zeroes the accumulator. Useful for tests; production callers get a fresh accumulator from NewEngine.
func (*Engine) Run ¶
Run executes a full agent pipeline: resolve prompt → render → execute → parse → ingest. Each call constructs a fresh in-process olium engine.
func (*Engine) RunOnOliumEngine ¶
func (e *Engine) RunOnOliumEngine(ctx context.Context, opts Options, sess AgentSession) (*Result, error)
RunOnOliumEngine is like Run but reuses an existing AgentSession so the caller's prior conversation history (system prompt, tool defs, earlier turns) remains in the provider request and can hit prompt caches. Use with AgentSession.Fork() for parallel sub-runs that share a prefix — e.g., the source-analysis explore phase forks to 3 format/extension goroutines that don't need to re-append the explore notes.
func (*Engine) RunSourceAnalysisParallel ¶
func (e *Engine) RunSourceAnalysisParallel(ctx context.Context, cfg SourceAnalysisConfig) (saResult *SourceAnalysisResult, rawOutput string, renderedPrompt string, err error)
RunSourceAnalysisParallel executes consolidated source analysis in 4 LLM calls across 2 waves:
Wave 1 (single call): Call 1: swarm-source-explore (reads source → notes on routes + auth + sinks) Wave 2 (parallel, consumes Wave 1 output): Call 2a: swarm-source-format-routes (route notes → JSONL http_records) Call 2b: swarm-source-format-session (auth notes → session_config JSON) Call 3: swarm-source-extensions (combined notes → JS scanner extensions)
The single explore call reads the codebase once and produces two labeled sections (routes + auth/session) that are split for the format calls. When SDK pool is available, format-routes reuses the explore session (multi-turn) for full context.
func (*Engine) RunWithExtra ¶
func (e *Engine) RunWithExtra(ctx context.Context, opts Options, extra map[string]string) (*Result, error)
RunWithExtra executes an agent run with additional extra template data injected. This is used by swarm mode to pass request context and vuln type to the template.
func (*Engine) RunWithExtraSkills ¶
func (e *Engine) RunWithExtraSkills(ctx context.Context, opts Options, extra map[string]string, reg *skill.Registry) (*Result, error)
RunWithExtraSkills merges extra template data (like RunWithExtra) and also surfaces the given skill registry to the agent. Used by the swarm plan phase to give the planner the full skill menu.
func (*Engine) RunWithSkills ¶
func (e *Engine) RunWithSkills(ctx context.Context, opts Options, reg *skill.Registry) (*Result, error)
RunWithSkills is Run with a skill registry surfaced to the agent: the fresh-per-call engine gets an <available_skills> block and the load_skill tool for exactly the skills in reg. A nil/empty reg behaves like Run.
func (*Engine) SetContextCache ¶
func (e *Engine) SetContextCache(cache *agentprompt.ContextCache)
SetContextCache sets a context cache for DB enrichment results. Used by swarm runs to avoid redundant queries across phases.
func (*Engine) TokenUsage ¶
func (e *Engine) TokenUsage() agenttypes.TokenUsage
TokenUsage returns the cumulative token usage of every Engine.Run call made on this Engine instance. SwarmRunner reads this at finalize time.
type ExploitationEvidence ¶
type ExploitationEvidence = agenttypes.ExploitationEvidence
Exploitation evidence
type ExtensionMergeResult ¶
type ExtensionMergeResult struct {
Extensions []GeneratedExtension
Renames map[string]string // original filename -> renamed filename
}
ExtensionMergeResult holds the merged extensions plus any rename tracking info.
type FindingStats ¶
type FindingStats struct {
Parsed int // total findings parsed from the session dir
Saved int // findings successfully persisted to the database
BySeverity map[string]int // count by normalized severity (critical/high/medium/low/info)
// Reported is the count reported by the audit binary's own NDJSON
// `result` event. It is only consulted when the on-disk findings tree
// could not be parsed (Parsed == 0) and serves as a display-only
// fallback so the CLI summary mirrors the streamer's `[result]` line
// even when persistence didn't run. Severity keys are normalized to
// lowercase to match BySeverity.
Reported int
ReportedBySeverity map[string]int
}
FindingStats summarises the audit findings imported by a single audit run.
func (FindingStats) SeverityBreakdownString ¶
func (s FindingStats) SeverityBreakdownString() string
SeverityBreakdownString renders a colored "critical:N high:N ..." string in descending severity order. Buckets with zero count are skipped. Falls back to the audit-reported breakdown when the on-disk parse yielded nothing. Returns "" when no findings were counted at all.
type GeneratedExtension ¶
type GeneratedExtension = agenttypes.GeneratedExtension
Pipeline types
func RepairExtensionsWithLLM ¶
func RepairExtensionsWithLLM(ctx context.Context, engine *Engine, invalids []InvalidExtension, cfg RepairConfig) []GeneratedExtension
RepairExtensionsWithLLM attempts to fix invalid extensions by sending each one to the configured LLM agent with the error context. Repairs run in parallel with bounded concurrency. Extensions that compile after repair are returned; those that still fail are dropped.
type GuardrailVerdict ¶
type GuardrailVerdict struct {
Allowed bool `json:"allowed"`
Reason string `json:"reason"`
Categories []string `json:"categories,omitempty"`
}
GuardrailVerdict is the structured response from the prompt-safety classifier.
func ClassifyPromptSafety ¶
func ClassifyPromptSafety(ctx context.Context, settings *config.Settings, userPrompt string) GuardrailVerdict
ClassifyPromptSafety runs a single olium-backed classification call against the user prompt. Reuses settings.Agent.Olium for provider/model.
Fails open: provider, network, or parse errors return Allowed=true with a Reason describing the degradation. A transient LLM outage shouldn't brick legitimate scans; the warning is logged so operators can notice.
type HarnessSpec ¶
type HarnessSpec = agenttypes.HarnessSpec
Audit types
func DefaultAuditHarness ¶
func DefaultAuditHarness() HarnessSpec
DefaultAuditHarness returns the canonical audit harness spec used by `vigolium agent audit` and the autopilot/swarm background audit. The zero value of AuditAgentConfig.Harness is treated as this for backward compat.
func PickAuditHarness ¶
func PickAuditHarness(pioliumMode, auditModeLocal string, auditNoAudit bool, sourcePath string, settingsAudit config.AuditAgentConfig) (*config.AuditAgentConfig, HarnessSpec)
PickAuditHarness picks the audit cfg + harness pair to run from already- resolved mode strings. Piolium wins when its mode is non-empty/"off" (callers do their own auto-pick before invoking this — see the CLI's post-intensity switch and the server's resolveAutopilotAuditCfgServer). Returns (nil, zero-spec) when no audit should run.
type InvalidExtension ¶
type InvalidExtension = agenttypes.InvalidExtension
Extension validation types
type PioliumChainScanner ¶
type PioliumChainScanner struct {
// contains filtered or unexported fields
}
PioliumChainScanner runs a piolium mode chain (e.g. deep,confirm) as a sequence of `pi` subprocesses against the same source dir, collapsing them into a single aggregated AgenticScan row. The chain stops at the first mode that does not complete cleanly — matching audit's native `--modes` semantics.
Why the per-mode aggregation rules differ: piolium's picost windows each cost summary to that subprocess's own run, so per-mode costs are disjoint and summed. Findings, by contrast, are NOT summed — piolium's findings/ dir is cumulative across chained modes in the same source tree, so the last completed mode's snapshot already reflects (and may have pruned) the whole chain; summing would double-count.
func NewPioliumChainScanner ¶
func NewPioliumChainScanner(cfg AuditAgentConfig, repo *database.Repository) *PioliumChainScanner
NewPioliumChainScanner builds a chain runner. The mode chain is read from cfg.EffectiveModes() and filtered to the modes piolium supports (callers normally pre-filter via ValidateAuditDriverModes; this is a defensive second pass so an unsupported mode in the chain is skipped rather than failing the whole driver).
func (*PioliumChainScanner) AgenticScanUUID ¶
func (p *PioliumChainScanner) AgenticScanUUID() string
func (*PioliumChainScanner) Cancel ¶
func (p *PioliumChainScanner) Cancel()
func (*PioliumChainScanner) CostSummary ¶
func (p *PioliumChainScanner) CostSummary() ScanCost
func (*PioliumChainScanner) Done ¶
func (p *PioliumChainScanner) Done() <-chan struct{}
func (*PioliumChainScanner) FindingStats ¶
func (p *PioliumChainScanner) FindingStats() FindingStats
func (*PioliumChainScanner) Start ¶
func (p *PioliumChainScanner) Start(ctx context.Context) error
Start creates the single aggregated child row and launches the chain loop in the background. It returns once the first mode's subprocess has started (or immediately with the error if it could not).
func (*PioliumChainScanner) Status ¶
func (p *PioliumChainScanner) Status() *AuditAgentStatus
Status reports the live phase progress of the mode currently running; once the chain is done it returns the last mode's snapshot with the full chain string as the mode label.
func (*PioliumChainScanner) Wait ¶
func (p *PioliumChainScanner) Wait() error
type PioliumSweepEntry ¶
type PioliumSweepEntry struct {
Dir string
LockPath string
BackupPath string
Holder pioliumLockBreadcrumb
}
PioliumSweepEntry captures one swept or held lock + backup pair.
type PioliumSweepResult ¶
type PioliumSweepResult struct {
Swept []PioliumSweepEntry // backup → target restored, lock removed
Held []PioliumSweepEntry // active run holds the lock; left alone
Orphaned []string // backup files without a matching restore target
}
PioliumSweepResult summarizes what SweepStalePioliumAuth did per agent directory. Returned so the caller can log a single structured line.
func SweepStalePioliumAuth ¶
func SweepStalePioliumAuth(piAgentDirs []string) PioliumSweepResult
SweepStalePioliumAuth restores credentials left orphaned by a crashed BYOK run. For each candidate piAgentDir:
- If `.vigolium-auth.lock` is missing → look for stray `auth.json.vigolium-bak-*` files and report them as orphaned (the operator must resolve, since we can't tell which one was active).
- If the lock is present but its PID is alive → record as held and leave everything intact.
- If the lock is present but its PID is dead → restore the matching `auth.json.vigolium-bak-<runUUID>` over `auth.json` and remove the lock. Non-matching backups are reported as orphaned for manual resolution.
Returns a structured summary so the caller can log a single line. Never errors — sweep is best-effort by design (a stuck cred file is an operator problem, not a vigolium-must-fail-boot problem).
type PlanCoverage ¶
PlanCoverage describes how well a SwarmPlan's focus areas + notes blanket the record set. MissingPrefixes is ordered by first appearance in records.
func AnalyzePlanCoverage ¶
func AnalyzePlanCoverage(plan *SwarmPlan, records []*httpmsg.HttpRequestResponse) PlanCoverage
AnalyzePlanCoverage returns the URL-prefix clusters in records that no FocusArea or Notes substring references (directly or via a parent/child path match).
type PrefixCoverage ¶
type ProbeConfig ¶
type ProbeConfig struct {
Concurrency int // max parallel probe requests; 0 = default 10
Timeout time.Duration // per-request probe timeout; 0 = default 10s
MaxBodySize int // max response body bytes; 0 = default 2MB
OnProgress func(completed, total int) // optional progress callback
}
ProbeConfig holds tuning parameters for HTTP record probing.
type QuickCheckLintIssue ¶
type QuickCheckLintIssue = agenttypes.QuickCheckLintIssue
Extension validation types
type RecordSpec ¶
type RecordSpec struct {
// SessionDir is the directory the transcript-*.jsonl file is written to.
// Empty disables recording (the common one-off CLI case).
SessionDir string
// Template is the phase/template name; it seeds the per-phase filename
// (transcript-<template>.jsonl) and the concurrency-dedup key so parallel
// same-template calls (swarm plan batches) never share a file.
Template string
// SessionID is the transcript header's session id; empty falls back to the
// SessionDir base name.
SessionID string
}
RecordSpec configures a per-run Pi-style JSONL transcript written under SessionDir. The zero value (empty SessionDir) disables recording. It is plain data on purpose so the AgentRuntime seam never leaks olium's EventRecorder type — the adapter builds the concrete sessionlog.Recorder from these fields inside buildOliumEngineWithSpec.
type RunPID ¶
type RunPID struct {
PID int `json:"pid"`
PGID int `json:"pgid"`
StartTime time.Time `json:"start_time"`
}
RunPID holds process lifecycle metadata written to session directories. Used for orphan detection: if vigolium crashes, the next startup can find and kill orphaned agent subprocesses by scanning for stale PID files.
func ReadRunPID ¶
ReadRunPID reads and parses a run.pid file. Returns nil if not found or invalid.
type ScanCost ¶
type ScanCost struct {
Backend string // "audit" | "pi"
Model string // model id reported by the harness
InputTokens int64 // total input tokens across the run
OutputTokens int64 // total output tokens across the run
CostUSD float64 // priced total in USD
Note string // CLI-facing one-line annotation
Blob map[string]interface{} // payload for the TokenUsage JSONB column
}
ScanCost is vigolium's normalized view of an audit harness's token usage and USD cost, produced by the per-harness cost adapter and consumed by the CLI summary and the DB writer.
Note is a short human-readable annotation the CLI renders after the dollar figure (e.g. "(model gpt-5.5, 3 sessions)" for piolium, "(agent codex, status complete)" for audit). It is populated by the adapter that converts from the harness-specific summary, not by the CLI, so each harness can render its own details without the CLI having to branch on harness type.
type ScanIntent ¶
type ScanIntent = agenttypes.ScanIntent
Intent types
func ParseAndResolveIntent ¶
func ParseAndResolveIntent(ctx context.Context, engine *Engine, prompt string, opts ...IntentParseOption) (*ScanIntent, error)
ParseAndResolveIntent is a convenience that calls ParseScanIntent followed by ResolveIntentApps. It returns an error if no apps could be extracted.
func ParseScanIntent ¶
func ParseScanIntent(ctx context.Context, engine *Engine, prompt string, opts ...IntentParseOption) (*ScanIntent, error)
ParseScanIntent uses a quick LLM call to extract structured scan parameters from a natural language prompt. Falls back to structured input detection if the prompt looks like a URL, curl command, etc. When the prompt requires environment setup (git clone, docker), it delegates to ParseScanIntentWithSetup for full Bash-powered olium agent setup.
func ParseScanIntentWithSetup ¶
func ParseScanIntentWithSetup(ctx context.Context, engine *Engine, prompt string, sessionsDir string) (*ScanIntent, error)
ParseScanIntentWithSetup runs the olium agent with full tool access to clone repos, start containers, and detect running targets before returning a structured scan intent.
func ResolveIntentApps ¶
func ResolveIntentApps(intent *ScanIntent) *ScanIntent
ResolveIntentApps processes a ScanIntent by auto-detecting targets for apps that have source paths but no target. Returns the modified intent.
type SessionSpec ¶
type SessionSpec struct {
System string // explicit system prompt; empty falls back to cfg/default
SourcePath string // appended to the system prompt when set
MaxTurns int // 0 = engine default
IncludeTools bool // register the builtin tool set
EnablePromptCache bool
// Skills, when non-nil and non-empty, injects an <available_skills> block
// into the system prompt and registers the load_skill tool (requires
// IncludeTools). Used by swarm plan/triage phases for planner-driven skill
// loading; nil for phases that don't surface skills.
Skills *skill.Registry
// VigTools, when non-nil with a Repo (and IncludeTools), registers the
// vigolium read+replay tool subset so a skill can actually confirm/escalate
// against scan records. nil for phases that only reason over prompt context.
VigTools *VigToolSpec
// BurpBridgeTools, when non-nil (and IncludeTools), registers only
// search_burp_items and inspect_burp_item. Both tools are read-only.
BurpBridgeTools *BurpBridgeToolSpec
// Record, when its SessionDir is set, attaches a Pi-style JSONL transcript
// recorder to the built engine so the session's turns (including model
// reasoning) persist for debugging. Zero value = no transcript.
Record RecordSpec
}
SessionSpec configures a session built via AgentRuntime.NewSessionWithSpec for specialized one-off flows (the guardrail classifier, intent setup) that need a custom system prompt, turn cap, or tool set. The combination used by the default NewSession — {SourcePath: ..., IncludeTools: true} — reproduces the standard engine: builtin tools, the config's system prompt (or the package default), and the engine's default turn cap.
type SourceAnalysisConfig ¶
type SourceAnalysisConfig = agenttypes.SourceAnalysisConfig
Pipeline types
type SourceAnalysisResult ¶
type SourceAnalysisResult = agenttypes.SourceAnalysisResult
Pipeline types
type SwarmConfig ¶
type SwarmConfig struct {
// Inputs: raw input strings (URL, curl, raw HTTP, Burp XML, or record UUID)
Inputs []string // raw input strings
InputType InputType // explicit type (auto-detected if empty)
// Source analysis
SourcePath string // path to application source code (triggers source analysis phase)
Files []string // specific files to include (relative to SourcePath)
DiffContext *agenttypes.DiffContext // non-nil when --diff or --last-commits was provided
// Custom instruction
Instruction string // user-provided custom instruction appended to agent prompts
// ForceExtensions forces the Phase-2 extension agent to run even when the
// plan agent decides built-in modules are sufficient. Bound to --with-extensions
// on the CLI. Has no effect when DryRun is true (DryRun still skips Phase 2).
ForceExtensions bool
// Skill selection (planner-driven loading overrides)
SkillNames []string // --skill: force-include these skills, bypassing planner judgement
SkillTags []string // --skill-tag: force-include every skill carrying one of these tags
NoSkillFilter bool // --no-skill-filter: load the full skill set, ignore planner selection
// Scanning parameters
VulnType string // optional: focus on specific vulnerability type
Focus string // optional: broad strategic hint (e.g. "API injection", "auth bypass")
ModuleNames []string // optional: explicit module IDs to use
OnlyPhase string // isolate a single phase (empty = all phases)
SkipPhases []string // skip specific phases (empty = skip none)
MaxIterations int // max triage-rescan loops (default 3)
BatchConcurrency int // max parallel master agent batches (0 = default 3)
MaxMasterRetries int // max master agent retries on parse failure (0 = default 3)
SAMaxConcurrency int // max parallel source analysis sub-agents (0 = default 3)
// Agent
AgentName string
DryRun bool
ShowPrompt bool // print rendered prompts to stderr before executing
SourceAnalysisOnly bool // run only source analysis phase and exit
CodeAudit bool // enable AI security code audit phase (--code-audit)
Browser bool // enable agent-browser integration (always on for swarm; no --browser flag)
Auth bool // run browser-based auth phase before discovery (--browser-auth)
Credentials string // optional credentials for the browser auth phase (extracted from the prompt)
CredentialSets []agenttypes.IntentCredentialSet
AuthRequired bool
RequiresBrowser bool
BrowserStartURL string
FocusRoutes []string
// Context truncation
MaxResponseBodyBytes int // max response body size in context; 0 = default 4096
MaxPlanRecords int // max records sent to plan agent; 0 = no cap (ship the full surface)
// Tuning: batching, probing, retries
MasterBatchSize int // max records per master agent batch; 0 = default 5
ProbeConcurrency int // max parallel probe requests; 0 = default 10
ProbeTimeout time.Duration // per-request probe timeout; 0 = default 10s
MaxProbeBodySize int // max response body bytes during probing; 0 = default 2MB
// ReconExtraHeaders, when set, is injected onto every recon probe
// (and into the prompt-context's TechStack rendering). Populated by
// the CLI from --cookie / --header / --auth-config so that recon
// fingerprints authenticated pages instead of the public landing.
ReconExtraHeaders map[string]string
ProjectUUID string
ScanUUID string
// Session directory base path for agent artifacts
SessionsDir string
// SessionDir is the pre-created session directory for this run.
// When set, the swarm runner uses it directly instead of creating one.
SessionDir string
// AgenticScanUUID overrides the auto-generated agent run UUID.
// When set (e.g. by CLI), the swarm runner uses this UUID for the DB record,
// ensuring it matches the pre-created session directory name.
AgenticScanUUID string
// ResumeDir is the session directory of a previous run to resume from.
// When set, the swarm runner loads the checkpoint and skips completed phases.
ResumeDir string
// Streaming
StreamWriter io.Writer
Verbose bool // when true, agent calls render a per-tool result preview alongside the standard one-liner
ProgressCallback func(ProgressEvent)
// ScanFunc runs the scan with the given module filters and extensions.
ScanFunc ScanFunc
// DiscoverFunc runs native discovery+spidering before master agent planning.
// When set, the swarm runner executes discovery and feeds discovered records
// into the master agent alongside the original inputs.
DiscoverFunc func(ctx context.Context) error
// SourceAnalysisCallback is called after source analysis completes to allow
// the caller to process session config (e.g., convert to auth-config.yaml)
// and extensions before the scan phase.
SourceAnalysisCallback func(result *SourceAnalysisResult) error
// BrowserAuthCallback is fired after the browser-based auth phase writes
// an auth-config.yaml to the session dir. The CLI uses this to thread
// the captured session into the discovery + scan funcs so the native
// spider (and downstream scan) crawl post-login surface. Empty path =
// auth phase ran but produced no config; the caller may treat that as
// a soft failure.
BrowserAuthCallback func(authConfigPath string) error
// PhaseCallback is called when a swarm phase starts.
PhaseCallback func(phase string)
// Audit is the background-audit cfg slot — backed by either audit or
// piolium per AuditHarness. Requires SourcePath to be non-empty. Field
// name is legacy; the runtime is harness-agnostic.
Audit *config.AuditAgentConfig
// AuditHarness selects which harness backs the Audit cfg. Zero-valued
// defaults to audit for backward compat.
AuditHarness HarnessSpec
}
SwarmConfig configures an agent swarm run.
type SwarmCoveragePlan ¶
type SwarmCoveragePlan struct {
ModuleTags []string `json:"module_tags,omitempty"`
ModuleIDs []string `json:"module_ids,omitempty"`
// False when the scan ran against the full registry rather than a
// plan-filtered subset — explicit so "no filter" isn't mistaken for
// a misconfig.
ModuleFilterApplied bool `json:"module_filter_applied"`
FocusAreas []string `json:"focus_areas,omitempty"`
Notes string `json:"notes,omitempty"`
ExtensionsCount int `json:"extensions_count"`
NeedsExtensions bool `json:"needs_extensions"`
ExtensionAgentError string `json:"extension_agent_error,omitempty"`
}
type SwarmCoverageReport ¶
type SwarmCoverageReport struct {
GeneratedAt time.Time `json:"generated_at"`
AgenticScanUUID string `json:"agentic_scan_uuid,omitempty"`
TargetURL string `json:"target_url,omitempty"`
Intensity string `json:"intensity,omitempty"`
TotalRecords int `json:"total_records"`
Prefixes []PrefixCoverage `json:"prefixes,omitempty"`
Plan SwarmCoveragePlan `json:"plan"`
FindingsByModule map[string]int `json:"findings_by_module,omitempty"`
FindingsByEndpoint map[string]int `json:"findings_by_endpoint,omitempty"`
TotalFindings int `json:"total_findings"`
Warnings []string `json:"warnings,omitempty"`
}
SwarmCoverageReport is the JSON document written to {sessionDir}/coverage.json. Every list is sorted deterministically so reports are diffable across runs.
func BuildSwarmCoverageReport ¶
func BuildSwarmCoverageReport(in CoverageReportInputs) *SwarmCoverageReport
type SwarmIntensityPreset ¶
type SwarmIntensityPreset = agenttypes.SwarmIntensityPreset
Intensity types
type SwarmRunner ¶
type SwarmRunner struct {
// contains filtered or unexported fields
}
SwarmRunner orchestrates AI-guided targeted vulnerability scanning.
func NewSwarmRunner ¶
func NewSwarmRunner(engine *Engine, repo *database.Repository) *SwarmRunner
NewSwarmRunner creates a swarm runner.
func (*SwarmRunner) Run ¶
func (s *SwarmRunner) Run(ctx context.Context, cfg SwarmConfig) (*SwarmResult, error)
Run executes the full agent swarm pipeline.
type TriageLoopConfig ¶
type TriageLoopConfig struct {
Engine *Engine
Repository *database.Repository // optional: used for early exit on high-confidence findings
// Agent options for triage calls
AgentName string
PromptTemplate string // e.g. "pipeline-triage" or "agent-swarm-triage"
TargetURL string
Hostname string
SourcePath string
Files []string
Instruction string
DryRun bool
ShowPrompt bool
ScanUUID string
ProjectUUID string
AgenticScanUUID string // when set, triage verdicts are written back to Finding.Status
StreamWriter io.Writer
Verbose bool // forwarded to agent.Options.Verbose for the per-tool result preview
// Skills, when non-nil and non-empty, is the planner-filtered skill set the
// triage agent loads (via load_skill) to confirm/escalate findings. Built
// by the swarm triage step from the plan's recommended_skills + always-on
// set. nil → triage runs without skills (e.g. the pipeline triage path).
Skills *skill.Registry
// Loop control
MaxRounds int
MaxFindingsPerTriageBatch int // if >0, split findings into batches of this size for triage
BatchConcurrency int // max triage batches run concurrently per round; 0 = default 3 (mirrors master-agent batches)
MaxFindingsPerRound int // max findings loaded per triage round; 0 = default 5000
ResumeFromRound int // skip triage rounds before this (0 = start from beginning)
ProgressCallback func(ProgressEvent)
InitialFindingIDFloor int64 // when >0, only findings newer than this ID are triaged in follow-up rounds
// Scan callback for rescans
ScanFunc ScanFunc
// Session artifacts (optional)
SessionDir string
ExtensionDir string // extension dir from the initial scan, carried into rescans
// OnRescan is called before each rescan phase starts (optional).
OnRescan func()
// OnTriageRoundComplete is called after each triage round completes (optional).
// The round number (0-indexed) is passed so callers can update checkpoints.
OnTriageRoundComplete func(round int)
}
TriageLoopConfig configures a shared triage+rescan loop used by both Pipeline and Swarm.
type TriageLoopResult ¶
type TriageLoopResult struct {
TriageResults []*TriageResult
Confirmed int
FalsePositives int
RescanRounds int
}
TriageLoopResult holds the accumulated results from a triage+rescan loop.
func RunAutopilotTriage ¶
func RunAutopilotTriage(ctx context.Context, engine *Engine, repo *database.Repository, p AutopilotTriageParams) (*TriageLoopResult, error)
RunAutopilotTriage runs a single AI triage pass over the project's findings after an autopilot scan completes. Each finding is classified as confirmed (→ status "triaged") or a false positive (→ "false_positive") and the verdict is written back, scoped to this run's AgenticScanUUID so only findings this scan produced are touched.
It is a pure classification pass: ScanFunc is nil and MaxRounds is 1, so triage never kicks off native rescans (that remains swarm's job). It reuses the shared RunTriageLoop machinery and the agent-swarm-triage prompt.
Callers should treat a returned error as non-fatal — a triage failure must not fail an otherwise-completed scan.
func RunTriageLoop ¶
func RunTriageLoop(ctx context.Context, cfg TriageLoopConfig) (*TriageLoopResult, error)
RunTriageLoop executes the triage agent in a loop, optionally rescanning based on the agent's verdict. This is the shared implementation used by both Pipeline and Swarm.
type VerifyCandidatesConfig ¶
type VerifyCandidatesConfig struct {
Repo *database.Repository
Provider provider.Provider
Model string
ProjectUUID string
ScanUUID string
AgenticScanUUID string
Target string
SessionDir string
Mode string // config.AutopilotMode{Shadow,Enforced}
Concurrency int // 0 = defaultVerifyConcurrency
StreamWriter io.Writer
}
VerifyCandidatesConfig configures a verify-before-promote pass.
type VerifyCandidatesResult ¶
type VerifyCandidatesResult struct {
Total int
Confirmed int
Rejected int
NeedsEvidence int
Promoted int // findings written (confirmed & promotion succeeded)
}
VerifyCandidatesResult summarizes a verify pass.
func VerifyCandidates ¶
func VerifyCandidates(ctx context.Context, cfg VerifyCandidatesConfig) (*VerifyCandidatesResult, error)
VerifyCandidates runs the fresh-context verifier over every proposed candidate for the run, promoting the confirmed ones. It is a no-op (nil, nil) in legacy mode, without a repo/provider, or when there are no proposed candidates. Best-effort: an individual verifier failure marks that candidate needs_evidence and continues; the pass never fails the whole autopilot run.
type VigToolSpec ¶
type VigToolSpec struct {
Repo *database.Repository
ProjectUUID string
}
VigToolSpec, when set on a SessionSpec built with IncludeTools, registers the vigolium read+replay tool subset — query_records, inspect_record, replay_request, attack_kit — so a skill-driven agent (swarm triage) can run an explore → inspect → craft → replay confirmation loop against prior scan records. Requires Repo. OAST tools are intentionally excluded: oast_mint owns an interactsh Service that needs an explicit Shutdown the per-call engine can't manage.
Source Files
¶
- aliases.go
- audit_agent.go
- audit_agent_config.go
- audit_chain.go
- audit_cost.go
- audit_driver_args.go
- audit_drivers.go
- audit_interactive.go
- audit_pi_byok.go
- audit_redact.go
- auth_override.go
- auth_synth.go
- autopilot_auth.go
- autopilot_context.go
- autopilot_coverage.go
- autopilot_pipeline.go
- autopilot_triage.go
- autopilot_verify.go
- autopilot_verify_tool.go
- console.go
- doc.go
- engine.go
- engine_ingest.go
- extension_validate.go
- guardrail.go
- intensity.go
- intent.go
- intent_auth_helpers.go
- olium_adapter.go
- pidfile.go
- pipeline_types.go
- process_cleanup.go
- retry.go
- runtime.go
- session_repair.go
- skills.go
- source_facade.go
- stream_group.go
- swarm.go
- swarm_agent_phases.go
- swarm_coverage.go
- swarm_coverage_report.go
- swarm_discover_reentry.go
- swarm_phase_ai.go
- swarm_pipeline.go
- swarm_probe.go
- swarm_records_context.go
- swarm_session_io.go
- swarm_triage_audit.go
- thinking_sink.go
- triage.go
Directories
¶
| Path | Synopsis |
|---|---|
|
Package agenttypes defines shared data types used across the agent subsystem.
|
Package agenttypes defines shared data types used across the agent subsystem. |
|
Package recon performs a lightweight, conservative reconnaissance sweep against a target host before the swarm plan agent runs.
|
Package recon performs a lightweight, conservative reconnaissance sweep against a target host before the swarm plan agent runs. |