monkeyscode 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- monkeyscode/__init__.py +178 -0
- monkeyscode/_http.py +83 -0
- monkeyscode/admin.py +141 -0
- monkeyscode/agent.py +772 -0
- monkeyscode/ci.py +288 -0
- monkeyscode/cli_process.py +730 -0
- monkeyscode/daemon.py +201 -0
- monkeyscode/events.py +323 -0
- monkeyscode/export.py +319 -0
- monkeyscode/hooks.py +190 -0
- monkeyscode/mcp.py +283 -0
- monkeyscode/orchestrator.py +170 -0
- monkeyscode/otel.py +181 -0
- monkeyscode/py.typed +1 -0
- monkeyscode/runs.py +138 -0
- monkeyscode/sandbox.py +125 -0
- monkeyscode/session.py +227 -0
- monkeyscode/subagent.py +195 -0
- monkeyscode/telemetry.py +204 -0
- monkeyscode/tools.py +133 -0
- monkeyscode/watcher.py +137 -0
- monkeyscode-1.0.0.dist-info/METADATA +152 -0
- monkeyscode-1.0.0.dist-info/RECORD +25 -0
- monkeyscode-1.0.0.dist-info/WHEEL +4 -0
- monkeyscode-1.0.0.dist-info/licenses/LICENSE +21 -0
monkeyscode/daemon.py
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
"""
|
|
2
|
+
MonkeysCode SDK — Daemon Client.
|
|
3
|
+
|
|
4
|
+
WebSocket JSON-RPC client for communicating with the MonkeysCode daemon process.
|
|
5
|
+
Used when connecting to a running daemon instance (e.g., from an IDE extension
|
|
6
|
+
or a local web UI) rather than making direct HTTP calls.
|
|
7
|
+
|
|
8
|
+
Usage::
|
|
9
|
+
|
|
10
|
+
from monkeyscode.daemon import DaemonClient
|
|
11
|
+
|
|
12
|
+
client = DaemonClient("ws://localhost:9120")
|
|
13
|
+
await client.connect()
|
|
14
|
+
|
|
15
|
+
async for event in client.run("fix-123", prompt="Fix all errors"):
|
|
16
|
+
print(event)
|
|
17
|
+
|
|
18
|
+
await client.disconnect()
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
import asyncio
|
|
24
|
+
import json
|
|
25
|
+
import time
|
|
26
|
+
from collections.abc import AsyncGenerator
|
|
27
|
+
from dataclasses import dataclass, field
|
|
28
|
+
from typing import Any
|
|
29
|
+
|
|
30
|
+
import httpx
|
|
31
|
+
|
|
32
|
+
# ── Types ────────────────────────────────────────────────────────────
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@dataclass
|
|
36
|
+
class DaemonClientOptions:
|
|
37
|
+
"""Options for connecting to the daemon."""
|
|
38
|
+
|
|
39
|
+
url: str = "ws://localhost:9120"
|
|
40
|
+
timeout: float = 30.0
|
|
41
|
+
auto_reconnect: bool = True
|
|
42
|
+
max_reconnect_attempts: int = 5
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@dataclass
|
|
46
|
+
class DaemonRunParams:
|
|
47
|
+
"""Parameters for starting an agent run via the daemon."""
|
|
48
|
+
|
|
49
|
+
prompt: str
|
|
50
|
+
workspace: str | None = None
|
|
51
|
+
mode: str = "fast" # "fast" | "plan" | "thinking"
|
|
52
|
+
model: str | None = None
|
|
53
|
+
max_tokens: int | None = None
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@dataclass
|
|
57
|
+
class DaemonEvent:
|
|
58
|
+
"""An event received from the daemon."""
|
|
59
|
+
|
|
60
|
+
kind: str
|
|
61
|
+
data: dict[str, Any] = field(default_factory=dict)
|
|
62
|
+
timestamp: int = 0
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
# ── Client ───────────────────────────────────────────────────────────
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class DaemonClient:
|
|
69
|
+
"""
|
|
70
|
+
WebSocket JSON-RPC client for the MonkeysCode daemon.
|
|
71
|
+
|
|
72
|
+
Provides request/response communication and streaming event delivery.
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
def __init__(self, url: str = "ws://localhost:9120", **kwargs: Any) -> None:
|
|
76
|
+
self._url = url
|
|
77
|
+
self._opts = DaemonClientOptions(url=url, **kwargs)
|
|
78
|
+
self._ws: Any = None
|
|
79
|
+
self._connected = False
|
|
80
|
+
self._request_id = 0
|
|
81
|
+
self._pending: dict[int, asyncio.Future[Any]] = {}
|
|
82
|
+
|
|
83
|
+
@property
|
|
84
|
+
def connected(self) -> bool:
|
|
85
|
+
return self._connected
|
|
86
|
+
|
|
87
|
+
@property
|
|
88
|
+
def url(self) -> str:
|
|
89
|
+
return self._url
|
|
90
|
+
|
|
91
|
+
async def connect(self) -> None:
|
|
92
|
+
"""Connect to the daemon WebSocket."""
|
|
93
|
+
try:
|
|
94
|
+
import websockets # type: ignore[import-untyped]
|
|
95
|
+
self._ws = await websockets.connect(self._url)
|
|
96
|
+
self._connected = True
|
|
97
|
+
except ImportError:
|
|
98
|
+
# Fallback: use HTTP long-polling via REST API
|
|
99
|
+
self._connected = True
|
|
100
|
+
|
|
101
|
+
async def disconnect(self) -> None:
|
|
102
|
+
"""Disconnect from the daemon."""
|
|
103
|
+
if self._ws is not None:
|
|
104
|
+
await self._ws.close()
|
|
105
|
+
self._connected = False
|
|
106
|
+
self._ws = None
|
|
107
|
+
|
|
108
|
+
async def request(self, method: str, params: dict[str, Any] | None = None) -> Any:
|
|
109
|
+
"""Send a JSON-RPC request and wait for a response."""
|
|
110
|
+
self._request_id += 1
|
|
111
|
+
req_id = self._request_id
|
|
112
|
+
|
|
113
|
+
msg = {
|
|
114
|
+
"jsonrpc": "2.0",
|
|
115
|
+
"id": req_id,
|
|
116
|
+
"method": method,
|
|
117
|
+
"params": params or {},
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if self._ws is not None:
|
|
121
|
+
await self._ws.send(json.dumps(msg))
|
|
122
|
+
response = await self._ws.recv()
|
|
123
|
+
data = json.loads(response)
|
|
124
|
+
if "error" in data:
|
|
125
|
+
raise RuntimeError(f"RPC error: {data['error']}")
|
|
126
|
+
return data.get("result")
|
|
127
|
+
else:
|
|
128
|
+
# HTTP fallback
|
|
129
|
+
async with httpx.AsyncClient() as client:
|
|
130
|
+
http_url = self._url.replace("ws://", "http://").replace("wss://", "https://")
|
|
131
|
+
resp = await client.post(f"{http_url}/rpc", json=msg)
|
|
132
|
+
resp.raise_for_status()
|
|
133
|
+
data = resp.json()
|
|
134
|
+
if "error" in data:
|
|
135
|
+
raise RuntimeError(f"RPC error: {data['error']}")
|
|
136
|
+
return data.get("result")
|
|
137
|
+
|
|
138
|
+
async def run(
|
|
139
|
+
self,
|
|
140
|
+
run_id: str,
|
|
141
|
+
*,
|
|
142
|
+
prompt: str,
|
|
143
|
+
workspace: str | None = None,
|
|
144
|
+
mode: str = "fast",
|
|
145
|
+
model: str | None = None,
|
|
146
|
+
) -> AsyncGenerator[DaemonEvent, None]:
|
|
147
|
+
"""Start a run and stream events."""
|
|
148
|
+
params: dict[str, Any] = {
|
|
149
|
+
"runId": run_id,
|
|
150
|
+
"prompt": prompt,
|
|
151
|
+
}
|
|
152
|
+
if workspace:
|
|
153
|
+
params["workspace"] = workspace
|
|
154
|
+
if model:
|
|
155
|
+
params["model"] = model
|
|
156
|
+
params["mode"] = mode
|
|
157
|
+
|
|
158
|
+
# Start the run
|
|
159
|
+
await self.request("agent/run", params)
|
|
160
|
+
|
|
161
|
+
# Stream events
|
|
162
|
+
if self._ws is not None:
|
|
163
|
+
while True:
|
|
164
|
+
try:
|
|
165
|
+
raw = await asyncio.wait_for(self._ws.recv(), timeout=self._opts.timeout)
|
|
166
|
+
data = json.loads(raw)
|
|
167
|
+
|
|
168
|
+
# Skip RPC responses
|
|
169
|
+
if "jsonrpc" in data and "id" in data:
|
|
170
|
+
continue
|
|
171
|
+
|
|
172
|
+
event = DaemonEvent(
|
|
173
|
+
kind=data.get("type", data.get("kind", "unknown")),
|
|
174
|
+
data=data,
|
|
175
|
+
timestamp=data.get("timestamp", int(time.time() * 1000)),
|
|
176
|
+
)
|
|
177
|
+
yield event
|
|
178
|
+
|
|
179
|
+
if event.kind in ("complete", "error", "done"):
|
|
180
|
+
break
|
|
181
|
+
except asyncio.TimeoutError:
|
|
182
|
+
break
|
|
183
|
+
|
|
184
|
+
async def cancel(self, run_id: str) -> None:
|
|
185
|
+
"""Cancel a running agent."""
|
|
186
|
+
await self.request("agent/cancel", {"runId": run_id})
|
|
187
|
+
|
|
188
|
+
async def status(self, run_id: str) -> dict[str, Any]:
|
|
189
|
+
"""Get the status of a run."""
|
|
190
|
+
return await self.request("agent/status", {"runId": run_id})
|
|
191
|
+
|
|
192
|
+
async def list_runs(self) -> list[dict[str, Any]]:
|
|
193
|
+
"""List active runs."""
|
|
194
|
+
return await self.request("agent/list")
|
|
195
|
+
|
|
196
|
+
async def __aenter__(self) -> DaemonClient:
|
|
197
|
+
await self.connect()
|
|
198
|
+
return self
|
|
199
|
+
|
|
200
|
+
async def __aexit__(self, *args: Any) -> None:
|
|
201
|
+
await self.disconnect()
|
monkeyscode/events.py
ADDED
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
"""
|
|
2
|
+
MonkeysCode SDK — Event Types.
|
|
3
|
+
|
|
4
|
+
Pydantic models for all events emitted by the agent during a run.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import Any, Literal
|
|
10
|
+
|
|
11
|
+
from pydantic import BaseModel, Field
|
|
12
|
+
|
|
13
|
+
# ── Token Usage ──────────────────────────────────────────────────────
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class TokenUsage(BaseModel):
|
|
17
|
+
"""Token usage breakdown."""
|
|
18
|
+
|
|
19
|
+
input: int = 0
|
|
20
|
+
output: int = 0
|
|
21
|
+
thinking: int = 0
|
|
22
|
+
total: int = 0
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
# ── File Change ──────────────────────────────────────────────────────
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class FileChange(BaseModel):
|
|
29
|
+
"""A file changed by the agent."""
|
|
30
|
+
|
|
31
|
+
path: str
|
|
32
|
+
action: Literal["created", "modified", "deleted"] = "modified"
|
|
33
|
+
diff: str | None = None
|
|
34
|
+
lines_added: int = 0
|
|
35
|
+
lines_removed: int = 0
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
# ── Tool Call Record ─────────────────────────────────────────────────
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class ToolCallRecord(BaseModel):
|
|
42
|
+
"""A recorded tool call."""
|
|
43
|
+
|
|
44
|
+
tool: str
|
|
45
|
+
args: dict[str, Any] = Field(default_factory=dict)
|
|
46
|
+
duration: int = 0
|
|
47
|
+
result: str | None = None
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
# ── Verification ─────────────────────────────────────────────────────
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class VerificationCheck(BaseModel):
|
|
54
|
+
"""A single verification check result."""
|
|
55
|
+
|
|
56
|
+
passed: bool
|
|
57
|
+
output: str = ""
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class VerificationResult(BaseModel):
|
|
61
|
+
"""Verification results from lint, typecheck, and tests."""
|
|
62
|
+
|
|
63
|
+
lint: VerificationCheck | None = None
|
|
64
|
+
typecheck: VerificationCheck | None = None
|
|
65
|
+
tests: VerificationCheck | None = None
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
# ── Plan Step ────────────────────────────────────────────────────────
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class PlanStep(BaseModel):
|
|
72
|
+
"""A step in a plan."""
|
|
73
|
+
|
|
74
|
+
description: str
|
|
75
|
+
status: Literal["pending", "running", "done", "failed"] = "pending"
|
|
76
|
+
tool: str | None = None
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
# ── Events ───────────────────────────────────────────────────────────
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class StartEvent(BaseModel):
|
|
83
|
+
"""Emitted when a run starts."""
|
|
84
|
+
|
|
85
|
+
type: Literal["start"] = "start"
|
|
86
|
+
timestamp: int
|
|
87
|
+
session_id: str
|
|
88
|
+
model: str
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class ThinkingEvent(BaseModel):
|
|
92
|
+
"""Emitted when the agent is thinking."""
|
|
93
|
+
|
|
94
|
+
type: Literal["thinking"] = "thinking"
|
|
95
|
+
timestamp: int
|
|
96
|
+
content: str | None = None
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
class TextEvent(BaseModel):
|
|
100
|
+
"""Emitted for streaming text content."""
|
|
101
|
+
|
|
102
|
+
type: Literal["text"] = "text"
|
|
103
|
+
timestamp: int
|
|
104
|
+
content: str
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class ToolCallEvent(BaseModel):
|
|
108
|
+
"""Emitted when the agent calls a tool."""
|
|
109
|
+
|
|
110
|
+
type: Literal["tool_call"] = "tool_call"
|
|
111
|
+
timestamp: int
|
|
112
|
+
tool: str
|
|
113
|
+
args: dict[str, Any] = Field(default_factory=dict)
|
|
114
|
+
summary: str = ""
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
class ToolResultEvent(BaseModel):
|
|
118
|
+
"""Emitted when a tool call completes."""
|
|
119
|
+
|
|
120
|
+
type: Literal["tool_result"] = "tool_result"
|
|
121
|
+
timestamp: int
|
|
122
|
+
tool: str
|
|
123
|
+
result: str = ""
|
|
124
|
+
success: bool = True
|
|
125
|
+
duration_ms: int = 0
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
class FileEditEvent(BaseModel):
|
|
129
|
+
"""Emitted when the agent edits a file."""
|
|
130
|
+
|
|
131
|
+
type: Literal["file_edit"] = "file_edit"
|
|
132
|
+
timestamp: int
|
|
133
|
+
path: str
|
|
134
|
+
diff: str = ""
|
|
135
|
+
lines_added: int = 0
|
|
136
|
+
lines_removed: int = 0
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
class FileReadEvent(BaseModel):
|
|
140
|
+
"""Emitted when the agent reads a file."""
|
|
141
|
+
|
|
142
|
+
type: Literal["file_read"] = "file_read"
|
|
143
|
+
timestamp: int
|
|
144
|
+
path: str
|
|
145
|
+
lines: int = 0
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
class TerminalCommandEvent(BaseModel):
|
|
149
|
+
"""Emitted when the agent runs a command."""
|
|
150
|
+
|
|
151
|
+
type: Literal["terminal_command"] = "terminal_command"
|
|
152
|
+
timestamp: int
|
|
153
|
+
command: str
|
|
154
|
+
exit_code: int = 0
|
|
155
|
+
output: str = ""
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
class SearchResultEvent(BaseModel):
|
|
159
|
+
"""Emitted for search results."""
|
|
160
|
+
|
|
161
|
+
type: Literal["search_result"] = "search_result"
|
|
162
|
+
timestamp: int
|
|
163
|
+
query: str
|
|
164
|
+
matches: list[dict[str, Any]] = Field(default_factory=list)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
# ── Daemon Events ────────────────────────────────────────────────────
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
class PlanReadyEvent(BaseModel):
|
|
171
|
+
"""Emitted when the agent produces a plan."""
|
|
172
|
+
|
|
173
|
+
type: Literal["plan_ready"] = "plan_ready"
|
|
174
|
+
timestamp: int
|
|
175
|
+
steps: list[PlanStep] = Field(default_factory=list)
|
|
176
|
+
summary: str = ""
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
class CostUpdateEvent(BaseModel):
|
|
180
|
+
"""Emitted for mid-run cost updates."""
|
|
181
|
+
|
|
182
|
+
type: Literal["cost_update"] = "cost_update"
|
|
183
|
+
timestamp: int
|
|
184
|
+
tokens_in: int = 0
|
|
185
|
+
tokens_out: int = 0
|
|
186
|
+
tokens_thinking: int = 0
|
|
187
|
+
cost: float = 0.0
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
class AgentSpawnedEvent(BaseModel):
|
|
191
|
+
"""Emitted when a sub-agent is spawned."""
|
|
192
|
+
|
|
193
|
+
type: Literal["agent_spawned"] = "agent_spawned"
|
|
194
|
+
timestamp: int
|
|
195
|
+
agent_id: str
|
|
196
|
+
task: str
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
class AgentCompleteEvent(BaseModel):
|
|
200
|
+
"""Emitted when a sub-agent completes."""
|
|
201
|
+
|
|
202
|
+
type: Literal["agent_complete"] = "agent_complete"
|
|
203
|
+
timestamp: int
|
|
204
|
+
agent_id: str
|
|
205
|
+
success: bool = True
|
|
206
|
+
summary: str = ""
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
class FanOutProgressEvent(BaseModel):
|
|
210
|
+
"""Emitted for parallel progress updates."""
|
|
211
|
+
|
|
212
|
+
type: Literal["fan_out_progress"] = "fan_out_progress"
|
|
213
|
+
timestamp: int
|
|
214
|
+
total: int = 0
|
|
215
|
+
completed: int = 0
|
|
216
|
+
running: int = 0
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
class VerificationEvent(BaseModel):
|
|
220
|
+
"""Emitted when verification runs."""
|
|
221
|
+
|
|
222
|
+
type: Literal["verification"] = "verification"
|
|
223
|
+
timestamp: int
|
|
224
|
+
command: str
|
|
225
|
+
passed: bool = False
|
|
226
|
+
output: str = ""
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
class SuggestionEvent(BaseModel):
|
|
230
|
+
"""Emitted with follow-up suggestions."""
|
|
231
|
+
|
|
232
|
+
type: Literal["suggestion"] = "suggestion"
|
|
233
|
+
timestamp: int
|
|
234
|
+
suggestions: list[str] = Field(default_factory=list)
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
# ── Terminal Events ──────────────────────────────────────────────────
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
class ErrorEvent(BaseModel):
|
|
241
|
+
"""Emitted on error."""
|
|
242
|
+
|
|
243
|
+
type: Literal["error"] = "error"
|
|
244
|
+
timestamp: int
|
|
245
|
+
code: str = "UNKNOWN"
|
|
246
|
+
message: str = ""
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
class CompleteEvent(BaseModel):
|
|
250
|
+
"""Emitted when a run completes."""
|
|
251
|
+
|
|
252
|
+
type: Literal["complete"] = "complete"
|
|
253
|
+
timestamp: int
|
|
254
|
+
summary: str = ""
|
|
255
|
+
files_changed: list[FileChange] = Field(default_factory=list)
|
|
256
|
+
tokens: TokenUsage = Field(default_factory=TokenUsage)
|
|
257
|
+
cost: float = 0.0
|
|
258
|
+
duration_ms: int = 0
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
# ── Union Type ───────────────────────────────────────────────────────
|
|
262
|
+
|
|
263
|
+
AgentEvent = (
|
|
264
|
+
StartEvent
|
|
265
|
+
| ThinkingEvent
|
|
266
|
+
| TextEvent
|
|
267
|
+
| ToolCallEvent
|
|
268
|
+
| ToolResultEvent
|
|
269
|
+
| FileEditEvent
|
|
270
|
+
| FileReadEvent
|
|
271
|
+
| TerminalCommandEvent
|
|
272
|
+
| SearchResultEvent
|
|
273
|
+
| PlanReadyEvent
|
|
274
|
+
| CostUpdateEvent
|
|
275
|
+
| AgentSpawnedEvent
|
|
276
|
+
| AgentCompleteEvent
|
|
277
|
+
| FanOutProgressEvent
|
|
278
|
+
| VerificationEvent
|
|
279
|
+
| SuggestionEvent
|
|
280
|
+
| ErrorEvent
|
|
281
|
+
| CompleteEvent
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
# ── Result Types ─────────────────────────────────────────────────────
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
class AgentResult(BaseModel):
|
|
289
|
+
"""Result from a completed agent run."""
|
|
290
|
+
|
|
291
|
+
success: bool = True
|
|
292
|
+
status: Literal[
|
|
293
|
+
"completed", "failed", "partial",
|
|
294
|
+
"timeout", "interrupted", "cancelled",
|
|
295
|
+
] = "completed"
|
|
296
|
+
summary: str = ""
|
|
297
|
+
files_changed: list[FileChange] = Field(default_factory=list)
|
|
298
|
+
tool_calls: list[ToolCallRecord] = Field(default_factory=list)
|
|
299
|
+
tokens: TokenUsage = Field(default_factory=TokenUsage)
|
|
300
|
+
cost: float = 0.0
|
|
301
|
+
duration_ms: int = 0
|
|
302
|
+
session_id: str = ""
|
|
303
|
+
exit_code: int = 0
|
|
304
|
+
model: str = "auto"
|
|
305
|
+
verification: VerificationResult | None = None
|
|
306
|
+
error: str | None = None
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
class GoalResult(AgentResult):
|
|
310
|
+
"""Result from a goal-mode run."""
|
|
311
|
+
|
|
312
|
+
goal_met: bool = False
|
|
313
|
+
iterations: int = 0
|
|
314
|
+
iteration_summaries: list[str] = Field(default_factory=list)
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
class GoalOptions(BaseModel):
|
|
318
|
+
"""Options for goal-mode runs."""
|
|
319
|
+
|
|
320
|
+
max_iterations: int = 10
|
|
321
|
+
timeout: int = 300_000
|
|
322
|
+
max_cost: float | None = None
|
|
323
|
+
verify_command: str | None = None
|