Skip to content

Commit e5a53f5

Browse files
📝 Add docstrings to feature/my-updates
Docstrings generation was requested by @getworken. * #2 (comment) The following files were modified: * `agent.py` * `api/agent_types.py` * `api/config.py` * `api/connection.py` * `api/dependency_resolver.py` * `api/feature_repository.py` * `api/logging_config.py` * `api/migrations.py` * `api/models.py` * `autonomous_agent_demo.py` * `client.py` * `mcp_server/feature_mcp.py` * `parallel_orchestrator.py` * `progress.py` * `quality_gates.py` * `rate_limit_utils.py` * `security.py` * `server/main.py` * `server/routers/agent.py` * `server/routers/assistant_chat.py` * `server/routers/devserver.py` * `server/routers/features.py` * `server/routers/filesystem.py` * `server/routers/projects.py` * `server/routers/schedules.py` * `server/routers/settings.py` * `server/routers/spec_creation.py` * `server/routers/terminal.py` * `server/schemas.py` * `server/services/assistant_chat_session.py` * `server/services/dev_server_manager.py` * `server/services/expand_chat_session.py` * `server/services/process_manager.py` * `server/services/spec_chat_session.py` * `server/services/terminal_manager.py` * `server/utils/auth.py` * `server/utils/process_utils.py` * `server/utils/validation.py` * `server/websocket.py` * `start_ui.py` * `structured_logging.py` * `tests/conftest.py` * `tests/test_async_examples.py` * `tests/test_repository_and_config.py` * `tests/test_security.py` * `tests/test_security_integration.py` * `ui/src/App.tsx` * `ui/src/components/AssistantPanel.tsx` * `ui/src/components/ConversationHistory.tsx` * `ui/src/components/DebugLogViewer.tsx` * `ui/src/components/IDESelectionModal.tsx` * `ui/src/components/ProjectSelector.tsx` * `ui/src/components/ProjectSetupRequired.tsx` * `ui/src/components/ResetProjectModal.tsx` * `ui/src/components/ScheduleModal.tsx` * `ui/src/components/SettingsModal.tsx` * `ui/src/components/ThemeSelector.tsx` * `ui/src/hooks/useAssistantChat.ts` * `ui/src/hooks/useConversations.ts` * `ui/src/hooks/useProjects.ts` * `ui/src/lib/api.ts`
1 parent b65f82b commit e5a53f5

61 files changed

Lines changed: 2775 additions & 1377 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

agent.py

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -58,17 +58,20 @@ async def run_agent_session(
5858
project_dir: Path,
5959
) -> tuple[str, str]:
6060
"""
61-
Run a single agent session using Claude Agent SDK.
62-
63-
Args:
64-
client: Claude SDK client
65-
message: The prompt to send
66-
project_dir: Project directory path
67-
61+
Run a single interaction with the Claude Agent SDK and stream the assistant and tool output to stdout.
62+
63+
Parameters:
64+
client (ClaudeSDKClient): SDK client used to send the prompt and receive streamed messages.
65+
message (str): Prompt text to send to the agent.
66+
project_dir (Path): Project directory path used for contextual output.
67+
6868
Returns:
69-
(status, response_text) where status is:
70-
- "continue" if agent should continue working
71-
- "error" if an error occurred
69+
tuple[str, str]: A pair (status, payload) where:
70+
- status is `"continue"` when the session completed normally,
71+
`"rate_limit"` when a rate-limit error was detected, or `"error"` for other failures.
72+
- payload is the assistant's concatenated response text when status is `"continue"`,
73+
the retry-after seconds as a string or `"unknown"` when status is `"rate_limit"`,
74+
or the error message when status is `"error"`.
7275
"""
7376
print("Sending prompt to Claude Agent SDK...\n")
7477

@@ -471,4 +474,4 @@ async def run_autonomous_agent(
471474
}
472475
)
473476

474-
print("\nDone!")
477+
print("\nDone!")

api/agent_types.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,10 @@ class AgentType(str, Enum):
2525
TESTING = "testing"
2626

2727
def __str__(self) -> str:
28-
"""Return the string value for string operations."""
29-
return self.value
28+
"""
29+
Return the enum member's underlying string value.
30+
31+
Returns:
32+
str: The underlying string value of the enum member.
33+
"""
34+
return self.value

