diff --git a/aios_core/kernel/__init__.py b/aios_core/kernel/__init__.py new file mode 100644 index 000000000..8e14daf36 --- /dev/null +++ b/aios_core/kernel/__init__.py @@ -0,0 +1,6 @@ +"""AIOS v20 Kernel foundation.""" + +from .identity import AgentIdentity +from .audit import AuditLogger + +__all__ = ["AgentIdentity", "AuditLogger"] diff --git a/aios_core/kernel/audit.py b/aios_core/kernel/audit.py new file mode 100644 index 000000000..a8c2896f0 --- /dev/null +++ b/aios_core/kernel/audit.py @@ -0,0 +1,15 @@ +from datetime import datetime + + +class AuditLogger: + """Minimal audit event storage for AIOS v20 kernel.""" + + def __init__(self): + self.events = [] + + def record(self, event: dict): + event["timestamp"] = datetime.utcnow().isoformat() + self.events.append(event) + + def get_events(self): + return self.events diff --git a/aios_core/kernel/context.py b/aios_core/kernel/context.py new file mode 100644 index 000000000..a885a4edf --- /dev/null +++ b/aios_core/kernel/context.py @@ -0,0 +1,9 @@ +from dataclasses import dataclass +from typing import Any + + +@dataclass +class ExecutionContext: + agent_id: str + action: str + metadata: dict[str, Any] | None = None diff --git a/aios_core/kernel/decisions.py b/aios_core/kernel/decisions.py new file mode 100644 index 000000000..52561f70a --- /dev/null +++ b/aios_core/kernel/decisions.py @@ -0,0 +1,7 @@ +from dataclasses import dataclass + + +@dataclass +class PolicyDecision: + allowed: bool + reason: str diff --git a/aios_core/kernel/exceptions.py b/aios_core/kernel/exceptions.py new file mode 100644 index 000000000..dbca5faf1 --- /dev/null +++ b/aios_core/kernel/exceptions.py @@ -0,0 +1,6 @@ +class KernelError(Exception): + pass + + +class PermissionDenied(KernelError): + pass diff --git a/aios_core/kernel/identity.py b/aios_core/kernel/identity.py new file mode 100644 index 000000000..f6841f283 --- /dev/null +++ b/aios_core/kernel/identity.py @@ -0,0 +1,10 @@ +class AgentIdentity: + """Identity model for AIOS agents.""" + + def __init__(self, agent_id: str, role: str, capabilities=None): + self.agent_id = agent_id + self.role = role + self.capabilities = capabilities or [] + + def has_capability(self, capability: str) -> bool: + return capability in self.capabilities diff --git a/aios_core/kernel/kernel.py b/aios_core/kernel/kernel.py new file mode 100644 index 000000000..f69e39e06 --- /dev/null +++ b/aios_core/kernel/kernel.py @@ -0,0 +1,16 @@ +from .decisions import PolicyDecision + + +class Kernel: + def __init__(self, identity, trust, policy, audit): + self.identity = identity + self.trust = trust + self.policy = policy + self.audit = audit + + def process(self, context): + self.identity.validate(context.agent_id) + trust = self.trust.evaluate(context.agent_id) + decision = self.policy.evaluate(context, trust) + self.audit.record(decision) + return decision diff --git a/aios_core/kernel/policies.py b/aios_core/kernel/policies.py new file mode 100644 index 000000000..4ea548396 --- /dev/null +++ b/aios_core/kernel/policies.py @@ -0,0 +1,24 @@ +"""AIOS v20 policy engine foundation.""" + +from dataclasses import dataclass + + +@dataclass +class PolicyDecision: + allowed: bool + reason: str + + +class PolicyEngine: + def __init__(self): + self.rules = {} + + def allow(self, capability: str) -> None: + self.rules[capability] = True + + def evaluate(self, capability: str) -> PolicyDecision: + allowed = self.rules.get(capability, False) + return PolicyDecision( + allowed=allowed, + reason="allowed" if allowed else "missing_capability", + ) diff --git a/aios_core/kernel/trust.py b/aios_core/kernel/trust.py new file mode 100644 index 000000000..d23f31e84 --- /dev/null +++ b/aios_core/kernel/trust.py @@ -0,0 +1,15 @@ +"""AIOS v20 trust management foundation.""" + + +class TrustManager: + def __init__(self): + self._trust = {} + + def evaluate(self, agent_id: str) -> str: + return self._trust.get(agent_id, "T0") + + def grant(self, agent_id: str, level: str = "T1") -> None: + self._trust[agent_id] = level + + def revoke(self, agent_id: str) -> None: + self._trust[agent_id] = "T0" diff --git a/aios_core/runtime/__init__.py b/aios_core/runtime/__init__.py new file mode 100644 index 000000000..0aa0f7801 --- /dev/null +++ b/aios_core/runtime/__init__.py @@ -0,0 +1,5 @@ +"""AIOS v20 runtime layer.""" + +from .lifecycle import AgentState, LifecycleManager + +__all__ = ["AgentState", "LifecycleManager"] diff --git a/aios_core/runtime/budgets.py b/aios_core/runtime/budgets.py new file mode 100644 index 000000000..dc75ca769 --- /dev/null +++ b/aios_core/runtime/budgets.py @@ -0,0 +1,11 @@ +class AgentBudget: + def __init__(self, max_actions=100, max_runtime=3600): + self.max_actions = max_actions + self.max_runtime = max_runtime + self.actions_used = 0 + + def can_execute(self): + return self.actions_used < self.max_actions + + def consume(self): + self.actions_used += 1 diff --git a/aios_core/runtime/heartbeat.py b/aios_core/runtime/heartbeat.py new file mode 100644 index 000000000..2dd9fc189 --- /dev/null +++ b/aios_core/runtime/heartbeat.py @@ -0,0 +1,12 @@ +from datetime import datetime + + +class HeartbeatManager: + def __init__(self): + self.timestamps = {} + + def ping(self, agent_id): + self.timestamps[agent_id] = datetime.utcnow() + + def alive(self, agent_id): + return agent_id in self.timestamps diff --git a/aios_core/runtime/lifecycle.py b/aios_core/runtime/lifecycle.py new file mode 100644 index 000000000..2c45eeb6c --- /dev/null +++ b/aios_core/runtime/lifecycle.py @@ -0,0 +1,26 @@ +from enum import Enum + + +class AgentState(Enum): + CREATED = "created" + READY = "ready" + RUNNING = "running" + STOPPED = "stopped" + FAILED = "failed" + + +class LifecycleManager: + def __init__(self): + self.states = {} + + def register(self, agent_id): + self.states[agent_id] = AgentState.CREATED + + def start(self, agent_id): + self.states[agent_id] = AgentState.RUNNING + + def stop(self, agent_id): + self.states[agent_id] = AgentState.STOPPED + + def fail(self, agent_id): + self.states[agent_id] = AgentState.FAILED diff --git a/tests/kernel/test_identity.py b/tests/kernel/test_identity.py new file mode 100644 index 000000000..699b63a1c --- /dev/null +++ b/tests/kernel/test_identity.py @@ -0,0 +1,6 @@ +from aios_core.kernel import AgentIdentity + + +def test_agent_capability(): + agent = AgentIdentity("agent-001", "developer", ["code"]) + assert agent.has_capability("code") diff --git a/tests/kernel/test_trust_policy.py b/tests/kernel/test_trust_policy.py new file mode 100644 index 000000000..23517cb97 --- /dev/null +++ b/tests/kernel/test_trust_policy.py @@ -0,0 +1,13 @@ +from aios_core.kernel.trust import TrustManager +from aios_core.kernel.policies import PolicyEngine + + +def test_trust_default_is_unknown(): + manager = TrustManager() + assert manager.evaluate("agent-001") == "T0" + + +def test_policy_denies_unknown_capability(): + policy = PolicyEngine() + result = policy.evaluate("execute_tool") + assert result.allowed is False