Add architecture package and application skeleton
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
from ai_orchestrator.domain.enums import NodeStatus, NodeType
|
||||
from ai_orchestrator.domain.models import ExecutionGraph, ExecutionNode
|
||||
|
||||
|
||||
def test_graph_marks_pending_node_ready_when_dependencies_are_completed() -> None:
|
||||
first = ExecutionNode(task_id="task_1", node_type=NodeType.PLANNER, input_data={})
|
||||
second = ExecutionNode(
|
||||
task_id="task_1",
|
||||
node_type=NodeType.FINALIZER,
|
||||
input_data={},
|
||||
dependencies=[first.node_id],
|
||||
)
|
||||
first.mark_completed({"ok": True})
|
||||
graph = ExecutionGraph(task_id="task_1", nodes=[first, second])
|
||||
|
||||
ready = graph.ready_nodes()
|
||||
|
||||
assert len(ready) == 1
|
||||
assert ready[0].node_id == second.node_id
|
||||
assert second.status == NodeStatus.READY
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
from ai_orchestrator.config import (
|
||||
ExecutionConfig,
|
||||
ModelsConfig,
|
||||
ModelSlotConfig,
|
||||
PolicyConfig,
|
||||
PolicyMode,
|
||||
ProjectConfig,
|
||||
ProjectMetadata,
|
||||
)
|
||||
from ai_orchestrator.domain.enums import PolicyDecisionType, RiskLevel
|
||||
from ai_orchestrator.domain.models import ActionDescriptor
|
||||
from ai_orchestrator.infrastructure.policy import StaticProjectPolicyEvaluator
|
||||
|
||||
|
||||
def test_policy_evaluator_returns_confirm_for_configured_resource() -> None:
|
||||
project = ProjectConfig(
|
||||
project=ProjectMetadata(id="default", name="Default"),
|
||||
models=ModelsConfig(
|
||||
weak=ModelSlotConfig(provider="local", model="weak"),
|
||||
strong=ModelSlotConfig(provider="local", model="strong"),
|
||||
vision=ModelSlotConfig(provider="disabled"),
|
||||
embedding=ModelSlotConfig(provider="local", model="embed"),
|
||||
),
|
||||
execution=ExecutionConfig(),
|
||||
policy=PolicyConfig(),
|
||||
)
|
||||
evaluator = StaticProjectPolicyEvaluator(projects={"default": project})
|
||||
|
||||
decision = evaluator.evaluate(
|
||||
ActionDescriptor(
|
||||
resource="filesystem",
|
||||
risk_level=RiskLevel.WRITE,
|
||||
action_name="file.write",
|
||||
preview_available=True,
|
||||
),
|
||||
"default",
|
||||
)
|
||||
|
||||
assert decision.decision == PolicyDecisionType.CONFIRM
|
||||
assert decision.requires_confirmation is True
|
||||
|
||||
|
||||
def test_policy_evaluator_returns_disabled_by_config() -> None:
|
||||
project = ProjectConfig(
|
||||
project=ProjectMetadata(id="default", name="Default"),
|
||||
models=ModelsConfig(
|
||||
weak=ModelSlotConfig(provider="local", model="weak"),
|
||||
strong=ModelSlotConfig(provider="local", model="strong"),
|
||||
vision=ModelSlotConfig(provider="disabled"),
|
||||
embedding=ModelSlotConfig(provider="local", model="embed"),
|
||||
),
|
||||
execution=ExecutionConfig(),
|
||||
policy=PolicyConfig(
|
||||
default_mode=PolicyMode.CONFIRM,
|
||||
resources={
|
||||
"filesystem": PolicyMode.CONFIRM,
|
||||
"shell": PolicyMode.CONFIRM,
|
||||
"sql": PolicyMode.CONFIRM,
|
||||
"mcp": PolicyMode.CONFIRM,
|
||||
"external_models": PolicyMode.DISABLED,
|
||||
"desktop": PolicyMode.CONFIRM,
|
||||
"browser": PolicyMode.CONFIRM,
|
||||
"network": PolicyMode.CONFIRM,
|
||||
"cost": PolicyMode.CONFIRM,
|
||||
"system": PolicyMode.CONFIRM,
|
||||
},
|
||||
),
|
||||
)
|
||||
evaluator = StaticProjectPolicyEvaluator(projects={"default": project})
|
||||
|
||||
decision = evaluator.evaluate(
|
||||
ActionDescriptor(
|
||||
resource="external_models",
|
||||
risk_level=RiskLevel.COST,
|
||||
action_name="model.external",
|
||||
),
|
||||
"default",
|
||||
)
|
||||
|
||||
assert decision.decision == PolicyDecisionType.DISABLED_BY_CONFIG
|
||||
@@ -0,0 +1,15 @@
|
||||
from ai_orchestrator.domain.enums import TaskStatus
|
||||
from ai_orchestrator.domain.models import Task
|
||||
|
||||
|
||||
def test_task_status_transitions() -> None:
|
||||
task = Task(project_id="default", goal="Test", inputs={})
|
||||
|
||||
task.mark_planned()
|
||||
task.mark_running()
|
||||
task.wait_for_confirmation("node_1")
|
||||
task.complete({"result": "ok"})
|
||||
|
||||
assert task.status == TaskStatus.COMPLETED
|
||||
assert task.current_node_id == "node_1"
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
from ai_orchestrator.application.services.workers import RegisterWorkerRequest, WorkerService
|
||||
from ai_orchestrator.infrastructure.storage.memory import (
|
||||
InMemoryEventStore,
|
||||
InMemoryWorkerRepository,
|
||||
)
|
||||
|
||||
|
||||
def test_worker_registration_creates_online_session_and_event() -> None:
|
||||
worker_repository = InMemoryWorkerRepository()
|
||||
event_store = InMemoryEventStore()
|
||||
service = WorkerService(worker_repository=worker_repository, event_store=event_store)
|
||||
|
||||
worker = service.register(
|
||||
RegisterWorkerRequest(
|
||||
worker_id="worker_home_pc",
|
||||
name="Home PC",
|
||||
machine="DESKTOP-1",
|
||||
os="windows",
|
||||
version="0.1.0",
|
||||
capabilities=["file.read", "command.run"],
|
||||
)
|
||||
)
|
||||
|
||||
assert worker.status.value == "online"
|
||||
assert worker_repository.get(worker.session_id) is not None
|
||||
assert event_store.items[-1].event_type == "worker_registered"
|
||||
Reference in New Issue
Block a user