api/config.py

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -114,12 +114,22 @@ class AutocoderConfig(BaseSettings):
114114

115115
@property
116116
def is_using_alternative_api(self) -> bool:
117-
"""Check if using an alternative API provider (not Claude directly)."""
117+
"""
118+
Indicates whether an alternative Anthropic-compatible API endpoint and auth token are configured.
119+
120+
Returns:
121+
True if both `anthropic_base_url` and `anthropic_auth_token` are set, False otherwise.
122+
"""
118123
return bool(self.anthropic_base_url and self.anthropic_auth_token)
119124

120125
@property
121126
def is_using_ollama(self) -> bool:
122-
"""Check if using Ollama local models."""
127+
"""
128+
Determine whether the configuration targets a local Ollama instance.
129+
130+
Returns:
131+
`true` if `anthropic_base_url` is set, `anthropic_auth_token` equals `"ollama"`, and the base URL's hostname is `localhost`, `127.0.0.1`, or `::1`; `false` otherwise.
132+
"""
123133
if not self.anthropic_base_url or self.anthropic_auth_token != "ollama":
124134
return False
125135
host = urlparse(self.anthropic_base_url).hostname or ""
@@ -131,12 +141,13 @@ def is_using_ollama(self) -> bool:
131141

132142

133143
def get_config() -> AutocoderConfig:
134-
"""Get the global configuration instance.
135-
136-
Creates the config on first access (lazy loading).
137-
144+
"""
145+
Retrieve the global AutocoderConfig singleton.
146+
147+
Creates and caches the AutocoderConfig on first access by loading settings from the environment and .env file.
148+
138149
Returns:
139-
The global AutocoderConfig instance.
150+
The global AutocoderConfig instance; created on first access if not already initialized.
140151
"""
141152
global _config
142153
if _config is None:
@@ -145,13 +156,12 @@ def get_config() -> AutocoderConfig:
145156

146157

147158
def reload_config() -> AutocoderConfig:
148-
"""Reload configuration from environment.
149-
150-
Useful after environment changes or for testing.
151-
159+
"""
160+
Reloads the global AutocoderConfig by re-reading environment variables.
161+
152162
Returns:
153-
The reloaded AutocoderConfig instance.
163+
AutocoderConfig: The reloaded configuration instance.
154164
"""
155165
global _config
156166
_config = AutocoderConfig()
157-
return _config
167+
return _config

api/connection.py

Lines changed: 82 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,14 @@
4141

4242

4343
def _is_network_path(path: Path) -> bool:
44-
"""Detect if path is on a network filesystem.
45-
46-
WAL mode doesn't work reliably on network filesystems (NFS, SMB, CIFS)
47-
and can cause database corruption. This function detects common network
48-
path patterns so we can fall back to DELETE mode.
49-
50-
Args:
51-
path: The path to check
52-
44+
"""
45+
Detects whether a given path is located on a network filesystem.
46+
47+
Detection is best-effort and may be conservative; if platform or system
48+
information cannot be inspected, the function will return False.
49+
5350
Returns:
54-
True if the path appears to be on a network filesystem
51+
True if the path appears to be on a network filesystem, False otherwise.
5552
"""
5653
path_str = str(path.resolve())
5754

@@ -92,39 +89,42 @@ def _is_network_path(path: Path) -> bool:
9289

9390

9491
def get_database_path(project_dir: Path) -> Path:
95-
"""Return the path to the SQLite database for a project."""
92+
"""
93+
Get the filesystem path for the project's SQLite database file.
94+
95+
Returns:
96+
database_path (Path): Path to the 'features.db' file inside the given project directory.
97+
"""
9698
return project_dir / "features.db"
9799

98100

99101
def get_database_url(project_dir: Path) -> str:
100-
"""Return the SQLAlchemy database URL for a project.
101-
102-
Uses POSIX-style paths (forward slashes) for cross-platform compatibility.
102+
"""
103+
Builds the SQLAlchemy SQLite database URL for the given project directory.
104+
105+
The path portion uses POSIX-style forward slashes for cross-platform compatibility.
106+
107+
Returns:
108+
database_url (str): SQLite URL pointing to the project's features.db (e.g. "sqlite:////path/to/features.db").
103109
"""
104110
db_path = get_database_path(project_dir)
105111
return f"sqlite:///{db_path.as_posix()}"
106112

