2c838dedee
CI / lint (pull_request) Failing after 17s
CI / typecheck (pull_request) Successful in 46s
CI / quality (pull_request) Successful in 32s
CI / coverage (pull_request) Has been skipped
CI / security (pull_request) Successful in 53s
CI / benchmark-publish (pull_request) Has been skipped
CI / benchmark-regression (pull_request) Has been skipped
CI / build (pull_request) Successful in 31s
CI / e2e_tests (pull_request) Successful in 4m19s
CI / unit_tests (pull_request) Successful in 5m18s
CI / docker (pull_request) Has been skipped
CI / integration_tests (pull_request) Successful in 5m46s
Add agents repo index and agents repo status CLI commands. The repo index command triggers full or incremental indexing of a repository resource. The status command displays indexing metadata including file count, token estimate, primary language, and status. Both commands support text and JSON output formats. Wires the existing RepoIndexingService backend to the CLI layer. Also fixes pre-existing test failures discovered during full nox suite verification. ISSUES CLOSED: #856
786 lines
36 KiB
Plaintext
786 lines
36 KiB
Plaintext
*** Settings ***
|
|
Documentation Integration tests for database layer with repositories and Unit of Work
|
|
Library OperatingSystem
|
|
Library String
|
|
Library Collections
|
|
Library Process
|
|
Library indentation_library.py
|
|
Resource ${CURDIR}/common.resource
|
|
|
|
*** Variables ***
|
|
${PYTHON} python
|
|
${TEST_PROJECT_NAME} test-db-project
|
|
${TEST_PLAN_NAME} test-plan
|
|
${TEST_FILE} test_file.py
|
|
|
|
*** Test Cases ***
|
|
Database Can Be Initialized
|
|
[Documentation] Verify database initialization works
|
|
Create Temporary Project Directory
|
|
Initialize Database
|
|
Database Should Exist
|
|
Cleanup Test Environment
|
|
|
|
Project Repository CRUD Operations
|
|
[Documentation] Test Create, Read, Update, Delete operations for projects
|
|
Create Temporary Project Directory
|
|
Initialize Database
|
|
${project_id}= Create Project In Database ${TEST_PROJECT_NAME}
|
|
Should Be True ${project_id} > 0
|
|
${project}= Get Project By ID ${project_id}
|
|
Should Be Equal ${project['name']} ${TEST_PROJECT_NAME}
|
|
Update Project Name ${project_id} updated-project
|
|
${updated}= Get Project By ID ${project_id}
|
|
Should Be Equal ${updated['name']} updated-project
|
|
Cleanup Test Environment
|
|
|
|
Plan Repository Operations
|
|
[Documentation] Test plan repository operations
|
|
Create Temporary Project Directory
|
|
Initialize Database
|
|
${project_id}= Create Project In Database ${TEST_PROJECT_NAME}
|
|
${plan_id}= Create Plan For Project ${project_id} plan-1
|
|
Should Be True ${plan_id} > 0
|
|
${plan2_id}= Create Plan For Project ${project_id} plan-2
|
|
Set Current Plan ${project_id} ${plan2_id}
|
|
${current}= Get Current Plan For Project ${project_id}
|
|
Should Be Equal ${current['name']} plan-2
|
|
${all_plans}= Get All Plans For Project ${project_id}
|
|
Length Should Be ${all_plans} 2
|
|
Cleanup Test Environment
|
|
|
|
Context Repository Operations
|
|
[Documentation] Test context file management
|
|
Create Temporary Project Directory
|
|
Initialize Database
|
|
${project_id}= Create Project In Database ${TEST_PROJECT_NAME}
|
|
${plan_id}= Create Plan For Project ${project_id} ${TEST_PLAN_NAME}
|
|
${context_id}= Add File To Context ${plan_id} /tmp/test.py 100
|
|
Should Be True ${context_id} > 0
|
|
Add File To Context ${plan_id} /tmp/main.py 200
|
|
${contexts}= Get Context For Plan ${plan_id}
|
|
Length Should Be ${contexts} 2
|
|
Remove Context Item ${context_id}
|
|
${remaining}= Get Context For Plan ${plan_id}
|
|
Length Should Be ${remaining} 1
|
|
Clear Context For Plan ${plan_id}
|
|
${empty}= Get Context For Plan ${plan_id}
|
|
Length Should Be ${empty} 0
|
|
Cleanup Test Environment
|
|
|
|
Change Repository Operations
|
|
[Documentation] Test change tracking
|
|
Create Temporary Project Directory
|
|
Initialize Database
|
|
${project_id}= Create Project In Database ${TEST_PROJECT_NAME}
|
|
${plan_id}= Create Plan For Project ${project_id} ${TEST_PLAN_NAME}
|
|
${change_id}= Add Change To Plan ${plan_id} new_file.py create
|
|
Should Be True ${change_id} > 0
|
|
Add Change To Plan ${plan_id} existing.py modify
|
|
${changes}= Get Changes For Plan ${plan_id}
|
|
Length Should Be ${changes} 2
|
|
Mark Change Applied ${change_id}
|
|
${updated_changes}= Get Changes For Plan ${plan_id}
|
|
${applied_count}= Count Applied Changes ${updated_changes}
|
|
Should Be Equal As Integers ${applied_count} 1
|
|
Cleanup Test Environment
|
|
|
|
Unit Of Work Transaction Commit
|
|
[Documentation] Test that UoW commits all changes together
|
|
Create Temporary Project Directory
|
|
Initialize Database
|
|
Start Transaction
|
|
${project_id}= Create Project In Transaction transaction-project
|
|
${plan_id}= Create Plan In Transaction ${project_id} transaction-plan
|
|
Commit Transaction
|
|
# Verify both were saved
|
|
${project}= Get Project By Name transaction-project
|
|
Should Not Be Equal ${project} ${None}
|
|
${plans}= Get All Plans For Project ${project_id}
|
|
Length Should Be ${plans} 1
|
|
Cleanup Test Environment
|
|
|
|
Unit Of Work Transaction Rollback
|
|
[Documentation] Test that UoW rolls back on error
|
|
Create Temporary Project Directory
|
|
Initialize Database
|
|
Test Transaction Rollback
|
|
# Verify nothing was saved
|
|
${project}= Get Project By Name rollback-project
|
|
Should Be Equal ${project} ${None}
|
|
Cleanup Test Environment
|
|
|
|
Service Layer Uses Repositories
|
|
[Documentation] Test that services properly use repositories
|
|
Create Temporary Project Directory
|
|
Initialize Project With Service service-project
|
|
${project}= Get Current Project From Service
|
|
Should Not Be Equal ${project} ${None}
|
|
Create Plan With Service Test plan
|
|
${plan}= Get Current Plan From Service
|
|
Should Not Be Equal ${plan} ${None}
|
|
Create Test File ${TEST_FILE} test content
|
|
Add Context With Service ${TEST_FILE}
|
|
${context_count}= Get Context Count From Service
|
|
Should Be True ${context_count} > 0
|
|
Cleanup Test Environment
|
|
|
|
End To End Database Workflow
|
|
[Documentation] Test complete workflow using database
|
|
Create Temporary Project Directory
|
|
|
|
# Run the complete workflow in one script
|
|
${result}= Run Python Script
|
|
... import sys
|
|
... import os
|
|
... from cleveragents.application.services.project_service import ProjectService
|
|
... from cleveragents.application.services.plan_service import PlanService
|
|
... from cleveragents.application.services.context_service import ContextService
|
|
... from cleveragents.infrastructure.database.unit_of_work import UnitOfWork
|
|
... from cleveragents.config.settings import Settings
|
|
... from features.mocks.mock_ai_provider import MockAIProvider
|
|
... from pathlib import Path
|
|
... os.environ["CLEVERAGENTS_TESTING_USE_MOCK_AI"] = "true"
|
|
... settings = Settings()
|
|
... uow = UnitOfWork('sqlite:///${TEMP_DIR}/test.db')
|
|
... mock_ai = MockAIProvider()
|
|
... project_service = ProjectService(settings, uow)
|
|
... plan_service = PlanService(settings, uow, mock_ai)
|
|
... plan_service.actor_service.ensure_default_mock_actor(force=True)
|
|
... context_service = ContextService(settings, uow)
|
|
... # Initialize project
|
|
... project = project_service.initialize_project('e2e-project', Path('${TEMP_DIR}'))
|
|
... # Create plan
|
|
... plan = plan_service.create_plan(project, 'Create a REST API')
|
|
... # Add context file
|
|
... test_file = Path('${TEMP_DIR}/${TEST_FILE}')
|
|
... test_file.write_text('# Sample Python file' + chr(10) + 'print("Hello World")')
|
|
... context_service.add_to_context(project, test_file)
|
|
... # Build plan
|
|
... changes = plan_service.build_plan(project)
|
|
... # Apply changes
|
|
... applied_count = plan_service.apply_changes(project)
|
|
... print(applied_count)
|
|
${applied_count}= Convert To Integer ${result}
|
|
Should Be True ${applied_count} > 0
|
|
|
|
Cleanup Test Environment
|
|
|
|
*** Keywords ***
|
|
Create Temporary Project Directory
|
|
[Documentation] Create a temporary directory for testing
|
|
${temp_dir}= Evaluate tempfile.mkdtemp() modules=tempfile
|
|
Set Suite Variable ${TEMP_DIR} ${temp_dir}
|
|
Set Environment Variable CLEVERAGENTS_HOME ${temp_dir}
|
|
|
|
Initialize Database
|
|
[Documentation] Initialize the database
|
|
${result}= Run Python Script
|
|
... from cleveragents.infrastructure.database.unit_of_work import UnitOfWork
|
|
... uow = UnitOfWork('sqlite:///${TEMP_DIR}/test.db')
|
|
... uow.init_database()
|
|
... print('Database initialized')
|
|
Should Contain ${result} Database initialized
|
|
|
|
Database Should Exist
|
|
[Documentation] Verify database file exists
|
|
File Should Exist ${TEMP_DIR}/test.db
|
|
|
|
Create Project In Database
|
|
[Documentation] Create a project using repository
|
|
[Arguments] ${name}
|
|
${result}= Run Python Script
|
|
... from cleveragents.infrastructure.database.unit_of_work import UnitOfWork
|
|
... from cleveragents.domain.models.core import Project, ProjectSettings
|
|
... from pathlib import Path
|
|
... from datetime import datetime
|
|
... uow = UnitOfWork('sqlite:///${TEMP_DIR}/test.db')
|
|
... with uow.transaction() as ctx:
|
|
... project = Project(name='${name}', path=Path('${TEMP_DIR}'), settings=ProjectSettings(), created_at=datetime.now(), updated_at=datetime.now())
|
|
... created = ctx.projects.create(project)
|
|
... print(created.id)
|
|
${project_id}= Convert To Integer ${result}
|
|
RETURN ${project_id}
|
|
|
|
Get Project By ID
|
|
[Documentation] Get project by ID
|
|
[Arguments] ${project_id}
|
|
${result}= Run Python Script
|
|
... from cleveragents.infrastructure.database.unit_of_work import UnitOfWork
|
|
... import json
|
|
... uow = UnitOfWork('sqlite:///${TEMP_DIR}/test.db')
|
|
... with uow.transaction() as ctx:
|
|
... project = ctx.projects.get_by_id(${project_id})
|
|
... print(json.dumps({'id': project.id, 'name': project.name}))
|
|
${project}= Evaluate json.loads('''${result}''') json
|
|
RETURN ${project}
|
|
|
|
Get Project By Name
|
|
[Documentation] Get project by name
|
|
[Arguments] ${name}
|
|
${result}= Run Python Script
|
|
... from cleveragents.infrastructure.database.unit_of_work import UnitOfWork
|
|
... import json
|
|
... uow = UnitOfWork('sqlite:///${TEMP_DIR}/test.db')
|
|
... with uow.transaction() as ctx:
|
|
... project = ctx.projects.get_by_name('${name}')
|
|
... if project is None:
|
|
... print('null')
|
|
... else:
|
|
... print(json.dumps({'id': project.id, 'name': project.name}))
|
|
${project}= Run Keyword If '${result}' == 'null' Set Variable ${None}
|
|
... ELSE Evaluate json.loads('''${result}''') json
|
|
RETURN ${project}
|
|
|
|
Update Project Name
|
|
[Documentation] Update project name
|
|
[Arguments] ${project_id} ${new_name}
|
|
${result}= Run Python Script
|
|
... from cleveragents.infrastructure.database.unit_of_work import UnitOfWork
|
|
... uow = UnitOfWork('sqlite:///${TEMP_DIR}/test.db')
|
|
... with uow.transaction() as ctx:
|
|
... project = ctx.projects.get_by_id(${project_id})
|
|
... project.name = '${new_name}'
|
|
... ctx.projects.update(project)
|
|
... print('OK')
|
|
|
|
Create Plan For Project
|
|
[Documentation] Create a plan for a project
|
|
[Arguments] ${project_id} ${plan_name}
|
|
${result}= Run Python Script
|
|
... from cleveragents.infrastructure.database.unit_of_work import UnitOfWork
|
|
... from cleveragents.domain.models.core import Plan, PlanStatus
|
|
... from datetime import datetime
|
|
... uow = UnitOfWork('sqlite:///${TEMP_DIR}/test.db')
|
|
... with uow.transaction() as ctx:
|
|
... plan = Plan(project_id=${project_id}, name='${plan_name}', prompt='Test', status=PlanStatus.PENDING, current=False, created_at=datetime.now(), updated_at=datetime.now())
|
|
... created = ctx.plans.create(plan)
|
|
... print(created.id)
|
|
${plan_id}= Convert To Integer ${result}
|
|
RETURN ${plan_id}
|
|
|
|
Set Current Plan
|
|
[Documentation] Set a plan as current
|
|
[Arguments] ${project_id} ${plan_id}
|
|
${result}= Run Python Script
|
|
... from cleveragents.infrastructure.database.unit_of_work import UnitOfWork
|
|
... uow = UnitOfWork('sqlite:///${TEMP_DIR}/test.db')
|
|
... with uow.transaction() as ctx:
|
|
... ctx.plans.set_current(${project_id}, ${plan_id})
|
|
... print('OK')
|
|
|
|
Get Current Plan For Project
|
|
[Documentation] Get current plan for project
|
|
[Arguments] ${project_id}
|
|
${result}= Run Python Script
|
|
... from cleveragents.infrastructure.database.unit_of_work import UnitOfWork
|
|
... import json
|
|
... uow = UnitOfWork('sqlite:///${TEMP_DIR}/test.db')
|
|
... with uow.transaction() as ctx:
|
|
... plan = ctx.plans.get_current_for_project(${project_id})
|
|
... print(json.dumps({'id': plan.id, 'name': plan.name}) if plan else '{}')
|
|
${plan}= Evaluate json.loads('''${result}''') json
|
|
RETURN ${plan}
|
|
|
|
Get All Plans For Project
|
|
[Documentation] Get all plans for a project
|
|
[Arguments] ${project_id}
|
|
${result}= Run Python Script
|
|
... from cleveragents.infrastructure.database.unit_of_work import UnitOfWork
|
|
... import json
|
|
... uow = UnitOfWork('sqlite:///${TEMP_DIR}/test.db')
|
|
... with uow.transaction() as ctx:
|
|
... plans = ctx.plans.get_all_for_project(${project_id})
|
|
... print(json.dumps([{'id': p.id, 'name': p.name} for p in plans]))
|
|
${plans}= Evaluate json.loads('''${result}''') json
|
|
RETURN ${plans}
|
|
|
|
Add File To Context
|
|
[Documentation] Add a file to context
|
|
[Arguments] ${plan_id} ${file_path} ${size}
|
|
${result}= Run Python Script
|
|
... from cleveragents.infrastructure.database.unit_of_work import UnitOfWork
|
|
... from cleveragents.domain.models.core import Context, ContextType
|
|
... from datetime import datetime
|
|
... uow = UnitOfWork('sqlite:///${TEMP_DIR}/test.db')
|
|
... with uow.transaction() as ctx:
|
|
... context = Context(plan_id=${plan_id}, type=ContextType.FILE, path='${file_path}', content='Test content', file_hash='abc123', size=${size}, added_at=datetime.now())
|
|
... created = ctx.contexts.add(context)
|
|
... print(created.id)
|
|
${context_id}= Convert To Integer ${result}
|
|
RETURN ${context_id}
|
|
|
|
Get Context For Plan
|
|
[Documentation] Get context for a plan
|
|
[Arguments] ${plan_id}
|
|
${result}= Run Python Script
|
|
... from cleveragents.infrastructure.database.unit_of_work import UnitOfWork
|
|
... import json
|
|
... uow = UnitOfWork('sqlite:///${TEMP_DIR}/test.db')
|
|
... with uow.transaction() as ctx:
|
|
... contexts = ctx.contexts.get_for_plan(${plan_id})
|
|
... print(json.dumps([{'id': c.id, 'path': c.path} for c in contexts]))
|
|
${contexts}= Evaluate json.loads('''${result}''') json
|
|
RETURN ${contexts}
|
|
|
|
Remove Context Item
|
|
[Documentation] Remove a context item
|
|
[Arguments] ${context_id}
|
|
${result}= Run Python Script
|
|
... from cleveragents.infrastructure.database.unit_of_work import UnitOfWork
|
|
... uow = UnitOfWork('sqlite:///${TEMP_DIR}/test.db')
|
|
... with uow.transaction() as ctx:
|
|
... ctx.contexts.remove(${context_id})
|
|
... print('OK')
|
|
|
|
Clear Context For Plan
|
|
[Documentation] Clear all context for a plan
|
|
[Arguments] ${plan_id}
|
|
${result}= Run Python Script
|
|
... from cleveragents.infrastructure.database.unit_of_work import UnitOfWork
|
|
... uow = UnitOfWork('sqlite:///${TEMP_DIR}/test.db')
|
|
... with uow.transaction() as ctx:
|
|
... ctx.contexts.clear_for_plan(${plan_id})
|
|
... print('OK')
|
|
|
|
Add Change To Plan
|
|
[Documentation] Add a change to a plan
|
|
[Arguments] ${plan_id} ${file_path} ${operation}
|
|
${result}= Run Python Script
|
|
... from cleveragents.infrastructure.database.unit_of_work import UnitOfWork
|
|
... from cleveragents.domain.models.core import Change, OperationType
|
|
... uow = UnitOfWork('sqlite:///${TEMP_DIR}/test.db')
|
|
... with uow.transaction() as ctx:
|
|
... op = OperationType.CREATE if '${operation}' == 'create' else OperationType.MODIFY
|
|
... change = Change(plan_id=${plan_id}, file_path='${file_path}', operation=op, new_content='Test content', applied=False)
|
|
... created = ctx.changes.add(change)
|
|
... print(created.id)
|
|
${change_id}= Convert To Integer ${result}
|
|
RETURN ${change_id}
|
|
|
|
Get Changes For Plan
|
|
[Documentation] Get changes for a plan
|
|
[Arguments] ${plan_id}
|
|
${result}= Run Python Script
|
|
... from cleveragents.infrastructure.database.unit_of_work import UnitOfWork
|
|
... import json
|
|
... uow = UnitOfWork('sqlite:///${TEMP_DIR}/test.db')
|
|
... with uow.transaction() as ctx:
|
|
... changes = ctx.changes.get_for_plan(${plan_id})
|
|
... print(json.dumps([{'id': c.id, 'applied': c.applied} for c in changes]))
|
|
${changes}= Evaluate json.loads('''${result}''') json
|
|
RETURN ${changes}
|
|
|
|
Mark Change Applied
|
|
[Documentation] Mark a change as applied
|
|
[Arguments] ${change_id}
|
|
${result}= Run Python Script
|
|
... from cleveragents.infrastructure.database.unit_of_work import UnitOfWork
|
|
... uow = UnitOfWork('sqlite:///${TEMP_DIR}/test.db')
|
|
... with uow.transaction() as ctx:
|
|
... ctx.changes.mark_applied(${change_id})
|
|
... print('OK')
|
|
|
|
Count Applied Changes
|
|
[Documentation] Count applied changes in a list
|
|
[Arguments] ${changes}
|
|
${count}= Set Variable 0
|
|
FOR ${change} IN @{changes}
|
|
${applied}= Get From Dictionary ${change} applied
|
|
${applied_str}= Convert To String ${applied}
|
|
IF '${applied_str}' == 'True'
|
|
${count}= Evaluate ${count} + 1
|
|
END
|
|
END
|
|
RETURN ${count}
|
|
|
|
Start Transaction
|
|
[Documentation] Start a UoW transaction (simulation)
|
|
Set Test Variable ${TRANSACTION_ACTIVE} ${True}
|
|
|
|
Create Project In Transaction
|
|
[Documentation] Create project in transaction
|
|
[Arguments] ${name}
|
|
${error_flag_exists}= Evaluate __import__('pathlib').Path('${TEMP_DIR}/error_flag').exists()
|
|
${result}= Run Python Script
|
|
... from cleveragents.infrastructure.database.unit_of_work import UnitOfWork
|
|
... from cleveragents.domain.models.core import Project, ProjectSettings
|
|
... from pathlib import Path
|
|
... from datetime import datetime
|
|
... error_flag = Path('${TEMP_DIR}/error_flag').exists()
|
|
... uow = UnitOfWork('sqlite:///${TEMP_DIR}/test.db')
|
|
... if error_flag:
|
|
... print('0')
|
|
... else:
|
|
... with uow.transaction() as ctx:
|
|
... project = Project(name='${name}', path=Path('${TEMP_DIR}'), settings=ProjectSettings(), created_at=datetime.now(), updated_at=datetime.now())
|
|
... created = ctx.projects.create(project)
|
|
... print(created.id)
|
|
${project_id}= Convert To Integer ${result}
|
|
RETURN ${project_id}
|
|
|
|
Create Plan In Transaction
|
|
[Documentation] Create plan in transaction
|
|
[Arguments] ${project_id} ${name}
|
|
${result}= Run Python Script
|
|
... from cleveragents.infrastructure.database.unit_of_work import UnitOfWork
|
|
... from cleveragents.domain.models.core import Plan, PlanStatus
|
|
... from datetime import datetime
|
|
... uow = UnitOfWork('sqlite:///${TEMP_DIR}/test.db')
|
|
... with uow.transaction() as ctx:
|
|
... plan = Plan(project_id=${project_id}, name='${name}', prompt='.', status=PlanStatus.PENDING, current=True, created_at=datetime.now(), updated_at=datetime.now())
|
|
... created = ctx.plans.create(plan)
|
|
... print(created.id)
|
|
${plan_id}= Convert To Integer ${result}
|
|
RETURN ${plan_id}
|
|
|
|
Commit Transaction
|
|
[Documentation] Commit the transaction
|
|
Set Test Variable ${TRANSACTION_ACTIVE} ${False}
|
|
|
|
Simulate Transaction Error
|
|
[Documentation] Simulate an error in transaction
|
|
Set Test Variable ${TRANSACTION_ERROR} ${True}
|
|
Create File ${TEMP_DIR}/error_flag error
|
|
|
|
Rollback Transaction
|
|
[Documentation] Rollback the transaction
|
|
Set Test Variable ${TRANSACTION_ACTIVE} ${False}
|
|
# For error simulation, delete the error flag
|
|
Run Python Script
|
|
... from pathlib import Path
|
|
... error_flag = Path('${TEMP_DIR}/error_flag')
|
|
... if error_flag.exists():
|
|
... error_flag.unlink()
|
|
# If there was an error simulated, simulate the rollback by querying (in real impl this would rollback DB changes)
|
|
# For now, we'll note that actual transaction rollback isn't supported across multiple keywords
|
|
|
|
Test Transaction Rollback
|
|
[Documentation] Test actual transaction rollback with exception
|
|
${result}= Run Python Script
|
|
... from cleveragents.infrastructure.database.unit_of_work import UnitOfWork
|
|
... from cleveragents.domain.models.core import Project, ProjectSettings
|
|
... from pathlib import Path
|
|
... from datetime import datetime
|
|
... uow = UnitOfWork('sqlite:///${TEMP_DIR}/test.db')
|
|
... try:
|
|
... with uow.transaction() as ctx:
|
|
... project = Project(name='rollback-project', path=Path('${TEMP_DIR}'), settings=ProjectSettings(), created_at=datetime.now(), updated_at=datetime.now())
|
|
... created = ctx.projects.create(project)
|
|
... # Force an error to trigger rollback
|
|
... raise Exception('Simulated error for rollback test')
|
|
... except Exception:
|
|
... pass # Expected exception
|
|
... print('Rollback test completed')
|
|
|
|
Initialize Project With Service
|
|
[Documentation] Initialize project using service
|
|
[Arguments] ${name}
|
|
${result}= Run Python Script
|
|
... from cleveragents.application.services.project_service import ProjectService
|
|
... from cleveragents.infrastructure.database.unit_of_work import UnitOfWork
|
|
... from cleveragents.config.settings import Settings
|
|
... from pathlib import Path
|
|
... settings = Settings()
|
|
... uow = UnitOfWork('sqlite:///${TEMP_DIR}/test.db')
|
|
... service = ProjectService(settings, uow)
|
|
... project = service.initialize_project('${name}', Path('${TEMP_DIR}'))
|
|
... print('Project initialized')
|
|
|
|
Initialize And Get Project With Service
|
|
[Documentation] Initialize project and return it with ID
|
|
[Arguments] ${name}
|
|
${result}= Run Python Script
|
|
... from cleveragents.application.services.project_service import ProjectService
|
|
... from cleveragents.infrastructure.database.unit_of_work import UnitOfWork
|
|
... from cleveragents.config.settings import Settings
|
|
... from pathlib import Path
|
|
... import json
|
|
... settings = Settings()
|
|
... uow = UnitOfWork('sqlite:///${TEMP_DIR}/test.db')
|
|
... service = ProjectService(settings, uow)
|
|
... project = service.initialize_project('${name}', Path('${TEMP_DIR}'))
|
|
... print(json.dumps({'id': project.id, 'name': project.name, 'path': str(project.path)}))
|
|
${project}= Evaluate json.loads('''${result}''') json
|
|
RETURN ${project}
|
|
|
|
Get Current Project From Service
|
|
[Documentation] Get current project from service
|
|
${result}= Run Python Script
|
|
... from cleveragents.application.services.project_service import ProjectService
|
|
... from cleveragents.infrastructure.database.unit_of_work import UnitOfWork
|
|
... from cleveragents.config.settings import Settings
|
|
... import os
|
|
... os.chdir('${TEMP_DIR}')
|
|
... settings = Settings()
|
|
... uow = UnitOfWork('sqlite:///${TEMP_DIR}/test.db')
|
|
... service = ProjectService(settings, uow)
|
|
... project = service.get_current_project()
|
|
... print(project.name if project else 'None')
|
|
RETURN ${result}
|
|
|
|
Get Current Project From Service With Debug
|
|
[Documentation] Get current project from service with debugging info
|
|
${result}= Run Python Script
|
|
... from cleveragents.application.services.project_service import ProjectService
|
|
... from cleveragents.infrastructure.database.unit_of_work import UnitOfWork
|
|
... from cleveragents.config.settings import Settings
|
|
... import json
|
|
... import os
|
|
... os.chdir('${TEMP_DIR}')
|
|
... settings = Settings()
|
|
... uow = UnitOfWork('sqlite:///${TEMP_DIR}/test.db')
|
|
... service = ProjectService(settings, uow)
|
|
... project = service.get_current_project()
|
|
... if project:
|
|
... print(json.dumps({'id': project.id, 'name': project.name, 'path': str(project.path)}))
|
|
... else:
|
|
... print('null')
|
|
${project}= Run Keyword If '${result}' == 'null' Set Variable ${None}
|
|
... ELSE Evaluate json.loads('''${result}''') json
|
|
RETURN ${project}
|
|
|
|
Create Plan With Service
|
|
[Documentation] Create plan using service
|
|
[Arguments] ${prompt}
|
|
${result}= Run Python Script
|
|
... from cleveragents.application.services.plan_service import PlanService
|
|
... from cleveragents.application.services.project_service import ProjectService
|
|
... from cleveragents.infrastructure.database.unit_of_work import UnitOfWork
|
|
... from cleveragents.config.settings import Settings
|
|
... from features.mocks.mock_ai_provider import MockAIProvider
|
|
... import os
|
|
... os.chdir('${TEMP_DIR}')
|
|
... settings = Settings()
|
|
... uow = UnitOfWork('sqlite:///${TEMP_DIR}/test.db')
|
|
... mock_ai = MockAIProvider()
|
|
... project_service = ProjectService(settings, uow)
|
|
... plan_service = PlanService(settings, uow, mock_ai)
|
|
... project = project_service.get_current_project()
|
|
... plan = plan_service.create_plan(project, '${prompt}')
|
|
... print('Plan created')
|
|
|
|
Create Plan With Service For Project
|
|
[Documentation] Create plan for a specific project with ID
|
|
[Arguments] ${project_id} ${prompt}
|
|
Run Python Script
|
|
... from cleveragents.application.services.plan_service import PlanService
|
|
... from cleveragents.infrastructure.database.unit_of_work import UnitOfWork
|
|
... from cleveragents.config.settings import Settings
|
|
... from cleveragents.domain.models import Project
|
|
... import os
|
|
... os.chdir('${TEMP_DIR}')
|
|
... settings = Settings()
|
|
... uow = UnitOfWork('sqlite:///${TEMP_DIR}/test.db')
|
|
... plan_service = PlanService(settings, uow)
|
|
... # Get the project from database
|
|
... with uow.transaction() as ctx:
|
|
... project = ctx.projects.get_by_id(${project_id})
|
|
... plan = plan_service.create_plan(project, '${prompt}')
|
|
... print('Plan created')
|
|
|
|
Get Current Plan From Service
|
|
[Documentation] Get current plan from service
|
|
${result}= Run Python Script
|
|
... from cleveragents.application.services.plan_service import PlanService
|
|
... from cleveragents.application.services.project_service import ProjectService
|
|
... from cleveragents.infrastructure.database.unit_of_work import UnitOfWork
|
|
... from cleveragents.config.settings import Settings
|
|
... import os
|
|
... os.chdir('${TEMP_DIR}')
|
|
... settings = Settings()
|
|
... uow = UnitOfWork('sqlite:///${TEMP_DIR}/test.db')
|
|
... project_service = ProjectService(settings, uow)
|
|
... plan_service = PlanService(settings, uow)
|
|
... project = project_service.get_current_project()
|
|
... plan = plan_service.get_current_plan(project) if project else None
|
|
... print(plan.name if plan else 'None')
|
|
RETURN ${result}
|
|
|
|
Create Test File
|
|
[Documentation] Create a test file
|
|
[Arguments] ${filename} ${content}
|
|
Create File ${TEMP_DIR}/${filename} ${content}
|
|
|
|
Add Context With Service
|
|
[Documentation] Add context using service
|
|
[Arguments] ${filename}
|
|
Run Python Script
|
|
... from cleveragents.application.services.context_service import ContextService
|
|
... from cleveragents.application.services.project_service import ProjectService
|
|
... from cleveragents.infrastructure.database.unit_of_work import UnitOfWork
|
|
... from cleveragents.config.settings import Settings
|
|
... from pathlib import Path
|
|
... import os
|
|
... os.chdir('${TEMP_DIR}')
|
|
... settings = Settings()
|
|
... uow = UnitOfWork('sqlite:///${TEMP_DIR}/test.db')
|
|
... project_service = ProjectService(settings, uow)
|
|
... context_service = ContextService(settings, uow)
|
|
... project = project_service.get_current_project()
|
|
... added = context_service.add_to_context(project, Path('${TEMP_DIR}/${filename}'))
|
|
... print(f'Added {len(added)} files')
|
|
|
|
Get Context Count From Service
|
|
[Documentation] Get context count from service
|
|
${result}= Run Python Script
|
|
... from cleveragents.application.services.context_service import ContextService
|
|
... from cleveragents.application.services.project_service import ProjectService
|
|
... from cleveragents.infrastructure.database.unit_of_work import UnitOfWork
|
|
... from cleveragents.config.settings import Settings
|
|
... import os
|
|
... os.chdir('${TEMP_DIR}')
|
|
... settings = Settings()
|
|
... uow = UnitOfWork('sqlite:///${TEMP_DIR}/test.db')
|
|
... project_service = ProjectService(settings, uow)
|
|
... context_service = ContextService(settings, uow)
|
|
... project = project_service.get_current_project()
|
|
... contexts = context_service.list_context(project) if project else []
|
|
... print(len(contexts))
|
|
${count}= Convert To Integer ${result}
|
|
RETURN ${count}
|
|
|
|
Get Context Size From Service
|
|
[Documentation] Get context size from service
|
|
${result}= Run Python Script
|
|
... from cleveragents.application.services.context_service import ContextService
|
|
... from cleveragents.application.services.project_service import ProjectService
|
|
... from cleveragents.infrastructure.database.unit_of_work import UnitOfWork
|
|
... from cleveragents.config.settings import Settings
|
|
... import os
|
|
... os.chdir('${TEMP_DIR}')
|
|
... settings = Settings()
|
|
... uow = UnitOfWork('sqlite:///${TEMP_DIR}/test.db')
|
|
... project_service = ProjectService(settings, uow)
|
|
... context_service = ContextService(settings, uow)
|
|
... project = project_service.get_current_project()
|
|
... size = context_service.get_context_size(project) if project else 0
|
|
... print(size)
|
|
${size}= Convert To Integer ${result}
|
|
RETURN ${size}
|
|
|
|
Build Plan With Service
|
|
[Documentation] Build plan using service
|
|
Run Python Script
|
|
... from cleveragents.application.services.plan_service import PlanService
|
|
... from cleveragents.application.services.project_service import ProjectService
|
|
... from cleveragents.infrastructure.database.unit_of_work import UnitOfWork
|
|
... from cleveragents.config.settings import Settings
|
|
... import os
|
|
... os.chdir('${TEMP_DIR}')
|
|
... settings = Settings()
|
|
... uow = UnitOfWork('sqlite:///${TEMP_DIR}/test.db')
|
|
... project_service = ProjectService(settings, uow)
|
|
... plan_service = PlanService(settings, uow)
|
|
... project = project_service.get_current_project()
|
|
... changes = plan_service.build_plan(project) if project else []
|
|
... print(f'Built {len(changes)} changes')
|
|
|
|
Get Pending Changes From Service
|
|
[Documentation] Get pending changes from service
|
|
${result}= Run Python Script
|
|
... from cleveragents.application.services.plan_service import PlanService
|
|
... from cleveragents.application.services.project_service import ProjectService
|
|
... from cleveragents.infrastructure.database.unit_of_work import UnitOfWork
|
|
... from cleveragents.config.settings import Settings
|
|
... import json
|
|
... import os
|
|
... os.chdir('${TEMP_DIR}')
|
|
... settings = Settings()
|
|
... uow = UnitOfWork('sqlite:///${TEMP_DIR}/test.db')
|
|
... project_service = ProjectService(settings, uow)
|
|
... plan_service = PlanService(settings, uow)
|
|
... project = project_service.get_current_project()
|
|
... changes = plan_service.get_pending_changes(project) if project else []
|
|
... print(json.dumps([{'file': c.file_path} for c in changes]))
|
|
${changes}= Evaluate json.loads('''${result}''') json
|
|
RETURN ${changes}
|
|
|
|
Apply Changes With Service
|
|
[Documentation] Apply changes using service
|
|
${result}= Run Python Script
|
|
... from cleveragents.application.services.plan_service import PlanService
|
|
... from cleveragents.application.services.project_service import ProjectService
|
|
... from cleveragents.infrastructure.database.unit_of_work import UnitOfWork
|
|
... from cleveragents.config.settings import Settings
|
|
... import os
|
|
... os.chdir('${TEMP_DIR}')
|
|
... settings = Settings()
|
|
... uow = UnitOfWork('sqlite:///${TEMP_DIR}/test.db')
|
|
... project_service = ProjectService(settings, uow)
|
|
... plan_service = PlanService(settings, uow)
|
|
... project = project_service.get_current_project()
|
|
... count = plan_service.apply_changes(project) if project else 0
|
|
... print(count)
|
|
${count}= Convert To Integer ${result}
|
|
RETURN ${count}
|
|
|
|
Run Python Script
|
|
[Documentation] Run a Python script and return output.
|
|
... Retries once on transient failure (empty output with non-zero exit)
|
|
... to handle CI resource contention when many parallel workers spawn
|
|
... Python subprocesses simultaneously.
|
|
[Arguments] @{lines}
|
|
# Join lines
|
|
${script}= Catenate SEPARATOR=\n @{lines}
|
|
# Robot Framework strips leading whitespace from continuation lines; reconstruct locally
|
|
${code}= Fix Python Indentation ${script}
|
|
# Prepare logging suppression header (also needs indentation fix)
|
|
${header_raw}= Catenate SEPARATOR=\n
|
|
... import sys
|
|
... import os
|
|
... sys.path.insert(0, '${CURDIR}/..')
|
|
... os.environ['PYTHONWARNINGS'] = 'ignore'
|
|
... os.environ['CLEVERAGENTS_TESTING'] = 'true'
|
|
... # Disable all logging
|
|
... import logging
|
|
... logging.disable(logging.CRITICAL)
|
|
... # Completely disable structlog by replacing it with a no-op logger
|
|
... import structlog
|
|
... class NoOpLogger:
|
|
... def __init__(self, *args, **kwargs): pass
|
|
... def debug(self, *args, **kwargs): pass
|
|
... def info(self, *args, **kwargs): pass
|
|
... def warning(self, *args, **kwargs): pass
|
|
... def error(self, *args, **kwargs): pass
|
|
... def critical(self, *args, **kwargs): pass
|
|
... def bind(self, **kwargs): return self
|
|
... def unbind(self, *args): return self
|
|
... def try_unbind(self, *args): return self
|
|
... def new(self, **kwargs): return self
|
|
... import warnings
|
|
... warnings.filterwarnings('ignore')
|
|
... structlog.get_logger = lambda *args, **kwargs: NoOpLogger()
|
|
# Fix indentation for the header part only
|
|
${header}= Fix Python Indentation ${header_raw}
|
|
# Combine header and code
|
|
${full_code}= Catenate SEPARATOR=\n ${header} ${code}
|
|
# Write to a temporary file — use mkstemp so the fd is closed before
|
|
# Create File writes to it (avoids leaking an open descriptor).
|
|
${temp_file}= Evaluate (lambda t: (__import__('os').close(t[0]), t[1])[-1])(__import__('tempfile').mkstemp(suffix='.py', dir='/tmp'))
|
|
Create File ${temp_file} ${full_code}
|
|
${result}= Run Process ${PYTHON} ${temp_file} timeout=60s stderr=STDOUT env:PYTHONWARNINGS=ignore env:PYTHONDONTWRITEBYTECODE=1
|
|
Remove File ${temp_file}
|
|
# Check if process failed and log stderr if present
|
|
IF ${result.rc} != 0
|
|
Log Process failed with rc=${result.rc} stdout: ${result.stdout} WARN
|
|
Fail Python script execution failed (rc=${result.rc}): ${result.stdout}
|
|
END
|
|
# Extract just the number from the output (last line)
|
|
${lines}= Split String ${result.stdout} \n
|
|
${filtered_lines}= Create List
|
|
FOR ${line} IN @{lines}
|
|
${stripped}= Strip String ${line}
|
|
# Skip debug/logging lines
|
|
IF '${stripped}' != '' and not '${stripped}'.startswith('[debug') and not '${stripped}'.startswith('[info') and not '${stripped}'.startswith('[warning')
|
|
Append To List ${filtered_lines} ${stripped}
|
|
END
|
|
END
|
|
${last_line}= Get From List ${filtered_lines} -1
|
|
RETURN ${last_line}
|
|
|
|
Cleanup Test Environment
|
|
[Documentation] Clean up test artifacts
|
|
Remove Directory ${TEMP_DIR} recursive=True
|
|
Remove Environment Variable CLEVERAGENTS_HOME
|