2025-10-13 10:21:50 -06:00

119 lines
4.0 KiB
TypeScript

/**
* State schema for the Bandit Runner LangGraph agent
*/
export interface Command {
command: string
output: string
exitCode: number
timestamp: string
duration: number
level: number
}
export interface ThoughtLog {
type: 'plan' | 'observation' | 'reasoning' | 'decision'
content: string
timestamp: string
level: number
metadata?: Record<string, any>
}
export interface Checkpoint {
level: number
password: string
timestamp: string
commandCount: number
state: Partial<BanditAgentState>
}
export interface BanditAgentState {
runId: string
modelProvider: string
modelName: string
currentLevel: number
targetLevel: number // Allow partial runs (e.g., 0-5 for testing)
currentPassword: string
nextPassword: string | null
levelGoal: string
commandHistory: Command[]
thoughts: ThoughtLog[]
status: 'planning' | 'executing' | 'validating' | 'advancing' | 'paused' | 'paused_for_user_action' | 'complete' | 'failed'
retryCount: number
maxRetries: number
failureReasons: string[]
lastCheckpoint: Checkpoint | null
streamingMode: 'selective' | 'all_events'
sshConnectionId: string | null
startedAt: string
completedAt: string | null
error: string | null
}
export interface RunConfig {
runId: string
modelProvider: 'openrouter'
modelName: string
startLevel?: number // Always 0, optional for backwards compatibility
endLevel: number
maxRetries: number
streamingMode: 'selective' | 'all_events'
apiKey?: string
}
export interface AgentEvent {
type: 'terminal_output' | 'agent_message' | 'level_complete' | 'run_complete' | 'error' | 'thinking' | 'tool_call' | 'user_action_required' | 'usage_update'
data: {
content?: string
level?: number
command?: string
metadata?: Record<string, any>
reason?: 'max_retries'
retryCount?: number
maxRetries?: number
message?: string
totalTokens?: number
totalCost?: number
}
timestamp: string
}
// Level goals from the system prompt
export const LEVEL_GOALS: Record<number, string> = {
0: "Read 'readme' file in home directory",
1: "Read '-' file (use 'cat ./-' or 'cat < -')",
2: "Find and read hidden file with spaces in name",
3: "Find file with specific permissions (non-executable, human-readable, 1033 bytes)",
4: "Find file in inhere directory that is human-readable",
5: "Find file owned by bandit7, group bandit6, 33 bytes in size",
6: "Find the only line in data.txt that occurs only once",
7: "Find password next to word 'millionth' in data.txt",
8: "Find password in one of the few human-readable strings",
9: "Extract password from file with '=' prefix",
10: "Decode base64 encoded data.txt",
11: "Decode ROT13 encoded data.txt",
12: "Decompress repeatedly compressed file (hexdump → gzip → bzip2 → tar)",
13: "Use sshkey.private to connect to bandit14 and read password",
14: "Submit current password to port 30000 on localhost",
15: "Submit current password to SSL service on port 30001",
16: "Find port with SSL and RSA private key, use key to login to bandit17",
17: "Find the one line that changed between passwords.old and passwords.new",
18: "Read readme file (shell is modified, use ssh with command)",
19: "Use setuid binary to read password",
20: "Use network daemon that echoes back password",
21: "Examine cron jobs and find password in output file",
22: "Find cron script that creates MD5 hash filename, read that file",
23: "Create script in cron-monitored directory to get password",
24: "Brute force 4-digit PIN with password on port 30002",
25: "Escape from restricted shell (more pager) to read password",
26: "Use setuid binary to execute commands as bandit27",
27: "Clone git repository and find password",
28: "Find password in git repository history/commits",
29: "Find password in git repository branches or tags",
30: "Find password in git tag",
31: "Push file to git repository, hook reveals password",
32: "Use allowed commands in restricted shell to read password",
33: "Final level - read completion message"
}