107113

108114
def get_robust_connection(db_path: Path) -> sqlite3.Connection:
109115
"""
110-
Get a robust SQLite connection with proper settings for concurrent access.
111-
112-
This should be used by all code that accesses the database directly via sqlite3
113-
(not through SQLAlchemy). It ensures consistent settings across all access points.
114-
115-
Settings applied:
116-
- WAL mode for better concurrency (unless on network filesystem)
117-
- Busy timeout of 30 seconds
118-
- Synchronous mode NORMAL for balance of safety and performance
119-
120-
Args:
121-
db_path: Path to the SQLite database file
122-
116+
Open and configure a sqlite3.Connection optimized for concurrent access.
117+
118+
Configures the connection with a 30-second busy timeout, enables WAL journal mode when the database file is on a local filesystem, and sets synchronous mode to NORMAL.
119+
120+
Parameters:
121+
db_path (Path): Path to the SQLite database file.
122+
123123
Returns:
124-
Configured sqlite3.Connection
125-
124+
sqlite3.Connection: Configured SQLite connection.
125+
126126
Raises:
127-
sqlite3.Error: If connection cannot be established
127+
sqlite3.Error: If the database connection or PRAGMA configuration fails.
128128
"""
129129
conn = sqlite3.connect(str(db_path), timeout=SQLITE_BUSY_TIMEOUT_MS / 1000)
130130

@@ -148,18 +148,13 @@ def get_robust_connection(db_path: Path) -> sqlite3.Connection:
148148
@contextmanager
149149
def robust_db_connection(db_path: Path):
150150
"""
151-
Context manager for robust SQLite connections with automatic cleanup.
152-
153-
Usage:
154-
with robust_db_connection(db_path) as conn:
155-
cursor = conn.cursor()
156-
cursor.execute("SELECT * FROM features")
157-
158-
Args:
159-
db_path: Path to the SQLite database file
160-
151+
Context manager that yields a configured sqlite3.Connection and ensures it is closed on exit.
152+
153+
Parameters:
154+
db_path (Path): Path to the SQLite database file.
155+
161156
Yields:
162-
Configured sqlite3.Connection
157+
sqlite3.Connection: A configured connection to the database; closed when the context exits.
163158
"""
164159
conn = None
165160
try:
@@ -178,22 +173,21 @@ def execute_with_retry(
178173
max_retries: int = SQLITE_MAX_RETRIES
179174
) -> Any:
180175
"""
181-
Execute a SQLite query with automatic retry on transient errors.
182-
183-
Handles SQLITE_BUSY and SQLITE_LOCKED errors with exponential backoff.
184-
185-
Args:
186-
db_path: Path to the SQLite database file
187-
query: SQL query to execute
188-
params: Query parameters (tuple)
189-
fetch: What to fetch - "none", "one", "all"
190-
max_retries: Maximum number of retry attempts
191-
176+
Execute a SQL statement against the given SQLite file and retry on transient lock/busy errors.
177+
178+
Parameters:
179+
db_path (Path): Path to the SQLite database file.
180+
query (str): SQL statement to execute.
181+
params (tuple): Parameters to bind to the SQL statement.
182+
fetch (str): Result mode: "none" commits and returns the number of affected rows, "one" returns a single row (or None), "all" returns all rows as a list.
183+
max_retries (int): Maximum number of retry attempts for transient errors.
184+
192185
Returns:
193-
Query result based on fetch parameter
194-
186+
int | tuple | list | None: For `fetch == "none"`, the number of rows affected; for `fetch == "one"`, a single row tuple or `None`; for `fetch == "all"`, a list of row tuples.
187+
195188
Raises:
196-
sqlite3.Error: If query fails after all retries
189+
sqlite3.DatabaseError: On database corruption or other database-level errors.
190+
sqlite3.OperationalError: If the statement fails after all retries (including persistent lock/busy conditions).
197191
"""
198192
last_error = None
199193
delay = SQLITE_RETRY_DELAY_MS / 1000 # Convert to seconds
@@ -241,13 +235,17 @@ def execute_with_retry(
241235

242236
def check_database_health(db_path: Path) -> dict:
243237
"""
244-
Check the health of a SQLite database.
245-
238+
Assess the integrity and journal mode of a SQLite database file.
239+
240+
Parameters:
241+
db_path (Path): Path to the SQLite database file to check.
242+
246243
Returns:
247-
Dict with:
248-
- healthy (bool): True if database passes integrity check
249-
- journal_mode (str): Current journal mode (WAL/DELETE/etc)
250-
- error (str, optional): Error message if unhealthy
244+
dict: A dictionary containing:
245+
- healthy (bool): `True` if the database passes PRAGMA integrity_check, `False` otherwise.
246+
- journal_mode (str, optional): The current journal mode (e.g., "WAL", "DELETE") when available.
247+
- integrity (str, optional): The raw result of PRAGMA integrity_check when available (e.g., "ok").
248+
- error (str, optional): Error message when the file is missing or an integrity/IO error occurred.
251249
"""
252250
if not db_path.exists():
253251
return {"healthy": False, "error": "Database file does not exist"}
@@ -342,22 +340,13 @@ def create_database(project_dir: Path) -> tuple:
342340

343341
def checkpoint_wal(project_dir: Path) -> bool:
344342
"""
345-
Checkpoint the WAL file to ensure all changes are written to the main database.
346-
347-
This should be called before exiting the orchestrator to ensure data durability
348-
and prevent database corruption when multiple agents are running.
349-
350-
WAL checkpoint modes:
351-
- PASSIVE (0): Checkpoint as much as possible without blocking
352-
- FULL (1): Checkpoint everything, block writers if necessary
353-
- RESTART (2): Like FULL but also truncate WAL
354-
- TRUNCATE (3): Like RESTART but ensure WAL is zero bytes
355-
356-
Args:
357-
project_dir: Directory containing the project database
358-
343+
Force a WAL checkpoint for the project's SQLite database to flush and truncate the WAL into the main database.
344+
345+
Parameters:
346+
project_dir (Path): Directory containing the project's SQLite database file (features.db).
347+
359348
Returns:
360-
True if checkpoint succeeded, False otherwise
349+
`true` if the checkpoint succeeded or the database file does not exist, `false` otherwise.
361350
"""
362351
db_path = get_database_path(project_dir)
363352
if not db_path.exists():
@@ -386,13 +375,10 @@ def checkpoint_wal(project_dir: Path) -> bool:
386375

387376
def invalidate_engine_cache(project_dir: Path) -> None:
388377
"""
389-
Invalidate the engine cache for a specific project.
390-
391-
Call this when you need to ensure fresh database connections, e.g.,
392-
after subprocess commits that may not be visible to the current connection.
393-
394-
Args:
395-
project_dir: Directory containing the project
378+
Invalidate and dispose the cached SQLAlchemy Engine and SessionLocal for the given project directory.
379+
380+
Parameters:
381+
project_dir (Path): Path to the project directory whose cached engine should be removed.
396382
"""
397383
cache_key = project_dir.resolve().as_posix()
398384
with _engine_cache_lock:
@@ -411,17 +397,24 @@ def invalidate_engine_cache(project_dir: Path) -> None:
411397

412398

413399
def set_session_maker(session_maker: sessionmaker) -> None:
414-
"""Set the global session maker."""
400+
"""
401+
Configure the module-wide SQLAlchemy session factory used by get_db and get_db_session.
402+
403+
Parameters:
404+
session_maker (sessionmaker): A SQLAlchemy sessionmaker instance to use as the global session factory.
405+
"""
415406
global _session_maker
416407
_session_maker = session_maker
417408

418409

419410
def get_db() -> Session:
420411
"""
421-
Dependency for FastAPI to get database session.
422-
423-
Yields a database session and ensures it's closed after use.
424-
Properly rolls back on error to prevent PendingRollbackError.
412+
Provide a SQLAlchemy Session for FastAPI dependency injection.
413+
414+
Yields a Session for database operations and ensures the session is closed afterwards. On exception, rolls back the transaction before re-raising.
415+
416+
Returns:
417+
Session: A SQLAlchemy Session instance for use in request handling.
425418
"""
426419
if _session_maker is None:
427420
raise RuntimeError("Database not initialized. Call set_session_maker first.")
@@ -467,4 +460,4 @@ def get_db_session(project_dir: Path):
467460
session.rollback()
468461
raise
469462
finally:
470-
session.close()
463+
session.close()

0 commit comments

Comments
 (0)