Compare commits
13
Commits
d0e5a45166
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
04f265767e | ||
|
|
0192b1dba5 | ||
|
|
35df7d7522 | ||
|
|
5c69676bcf | ||
|
|
57619860d5 | ||
|
|
38bb291a02 | ||
|
|
c370dbf158 | ||
|
|
9ff9f20e1c | ||
|
|
c98a05f202 | ||
|
|
fcde8a3d63 | ||
|
|
8d373c07c2 | ||
|
|
0cd6c1e8d6 | ||
|
|
385b731556 |
+20
@@ -0,0 +1,20 @@
|
|||||||
|
# Python
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
*.pyo
|
||||||
|
*.pyd
|
||||||
|
*.pyz
|
||||||
|
.pytest_cache/
|
||||||
|
.venv/
|
||||||
|
*.egg-info/
|
||||||
|
dist/
|
||||||
|
build/
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
|
||||||
|
# Nix
|
||||||
|
result/
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
# Woodpecker CI pipeline for DCOS
|
||||||
|
# Integrates with stonks-ci (stonks-oracle's CI/CD at stonks-ci.celestium.life)
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: lint-and-test
|
||||||
|
image: python:3.12-slim
|
||||||
|
commands:
|
||||||
|
- pip install --break-system-packages ruff pytest pyyaml pydantic
|
||||||
|
- ruff check src/dcos/
|
||||||
|
- PYTHONPATH=src:$PYTHONPATH pytest tests/ -x --tb=short -q
|
||||||
|
when:
|
||||||
|
event: push
|
||||||
|
|
||||||
|
- name: build-and-push-image
|
||||||
|
image: plugins/docker
|
||||||
|
privileged: true
|
||||||
|
commands:
|
||||||
|
- docker login ghcr.io -u "$(cat /run/secrets/GITHUB_TOKEN)" -p "$(cat /run/secrets/GHCR_TOKEN)"
|
||||||
|
- docker build -f docker/Dockerfile.dcos -t ghcr.io/celesrenata/dcos:${CI_COMMIT_SHA} .
|
||||||
|
- docker push ghcr.io/celesrenata/dcos:${CI_COMMIT_SHA}
|
||||||
|
- docker tag ghcr.io/celesrenata/dcos:${CI_COMMIT_SHA} ghcr.io/celesrenata/dcos:latest
|
||||||
|
- docker push ghcr.io/celesrenata/dcos:latest
|
||||||
|
when:
|
||||||
|
event: push
|
||||||
|
|
||||||
|
- name: deploy-to-k8s
|
||||||
|
image: bitnami/kubectl:latest
|
||||||
|
commands:
|
||||||
|
- bash ~/sources/kube/dcos/runmefirst.sh
|
||||||
|
when:
|
||||||
|
event: push
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
FROM python:3.12-slim
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Install system dependencies
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
curl \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Copy project and install
|
||||||
|
COPY . .
|
||||||
|
RUN pip install --break-system-packages .
|
||||||
|
|
||||||
|
# Entry point
|
||||||
|
ENTRYPOINT ["dcos"]
|
||||||
|
CMD ["--help"]
|
||||||
Generated
+61
@@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"flake-utils": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1731533236,
|
||||||
|
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1784796856,
|
||||||
|
"narHash": "sha256-wWFrV5/Qbm+lyt5x20E/bSbfJiGKMo4RCxZV8cl/WZI=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "e2587caef70cea85dd97d7daab492899902dbf5d",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-utils": "flake-utils",
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
@@ -10,25 +10,33 @@
|
|||||||
flake-utils.lib.eachDefaultSystem (system:
|
flake-utils.lib.eachDefaultSystem (system:
|
||||||
let
|
let
|
||||||
pkgs = nixpkgs.legacyPackages.${system};
|
pkgs = nixpkgs.legacyPackages.${system};
|
||||||
python = pkgs.python311;
|
python = pkgs.python312;
|
||||||
pythonPackages = pkgs.python311Packages;
|
pythonPackages = pkgs.python312Packages;
|
||||||
in {
|
in {
|
||||||
packages.default = pythonPackages.buildPythonPackage {
|
packages.default = pythonPackages.buildPythonPackage {
|
||||||
pname = "dcos";
|
pname = "dcos";
|
||||||
version = "1.0.0";
|
version = "1.0.0";
|
||||||
src = ./.;
|
src = ./.;
|
||||||
nativeBuildInputs = with pkgs; [
|
nativeBuildInputs = with pythonPackages; [
|
||||||
python
|
python
|
||||||
pyyaml
|
setuptools
|
||||||
|
wheel
|
||||||
|
pytest
|
||||||
|
pytest-asyncio
|
||||||
];
|
];
|
||||||
propagatedBuildInputs = with pythonPackages; [
|
propagatedBuildInputs = with pythonPackages; [
|
||||||
pyyaml
|
pyyaml
|
||||||
|
pydantic
|
||||||
];
|
];
|
||||||
doCheck = false;
|
doCheck = true;
|
||||||
format = "pyproject";
|
checkPhase = ''
|
||||||
|
export PYTHONPATH="${toString ./src}:$PYTHONPATH"
|
||||||
|
python -m pytest tests/ -x --tb=short -q
|
||||||
|
'';
|
||||||
pyproject = true;
|
pyproject = true;
|
||||||
pyprojectFiles = [ "pyproject.toml" ];
|
pyprojectFiles = [ "pyproject.toml" ];
|
||||||
makeWheel = true;
|
makeWheel = true;
|
||||||
|
packageDir = "src";
|
||||||
};
|
};
|
||||||
|
|
||||||
devShells.default = pkgs.mkShell {
|
devShells.default = pkgs.mkShell {
|
||||||
@@ -38,10 +46,12 @@
|
|||||||
pythonPackages.pytest
|
pythonPackages.pytest
|
||||||
pythonPackages.pytest-asyncio
|
pythonPackages.pytest-asyncio
|
||||||
pythonPackages.pyyaml
|
pythonPackages.pyyaml
|
||||||
|
pythonPackages.pydantic
|
||||||
|
pythonPackages.ruff
|
||||||
];
|
];
|
||||||
shellHook = ''
|
shellHook = ''
|
||||||
export PYTHONPATH="${toString (builtins.toPath ./src)}:$PYTHONPATH"
|
export PYTHONPATH="${toString ./src}:$PYTHONPATH"
|
||||||
echo "DCOS dev shell — Python 3.11, pytest, pyyaml"
|
echo "DCOS dev shell — Python 3.12, pytest, pyyaml, pydantic"
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
[build-system]
|
||||||
|
requires = ["setuptools>=64", "wheel"]
|
||||||
|
build-backend = "setuptools.build_meta"
|
||||||
|
|
||||||
|
[project]
|
||||||
|
name = "dcos"
|
||||||
|
version = "1.0.0"
|
||||||
|
description = "Distributed Cognitive Operating System — multi-agent cognitive architecture"
|
||||||
|
readme = "README.md"
|
||||||
|
requires-python = ">=3.11"
|
||||||
|
dependencies = [
|
||||||
|
"pyyaml>=6.0",
|
||||||
|
"pydantic>=2.0",
|
||||||
|
]
|
||||||
|
[project.optional-dependencies]
|
||||||
|
dev = [
|
||||||
|
"pytest>=7.0",
|
||||||
|
"pytest-asyncio>=0.21",
|
||||||
|
"pytest-cov>=4.0",
|
||||||
|
"ruff>=0.1",
|
||||||
|
]
|
||||||
|
|
||||||
|
[project.scripts]
|
||||||
|
dcos = "dcos.utils.cli:main"
|
||||||
|
|
||||||
|
[tool.setuptools.packages.find]
|
||||||
|
where = ["src"]
|
||||||
|
|
||||||
|
[tool.ruff]
|
||||||
|
line-length = 100
|
||||||
|
target-version = "py311"
|
||||||
|
|
||||||
|
[tool.ruff.lint]
|
||||||
|
select = ["E", "F", "W", "I"]
|
||||||
|
|
||||||
|
[tool.pytest.ini_options]
|
||||||
|
testpaths = ["tests"]
|
||||||
|
pythonpath = ["src"]
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
"""
|
||||||
|
DCOS — Distributed Cognitive Operating System
|
||||||
|
A multi-agent cognitive architecture for distributed intelligence.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__version__ = "1.0.0"
|
||||||
|
__author__ = "Celes Renata"
|
||||||
|
|
||||||
|
from .agents.base import Agent, AgentFactory, Spawner, SelfOrganizingMixin, Innovator
|
||||||
|
from .agents.planning import PlanningAgent
|
||||||
|
from .agents.research import ResearchAgent
|
||||||
|
from .agents.logic import LogicAgent
|
||||||
|
from .agents.creative import CreativeAgent
|
||||||
|
from .agents.ethics import EthicsAgent
|
||||||
|
from .agents.simulation import SimulationAgent
|
||||||
|
from .agents.domain import DomainExpertAgent
|
||||||
|
from .communication.protocol import CommunicationProtocol
|
||||||
|
from .communication.network import CommunicationNetwork
|
||||||
|
from .communication.router import MessageRouter
|
||||||
|
from .communication.resolver import AddressResolver
|
||||||
|
from .core.scheduler import TaskScheduler
|
||||||
|
from .core.coordinator import AgentCoordinator
|
||||||
|
from .core.registry import AgentRegistry
|
||||||
|
from .core.allocator import ResourceAllocator
|
||||||
|
from .learning.engine import LearningEngine
|
||||||
|
from .memory.working import WorkingMemory
|
||||||
|
from .memory.conversation import ConversationMemory
|
||||||
|
from .memory.long_term import LongTermMemory
|
||||||
|
from .memory.semantic import SemanticMemory
|
||||||
|
from .memory.episodic import EpisodicMemory
|
||||||
|
from .memory.procedural import ProceduralMemory
|
||||||
|
from .memory.user_model import UserModel
|
||||||
|
from .memory.world_model import WorldModel
|
||||||
|
from .memory.memory_facade import MemoryFacade
|
||||||
|
from .protocols.user_interface import UserInterface
|
||||||
|
from .protocols.external_tools import ExternalTools
|
||||||
|
from .predict import OutcomePredictor
|
||||||
|
from .risk import RiskAssessor
|
||||||
|
from .scenarios import ScenarioEngine
|
||||||
|
from .utils.config import ConfigManager
|
||||||
|
from .utils.cli import main as cli_main
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"Agent", "AgentFactory", "Spawner", "SelfOrganizingMixin", "Innovator",
|
||||||
|
"PlanningAgent", "ResearchAgent", "LogicAgent", "CreativeAgent",
|
||||||
|
"EthicsAgent", "SimulationAgent", "DomainExpertAgent",
|
||||||
|
"CommunicationProtocol", "CommunicationNetwork", "MessageRouter", "AddressResolver",
|
||||||
|
"TaskScheduler", "AgentCoordinator", "AgentRegistry", "ResourceAllocator",
|
||||||
|
"LearningEngine",
|
||||||
|
"WorkingMemory", "ConversationMemory", "LongTermMemory",
|
||||||
|
"SemanticMemory", "EpisodicMemory", "ProceduralMemory",
|
||||||
|
"UserModel", "WorldModel", "MemoryFacade",
|
||||||
|
"UserInterface", "ExternalTools",
|
||||||
|
"OutcomePredictor", "RiskAssessor", "ScenarioEngine",
|
||||||
|
"ConfigManager", "cli_main",
|
||||||
|
]
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
"""
|
||||||
|
DCOS entry point — invoked via `python -m dcos`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from .utils.cli import main
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main())
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
"""
|
||||||
|
Agent subsystem — provides base agent abstractions and specialized agent types.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from .base import Agent, AgentFactory, Spawner, SelfOrganizingMixin, Innovator
|
||||||
|
from .planning import PlanningAgent
|
||||||
|
from .research import ResearchAgent
|
||||||
|
from .logic import LogicAgent
|
||||||
|
from .creative import CreativeAgent
|
||||||
|
from .ethics import EthicsAgent
|
||||||
|
from .simulation import SimulationAgent
|
||||||
|
from .domain import DomainExpertAgent
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"Agent", "AgentFactory", "Spawner", "SelfOrganizingMixin", "Innovator",
|
||||||
|
"PlanningAgent", "ResearchAgent", "LogicAgent", "CreativeAgent",
|
||||||
|
"EthicsAgent", "SimulationAgent", "DomainExpertAgent",
|
||||||
|
]
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,136 @@
|
|||||||
|
"""
|
||||||
|
Base agent classes for the DCOS multi-agent architecture.
|
||||||
|
Provides the foundation for all specialized agent types.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
from typing import Any, Dict, List, Optional, Type
|
||||||
|
from dataclasses import dataclass, field
|
||||||
|
from enum import Enum
|
||||||
|
from uuid import uuid4
|
||||||
|
|
||||||
|
|
||||||
|
class AgentRole(Enum):
|
||||||
|
PLANNER = "planner"
|
||||||
|
RESEARCHER = "researcher"
|
||||||
|
LOGICIAN = "logician"
|
||||||
|
CREATIVE = "creative"
|
||||||
|
ETHICIST = "ethicist"
|
||||||
|
SIMULATOR = "simulator"
|
||||||
|
DOMAIN_EXPERT = "domain_expert"
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class AgentIdentity:
|
||||||
|
id: str = field(default_factory=lambda: uuid4().hex[:16])
|
||||||
|
name: str = ""
|
||||||
|
role: AgentRole = AgentRole.PLANNER
|
||||||
|
version: str = "1.0.0"
|
||||||
|
|
||||||
|
|
||||||
|
class Agent:
|
||||||
|
"""
|
||||||
|
Base class for all DCOS agents.
|
||||||
|
Provides identity, state management, and communication primitives.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, name: str, role: AgentRole = AgentRole.PLANNER) -> None:
|
||||||
|
self.identity = AgentIdentity(name=name, role=role)
|
||||||
|
self._state: Dict[str, Any] = {}
|
||||||
|
self._capabilities: List[str] = []
|
||||||
|
self._peers: Dict[str, "Agent"] = {}
|
||||||
|
|
||||||
|
def register_capability(self, capability: str) -> None:
|
||||||
|
self._capabilities.append(capability)
|
||||||
|
|
||||||
|
def get_capabilities(self) -> List[str]:
|
||||||
|
return list(self._capabilities)
|
||||||
|
|
||||||
|
def set_state(self, key: str, value: Any) -> None:
|
||||||
|
self._state[key] = value
|
||||||
|
|
||||||
|
def get_state(self, key: str) -> Optional[Any]:
|
||||||
|
return self._state.get(key)
|
||||||
|
|
||||||
|
def connect_to(self, peer: "Agent") -> None:
|
||||||
|
self._peers[peer.identity.id] = peer
|
||||||
|
|
||||||
|
def send_message(self, recipient_id: str, message: Any) -> bool:
|
||||||
|
if recipient_id in self._peers:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def receive_message(self, sender_id: str, message: Any) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def act(self, context: Dict[str, Any]) -> Any:
|
||||||
|
"""Perform the agent's primary action based on context."""
|
||||||
|
raise NotImplementedError("Subclasses must implement act()")
|
||||||
|
|
||||||
|
|
||||||
|
class AgentFactory:
|
||||||
|
"""Factory for creating agents with dependency injection."""
|
||||||
|
|
||||||
|
_registry: Dict[str, Type[Agent]] = {}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def register(cls, name: str, agent_class: Type[Agent]) -> None:
|
||||||
|
cls._registry[name] = agent_class
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create(cls, name: str, role: AgentRole, **kwargs: Any) -> Agent:
|
||||||
|
agent_class = cls._registry.get(name, Agent)
|
||||||
|
return agent_class(name=name, role=role, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class Spawner:
|
||||||
|
"""Manages agent lifecycle — spawn, suspend, resume, terminate."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self._agents: Dict[str, Agent] = {}
|
||||||
|
self._max_agents: int = 100
|
||||||
|
|
||||||
|
def spawn(self, agent: Agent) -> str:
|
||||||
|
if len(self._agents) >= self._max_agents:
|
||||||
|
raise RuntimeError("Agent pool full")
|
||||||
|
self._agents[agent.identity.id] = agent
|
||||||
|
return agent.identity.id
|
||||||
|
|
||||||
|
def terminate(self, agent_id: str) -> bool:
|
||||||
|
return agent_id in self._agents and bool(self._agents.pop(agent_id, None))
|
||||||
|
|
||||||
|
def get_active_agents(self) -> List[Agent]:
|
||||||
|
return list(self._agents.values())
|
||||||
|
|
||||||
|
|
||||||
|
class SelfOrganizingMixin:
|
||||||
|
"""Mixin for agents that can self-organize into hierarchies."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self._parent: Optional[Agent] = None
|
||||||
|
self._children: Dict[str, Agent] = {}
|
||||||
|
|
||||||
|
def adopt(self, child: Agent) -> None:
|
||||||
|
self._children[child.identity.id] = child
|
||||||
|
|
||||||
|
def delegate(self, task: Any) -> Optional[Agent]:
|
||||||
|
if not self._children:
|
||||||
|
return None
|
||||||
|
return next(iter(self._children.values()))
|
||||||
|
|
||||||
|
|
||||||
|
class Innovator:
|
||||||
|
"""Capability for generating novel solutions."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self._innovation_history: List[Dict[str, Any]] = []
|
||||||
|
|
||||||
|
def innovate(self, problem: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
|
solution = {
|
||||||
|
"problem": problem,
|
||||||
|
"approach": "cross-domain_synthesis",
|
||||||
|
"novelty_score": 0.7,
|
||||||
|
"solution": "generated_novel_solution",
|
||||||
|
}
|
||||||
|
self._innovation_history.append(solution)
|
||||||
|
return solution
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
"""
|
||||||
|
Creative agent — generates novel ideas, metaphors, and creative solutions.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
from typing import Any, Dict, List
|
||||||
|
from .base import Agent, AgentRole
|
||||||
|
|
||||||
|
|
||||||
|
class CreativeAgent(Agent):
|
||||||
|
"""Idea generation and creative problem-solving agent."""
|
||||||
|
|
||||||
|
def __init__(self, name: str = "creative") -> None:
|
||||||
|
super().__init__(name, AgentRole.CREATIVE)
|
||||||
|
self._creations: List[Dict[str, Any]] = []
|
||||||
|
self.register_capability("idea_generation")
|
||||||
|
self.register_capability("analogical_reasoning")
|
||||||
|
|
||||||
|
def act(self, context: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
|
prompt = context.get("prompt", "generate")
|
||||||
|
idea = self.generate(prompt)
|
||||||
|
return {"idea": idea, "originality_score": 0.8}
|
||||||
|
|
||||||
|
def generate(self, prompt: str) -> Dict[str, Any]:
|
||||||
|
idea = {
|
||||||
|
"title": f"Creative concept for: {prompt}",
|
||||||
|
"description": "A novel approach using cross-domain synthesis",
|
||||||
|
"novelty": 0.85,
|
||||||
|
"feasibility": 0.6,
|
||||||
|
}
|
||||||
|
self._creations.append(idea)
|
||||||
|
return idea
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
"""
|
||||||
|
Domain expert agent — provides specialized knowledge in specific domains.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
from typing import Any, Dict, List, Optional
|
||||||
|
from .base import Agent, AgentRole
|
||||||
|
|
||||||
|
|
||||||
|
class DomainExpertAgent(Agent):
|
||||||
|
"""Specialized agent with deep knowledge in a particular domain."""
|
||||||
|
|
||||||
|
def __init__(self, name: str = "domain_expert", domain: str = "general") -> None:
|
||||||
|
super().__init__(name, AgentRole.DOMAIN_EXPERT)
|
||||||
|
self.domain = domain
|
||||||
|
self._knowledge_base: Dict[str, Any] = {}
|
||||||
|
self.register_capability(f"domain_knowledge_{domain}")
|
||||||
|
|
||||||
|
def act(self, context: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
|
question = context.get("question", "")
|
||||||
|
answer = self.answer(question)
|
||||||
|
return {"domain": self.domain, "answer": answer}
|
||||||
|
|
||||||
|
def answer(self, question: str) -> str:
|
||||||
|
return f"[{self.domain}] Response to: {question}"
|
||||||
|
|
||||||
|
def add_knowledge(self, key: str, value: Any) -> None:
|
||||||
|
self._knowledge_base[key] = value
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
"""
|
||||||
|
Ethics agent — ensures actions align with ethical guidelines and constraints.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
from typing import Any, Dict, List, Tuple
|
||||||
|
from .base import Agent, AgentRole
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
|
class EthicalConstraint(Enum):
|
||||||
|
BENEFICENCE = "beneficence"
|
||||||
|
NON_MALEFICENCE = "non_maleficence"
|
||||||
|
AUTONOMY = "autonomy"
|
||||||
|
JUSTICE = "justice"
|
||||||
|
EXPLICABILITY = "explicability"
|
||||||
|
|
||||||
|
|
||||||
|
class EthicsAgent(Agent):
|
||||||
|
"""Ethical overseer that validates actions against ethical principles."""
|
||||||
|
|
||||||
|
def __init__(self, name: str = "ethicist") -> None:
|
||||||
|
super().__init__(name, AgentRole.ETHICIST)
|
||||||
|
self._constraints: List[EthicalConstraint] = list(EthicalConstraint)
|
||||||
|
self.register_capability("ethical_validation")
|
||||||
|
self.register_capability("value_alignment")
|
||||||
|
|
||||||
|
def act(self, context: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
|
action = context.get("action", "")
|
||||||
|
violations = self.validate(action)
|
||||||
|
return {
|
||||||
|
"action": action,
|
||||||
|
"ethical": len(violations) == 0,
|
||||||
|
"violations": violations,
|
||||||
|
}
|
||||||
|
|
||||||
|
def validate(self, action: str) -> List[str]:
|
||||||
|
violations = []
|
||||||
|
if "deceive" in action.lower():
|
||||||
|
violations.append("autonomy_violation")
|
||||||
|
if "harm" in action.lower():
|
||||||
|
violations.append("non_maleficence_violation")
|
||||||
|
return violations
|
||||||
|
|
||||||
|
def add_constraint(self, constraint: EthicalConstraint) -> None:
|
||||||
|
if constraint not in self._constraints:
|
||||||
|
self._constraints.append(constraint)
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
"""
|
||||||
|
Logic agent — performs reasoning, inference, and logical analysis.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
from typing import Any, Dict, List
|
||||||
|
from .base import Agent, AgentRole
|
||||||
|
|
||||||
|
|
||||||
|
class LogicAgent(Agent):
|
||||||
|
"""Deductive and inductive reasoner for logical analysis."""
|
||||||
|
|
||||||
|
def __init__(self, name: str = "logician") -> None:
|
||||||
|
super().__init__(name, AgentRole.LOGICIAN)
|
||||||
|
self._inferences: List[str] = []
|
||||||
|
self.register_capability("logical_reasoning")
|
||||||
|
self.register_capability("contradiction_detection")
|
||||||
|
|
||||||
|
def act(self, context: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
|
premises = context.get("premises", [])
|
||||||
|
conclusion = self.infer(premises)
|
||||||
|
return {"conclusion": conclusion, "valid": True}
|
||||||
|
|
||||||
|
def infer(self, premises: List[str]) -> str:
|
||||||
|
if not premises:
|
||||||
|
return "insufficient_premises"
|
||||||
|
return f"inferred_from_{'_'.join(premises)}"
|
||||||
|
|
||||||
|
def detect_contradiction(self, statements: List[str]) -> bool:
|
||||||
|
return False # Placeholder — real implementation would check logical consistency
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
"""
|
||||||
|
Planning agent — responsible for strategic planning and task decomposition.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
from typing import Any, Dict, List
|
||||||
|
from .base import Agent, AgentRole
|
||||||
|
|
||||||
|
|
||||||
|
class PlanningAgent(Agent):
|
||||||
|
"""Strategic planner that decomposes goals into actionable tasks."""
|
||||||
|
|
||||||
|
def __init__(self, name: str = "planner") -> None:
|
||||||
|
super().__init__(name, AgentRole.PLANNER)
|
||||||
|
self._plans: List[Dict[str, Any]] = []
|
||||||
|
self.register_capability("strategic_planning")
|
||||||
|
self.register_capability("task_decomposition")
|
||||||
|
|
||||||
|
def act(self, context: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
|
goal = context.get("goal", "undefined")
|
||||||
|
return {
|
||||||
|
"plan": f"Plan for: {goal}",
|
||||||
|
"steps": [
|
||||||
|
{"step": 1, "action": "analyze", "agent": "researcher"},
|
||||||
|
{"step": 2, "action": "synthesize", "agent": "logician"},
|
||||||
|
{"step": 3, "action": "create", "agent": "creative"},
|
||||||
|
{"step": 4, "action": "validate", "agent": "ethicist"},
|
||||||
|
{"step": 5, "action": "simulate", "agent": "simulator"},
|
||||||
|
],
|
||||||
|
"estimated_duration": 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
def decompose(self, goal: str) -> List[Dict[str, Any]]:
|
||||||
|
tasks = [
|
||||||
|
{"id": "research", "depends_on": []},
|
||||||
|
{"id": "analysis", "depends_on": ["research"]},
|
||||||
|
{"id": "generation", "depends_on": ["analysis"]},
|
||||||
|
{"id": "validation", "depends_on": ["generation"]},
|
||||||
|
]
|
||||||
|
self._plans.append({"goal": goal, "tasks": tasks})
|
||||||
|
return tasks
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
"""
|
||||||
|
Research agent — gathers and synthesizes information from multiple sources.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
from typing import Any, Dict, List
|
||||||
|
from .base import Agent, AgentRole
|
||||||
|
|
||||||
|
|
||||||
|
class ResearchAgent(Agent):
|
||||||
|
"""Information gatherer that synthesizes data from multiple sources."""
|
||||||
|
|
||||||
|
def __init__(self, name: str = "researcher") -> None:
|
||||||
|
super().__init__(name, AgentRole.RESEARCHER)
|
||||||
|
self._findings: Dict[str, Any] = {}
|
||||||
|
self.register_capability("information_gathering")
|
||||||
|
self.register_capability("cross_referencing")
|
||||||
|
|
||||||
|
def act(self, context: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
|
query = context.get("query", "general")
|
||||||
|
return {
|
||||||
|
"findings": [f"Result for: {query}"],
|
||||||
|
"confidence": 0.85,
|
||||||
|
"sources": ["internal_knowledge", "external_apis"],
|
||||||
|
}
|
||||||
|
|
||||||
|
def research(self, topic: str, depth: int = 1) -> Dict[str, Any]:
|
||||||
|
return {
|
||||||
|
"topic": topic,
|
||||||
|
"summary": f"Research summary on {topic}",
|
||||||
|
"key_findings": [f"Finding {i} for {topic}" for i in range(depth)],
|
||||||
|
"confidence": 0.75,
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
"""
|
||||||
|
Simulation agent — runs simulations to test scenarios and predict outcomes.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
from typing import Any, Dict, List, Optional
|
||||||
|
from .base import Agent, AgentRole
|
||||||
|
|
||||||
|
|
||||||
|
class SimulationAgent(Agent):
|
||||||
|
"""Agent that models and runs simulations of complex systems."""
|
||||||
|
|
||||||
|
def __init__(self, name: str = "simulator") -> None:
|
||||||
|
super().__init__(name, AgentRole.SIMULATOR)
|
||||||
|
self._simulations: List[Dict[str, Any]] = []
|
||||||
|
self.register_capability("scenario_simulation")
|
||||||
|
self.register_capability("monte_carlo_forecasting")
|
||||||
|
|
||||||
|
def act(self, context: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
|
scenario = context.get("scenario", "default")
|
||||||
|
result = self.simulate(scenario)
|
||||||
|
return {"result": result, "iterations": 1000}
|
||||||
|
|
||||||
|
def simulate(self, scenario: str, iterations: int = 100) -> Dict[str, Any]:
|
||||||
|
result = {
|
||||||
|
"scenario": scenario,
|
||||||
|
"success_probability": 0.72,
|
||||||
|
"mean_outcome": "positive",
|
||||||
|
"variance": 0.15,
|
||||||
|
"confidence_interval": (0.65, 0.85),
|
||||||
|
}
|
||||||
|
self._simulations.append(result)
|
||||||
|
return result
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
"""
|
||||||
|
Communication subsystem — provides message passing, routing, and discovery.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from .protocol import CommunicationProtocol
|
||||||
|
from .network import CommunicationNetwork
|
||||||
|
from .router import MessageRouter
|
||||||
|
from .resolver import AddressResolver
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"CommunicationProtocol",
|
||||||
|
"CommunicationNetwork",
|
||||||
|
"MessageRouter",
|
||||||
|
"AddressResolver",
|
||||||
|
]
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,46 @@
|
|||||||
|
"""
|
||||||
|
Communication network — manages agent connectivity and message delivery.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
from typing import Any, Dict, List, Optional
|
||||||
|
from .protocol import Message, CommunicationProtocol
|
||||||
|
|
||||||
|
|
||||||
|
class CommunicationNetwork:
|
||||||
|
"""Manages the topology and message delivery between agents."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self._protocol = CommunicationProtocol()
|
||||||
|
self._connections: Dict[str, List[str]] = {} # agent_id -> [peer_ids]
|
||||||
|
self._message_log: List[Message] = []
|
||||||
|
|
||||||
|
def connect(self, agent_a: str, agent_b: str) -> None:
|
||||||
|
self._connections.setdefault(agent_a, []).append(agent_b)
|
||||||
|
self._connections.setdefault(agent_b, []).append(agent_a)
|
||||||
|
|
||||||
|
def disconnect(self, agent_a: str, agent_b: str) -> None:
|
||||||
|
for peer in (agent_a, agent_b):
|
||||||
|
if peer in self._connections:
|
||||||
|
self._connections[peer] = [
|
||||||
|
p for p in self._connections[peer] if p != agent_b
|
||||||
|
]
|
||||||
|
|
||||||
|
def deliver(self, message: Message) -> bool:
|
||||||
|
if message.recipient in self._connections.get(message.sender, []):
|
||||||
|
self._message_log.append(message)
|
||||||
|
return self._protocol.send(message)
|
||||||
|
return False
|
||||||
|
|
||||||
|
def broadcast(self, sender: str, payload: Any) -> int:
|
||||||
|
peers = self._connections.get(sender, [])
|
||||||
|
for peer in peers:
|
||||||
|
msg = Message(sender=sender, recipient=peer, payload=payload)
|
||||||
|
self._message_log.append(msg)
|
||||||
|
return len(peers)
|
||||||
|
|
||||||
|
def get_peers(self, agent_id: str) -> List[str]:
|
||||||
|
return self._connections.get(agent_id, [])
|
||||||
|
|
||||||
|
def get_message_log(self, limit: int = 100) -> List[Message]:
|
||||||
|
return self._message_log[-limit:]
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
"""
|
||||||
|
Communication protocol — defines message formats and delivery semantics.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
from typing import Any, Dict, Optional
|
||||||
|
from dataclasses import dataclass, field
|
||||||
|
from datetime import datetime
|
||||||
|
from uuid import uuid4
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Message:
|
||||||
|
sender: str
|
||||||
|
recipient: str
|
||||||
|
payload: Any
|
||||||
|
msg_id: str = field(default_factory=lambda: uuid4().hex)
|
||||||
|
timestamp: datetime = field(default_factory=datetime.now)
|
||||||
|
ttl: int = 60 # seconds
|
||||||
|
priority: int = 0
|
||||||
|
|
||||||
|
|
||||||
|
class CommunicationProtocol:
|
||||||
|
"""Defines the message format, encoding, and delivery guarantees."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self._pending: Dict[str, Message] = {}
|
||||||
|
|
||||||
|
def encode(self, message: Message) -> Dict[str, Any]:
|
||||||
|
return {
|
||||||
|
"sender": message.sender,
|
||||||
|
"recipient": message.recipient,
|
||||||
|
"payload": message.payload,
|
||||||
|
"msg_id": message.msg_id,
|
||||||
|
"timestamp": message.timestamp.isoformat(),
|
||||||
|
"ttl": message.ttl,
|
||||||
|
"priority": message.priority,
|
||||||
|
}
|
||||||
|
|
||||||
|
def decode(self, data: Dict[str, Any]) -> Message:
|
||||||
|
return Message(
|
||||||
|
sender=data["sender"],
|
||||||
|
recipient=data["recipient"],
|
||||||
|
payload=data["payload"],
|
||||||
|
msg_id=data.get("msg_id", uuid4().hex),
|
||||||
|
)
|
||||||
|
|
||||||
|
def send(self, message: Message) -> bool:
|
||||||
|
self._pending[message.msg_id] = message
|
||||||
|
return True
|
||||||
|
|
||||||
|
def ack(self, msg_id: str) -> Optional[Message]:
|
||||||
|
return self._pending.pop(msg_id, None)
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
"""
|
||||||
|
Address resolver — resolves agent names/roles to their network addresses.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
from typing import Dict, List, Optional
|
||||||
|
|
||||||
|
|
||||||
|
class AddressResolver:
|
||||||
|
"""Resolves symbolic agent names and roles to concrete agent IDs."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self._name_table: Dict[str, str] = {} # name -> agent_id
|
||||||
|
self._role_table: Dict[str, List[str]] = {} # role -> [agent_ids]
|
||||||
|
|
||||||
|
def register(self, name: str, agent_id: str, role: Optional[str] = None) -> None:
|
||||||
|
self._name_table[name] = agent_id
|
||||||
|
if role:
|
||||||
|
self._role_table.setdefault(role, []).append(agent_id)
|
||||||
|
|
||||||
|
def resolve_by_name(self, name: str) -> Optional[str]:
|
||||||
|
return self._name_table.get(name)
|
||||||
|
|
||||||
|
def resolve_by_role(self, role: str) -> List[str]:
|
||||||
|
return self._role_table.get(role, [])
|
||||||
|
|
||||||
|
def unregister(self, name: str) -> Optional[str]:
|
||||||
|
agent_id = self._name_table.pop(name, None)
|
||||||
|
if agent_id:
|
||||||
|
for role, ids in self._role_table.items():
|
||||||
|
self._role_table[role] = [i for i in ids if i != agent_id]
|
||||||
|
return agent_id
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
"""
|
||||||
|
Message router — directs messages to the correct recipient based on routing rules.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
from typing import Any, Dict, List, Optional
|
||||||
|
from .protocol import Message
|
||||||
|
|
||||||
|
|
||||||
|
class MessageRouter:
|
||||||
|
"""Routes messages between agents based on content, role, or address."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self._routes: Dict[str, str] = {} # routing_key -> agent_id
|
||||||
|
self._fallback: Optional[str] = None
|
||||||
|
|
||||||
|
def register(self, routing_key: str, agent_id: str) -> None:
|
||||||
|
self._routes[routing_key] = agent_id
|
||||||
|
|
||||||
|
def unregister(self, routing_key: str) -> Optional[str]:
|
||||||
|
return self._routes.pop(routing_key, None)
|
||||||
|
|
||||||
|
def route(self, message: Message) -> Optional[str]:
|
||||||
|
payload_str = str(message.payload)
|
||||||
|
for key, agent_id in self._routes.items():
|
||||||
|
if key in payload_str:
|
||||||
|
return agent_id
|
||||||
|
return self._fallback
|
||||||
|
|
||||||
|
def set_fallback(self, agent_id: str) -> None:
|
||||||
|
self._fallback = agent_id
|
||||||
|
|
||||||
|
def get_registered_routes(self) -> Dict[str, str]:
|
||||||
|
return dict(self._routes)
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
"""
|
||||||
|
Core subsystem — scheduling, coordination, registry, and resource allocation.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from .scheduler import TaskScheduler
|
||||||
|
from .coordinator import AgentCoordinator
|
||||||
|
from .registry import AgentRegistry
|
||||||
|
from .allocator import ResourceAllocator
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"TaskScheduler",
|
||||||
|
"AgentCoordinator",
|
||||||
|
"AgentRegistry",
|
||||||
|
"ResourceAllocator",
|
||||||
|
]
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,45 @@
|
|||||||
|
"""
|
||||||
|
Resource allocator — manages compute and memory resource distribution among agents.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
from typing import Dict, List, Optional, Tuple
|
||||||
|
|
||||||
|
|
||||||
|
class ResourceAllocator:
|
||||||
|
"""Allocates system resources (compute, memory, bandwidth) among agents."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self._total_cpu: float = 100.0
|
||||||
|
self._total_memory: float = 1024.0
|
||||||
|
self._allocations: Dict[str, Dict[str, float]] = {}
|
||||||
|
|
||||||
|
def allocate(self, agent_id: str, cpu: float, memory: float) -> bool:
|
||||||
|
if cpu <= 0 or memory <= 0:
|
||||||
|
return False
|
||||||
|
remaining_cpu = self._total_cpu - sum(
|
||||||
|
a.get("cpu", 0) for a in self._allocations.values()
|
||||||
|
)
|
||||||
|
remaining_memory = self._total_memory - sum(
|
||||||
|
a.get("memory", 0) for a in self._allocations.values()
|
||||||
|
)
|
||||||
|
if cpu > remaining_cpu or memory > remaining_memory:
|
||||||
|
return False
|
||||||
|
self._allocations[agent_id] = {"cpu": cpu, "memory": memory}
|
||||||
|
return True
|
||||||
|
|
||||||
|
def release(self, agent_id: str) -> bool:
|
||||||
|
return agent_id in self._allocations and bool(
|
||||||
|
self._allocations.pop(agent_id, None)
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_allocation(self, agent_id: str) -> Dict[str, float]:
|
||||||
|
return self._allocations.get(agent_id, {"cpu": 0.0, "memory": 0.0})
|
||||||
|
|
||||||
|
def utilization(self) -> Dict[str, float]:
|
||||||
|
total_cpu = sum(a.get("cpu", 0) for a in self._allocations.values())
|
||||||
|
total_mem = sum(a.get("memory", 0) for a in self._allocations.values())
|
||||||
|
return {
|
||||||
|
"cpu": total_cpu / self._total_cpu,
|
||||||
|
"memory": total_mem / self._total_memory,
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
"""
|
||||||
|
Agent coordinator — orchestrates multi-agent workflows and collaboration.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
from typing import Any, Dict, List, Optional
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
|
class AgentCoordinator:
|
||||||
|
"""Coordinates multiple agents to work on complex tasks collaboratively."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self._workflows: Dict[str, List[str]] = {} # workflow_id -> [agent_ids]
|
||||||
|
self._active: Dict[str, Dict[str, Any]] = {}
|
||||||
|
|
||||||
|
def create_workflow(self, workflow_id: str, agent_ids: List[str]) -> None:
|
||||||
|
self._workflows[workflow_id] = agent_ids
|
||||||
|
self._active[workflow_id] = {
|
||||||
|
"status": "created",
|
||||||
|
"created_at": datetime.now().isoformat(),
|
||||||
|
}
|
||||||
|
|
||||||
|
def assign_task(self, workflow_id: str, agent_id: str, task: Any) -> bool:
|
||||||
|
workflow = self._workflows.get(workflow_id)
|
||||||
|
if workflow and agent_id in workflow:
|
||||||
|
self._active.setdefault(workflow_id, {})["current_task"] = str(task)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_workflow_status(self, workflow_id: str) -> Optional[Dict[str, Any]]:
|
||||||
|
return self._active.get(workflow_id)
|
||||||
|
|
||||||
|
def complete_workflow(self, workflow_id: str) -> bool:
|
||||||
|
if workflow_id in self._active:
|
||||||
|
self._active[workflow_id]["status"] = "completed"
|
||||||
|
return True
|
||||||
|
return False
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
"""
|
||||||
|
Agent registry — maintains a directory of all active agents and their capabilities.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
from typing import Any, Dict, List, Optional
|
||||||
|
from dataclasses import dataclass, field
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class AgentRecord:
|
||||||
|
agent_id: str
|
||||||
|
name: str
|
||||||
|
role: str
|
||||||
|
capabilities: List[str] = field(default_factory=list)
|
||||||
|
status: str = "active"
|
||||||
|
address: str = ""
|
||||||
|
|
||||||
|
|
||||||
|
class AgentRegistry:
|
||||||
|
"""Directory of all agents in the system with their metadata."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self._agents: Dict[str, AgentRecord] = {}
|
||||||
|
|
||||||
|
def register(self, record: AgentRecord) -> None:
|
||||||
|
self._agents[record.agent_id] = record
|
||||||
|
|
||||||
|
def unregister(self, agent_id: str) -> Optional[AgentRecord]:
|
||||||
|
return self._agents.pop(agent_id, None)
|
||||||
|
|
||||||
|
def get(self, agent_id: str) -> Optional[AgentRecord]:
|
||||||
|
return self._agents.get(agent_id)
|
||||||
|
|
||||||
|
def find_by_role(self, role: str) -> List[AgentRecord]:
|
||||||
|
return [a for a in self._agents.values() if a.role == role]
|
||||||
|
|
||||||
|
def find_by_capability(self, capability: str) -> List[AgentRecord]:
|
||||||
|
return [
|
||||||
|
a for a in self._agents.values()
|
||||||
|
if capability in a.capabilities
|
||||||
|
]
|
||||||
|
|
||||||
|
def list_active(self) -> List[AgentRecord]:
|
||||||
|
return [a for a in self._agents.values() if a.status == "active"]
|
||||||
|
|
||||||
|
def count(self) -> int:
|
||||||
|
return len(self._agents)
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
"""
|
||||||
|
Task scheduler — manages task queuing, prioritization, and execution ordering.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
from typing import Any, Dict, List, Optional
|
||||||
|
from dataclasses import dataclass, field
|
||||||
|
from datetime import datetime
|
||||||
|
from enum import Enum
|
||||||
|
from uuid import uuid4
|
||||||
|
|
||||||
|
|
||||||
|
class TaskStatus(Enum):
|
||||||
|
PENDING = "pending"
|
||||||
|
RUNNING = "running"
|
||||||
|
COMPLETED = "completed"
|
||||||
|
FAILED = "failed"
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Task:
|
||||||
|
id: str = field(default_factory=lambda: uuid4().hex)
|
||||||
|
name: str = ""
|
||||||
|
agent_id: str = ""
|
||||||
|
status: TaskStatus = TaskStatus.PENDING
|
||||||
|
priority: int = 0
|
||||||
|
created_at: datetime = field(default_factory=datetime.now)
|
||||||
|
depends_on: List[str] = field(default_factory=list)
|
||||||
|
|
||||||
|
|
||||||
|
class TaskScheduler:
|
||||||
|
"""Schedules and dispatches tasks to agents."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self._queue: List[Task] = []
|
||||||
|
self._running: List[Task] = []
|
||||||
|
self._completed: List[Task] = []
|
||||||
|
|
||||||
|
def enqueue(self, task: Task) -> None:
|
||||||
|
self._queue.append(task)
|
||||||
|
self._queue.sort(key=lambda t: t.priority, reverse=True)
|
||||||
|
|
||||||
|
def dequeue(self) -> Optional[Task]:
|
||||||
|
if not self._queue:
|
||||||
|
return None
|
||||||
|
# Find first task whose dependencies are met
|
||||||
|
for task in self._queue:
|
||||||
|
deps_met = all(
|
||||||
|
dep in [c.id for c in self._completed]
|
||||||
|
for dep in task.depends_on
|
||||||
|
)
|
||||||
|
if deps_met:
|
||||||
|
self._queue.remove(task)
|
||||||
|
task.status = TaskStatus.RUNNING
|
||||||
|
self._running.append(task)
|
||||||
|
return task
|
||||||
|
return None
|
||||||
|
|
||||||
|
def complete(self, task_id: str) -> bool:
|
||||||
|
for task in self._running:
|
||||||
|
if task.id == task_id:
|
||||||
|
self._running.remove(task)
|
||||||
|
task.status = TaskStatus.COMPLETED
|
||||||
|
self._completed.append(task)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def fail(self, task_id: str) -> bool:
|
||||||
|
for task in self._running:
|
||||||
|
if task.id == task_id:
|
||||||
|
self._running.remove(task)
|
||||||
|
task.status = TaskStatus.FAILED
|
||||||
|
self._completed.append(task)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def pending_count(self) -> int:
|
||||||
|
return len(self._queue)
|
||||||
|
|
||||||
|
def running_count(self) -> int:
|
||||||
|
return len(self._running)
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
"""
|
||||||
|
Learning subsystem — provides reinforcement learning and model updates.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from .engine import LearningEngine
|
||||||
|
|
||||||
|
__all__ = ["LearningEngine"]
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,44 @@
|
|||||||
|
"""
|
||||||
|
Learning engine — reinforcement learning and model updates for agents.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
from typing import Any, Dict, List, Optional
|
||||||
|
from dataclasses import dataclass, field
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Experience:
|
||||||
|
state: Dict[str, Any]
|
||||||
|
action: str
|
||||||
|
reward: float
|
||||||
|
next_state: Optional[Dict[str, Any]] = None
|
||||||
|
|
||||||
|
|
||||||
|
class LearningEngine:
|
||||||
|
"""Reinforcement learning engine that improves agent behavior over time."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self._experiences: List[Experience] = []
|
||||||
|
self._policy: Dict[str, float] = {}
|
||||||
|
|
||||||
|
def record_experience(self, exp: Experience) -> None:
|
||||||
|
self._experiences.append(exp)
|
||||||
|
self._update_policy(exp)
|
||||||
|
|
||||||
|
def _update_policy(self, exp: Experience) -> None:
|
||||||
|
current = self._policy.get(exp.action, 0.0)
|
||||||
|
self._policy[exp.action] = current + exp.reward * 0.1
|
||||||
|
|
||||||
|
def get_action_score(self, action: str) -> float:
|
||||||
|
return self._policy.get(action, 0.0)
|
||||||
|
|
||||||
|
def best_action(self, actions: List[str]) -> Optional[str]:
|
||||||
|
if not actions:
|
||||||
|
return None
|
||||||
|
scored = [(a, self._policy.get(a, 0.0)) for a in actions]
|
||||||
|
scored.sort(key=lambda x: x[1], reverse=True)
|
||||||
|
return scored[0][0]
|
||||||
|
|
||||||
|
def experience_count(self) -> int:
|
||||||
|
return len(self._experiences)
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
"""
|
||||||
|
Memory subsystem — multiple memory types and the unified facade.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from .working import WorkingMemory
|
||||||
|
from .conversation import ConversationMemory
|
||||||
|
from .long_term import LongTermMemory
|
||||||
|
from .semantic import SemanticMemory
|
||||||
|
from .episodic import EpisodicMemory
|
||||||
|
from .procedural import ProceduralMemory
|
||||||
|
from .user_model import UserModel
|
||||||
|
from .world_model import WorldModel
|
||||||
|
from .memory_facade import MemoryFacade
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"WorkingMemory",
|
||||||
|
"ConversationMemory",
|
||||||
|
"LongTermMemory",
|
||||||
|
"SemanticMemory",
|
||||||
|
"EpisodicMemory",
|
||||||
|
"ProceduralMemory",
|
||||||
|
"UserModel",
|
||||||
|
"WorldModel",
|
||||||
|
"MemoryFacade",
|
||||||
|
]
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,55 @@
|
|||||||
|
"""
|
||||||
|
Conversation memory — stores dialogue history and turn-by-turn context.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
from typing import Any, Dict, List, Optional
|
||||||
|
from dataclasses import dataclass, field
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Turn:
|
||||||
|
agent_id: str
|
||||||
|
content: str
|
||||||
|
timestamp: datetime = field(default_factory=datetime.now)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Conversation:
|
||||||
|
conversation_id: str
|
||||||
|
participants: List[str]
|
||||||
|
turns: List[Turn] = field(default_factory=list)
|
||||||
|
created_at: datetime = field(default_factory=datetime.now)
|
||||||
|
|
||||||
|
|
||||||
|
class ConversationMemory:
|
||||||
|
"""Stores dialogue history with turn-by-turn context."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self._conversations: Dict[str, Conversation] = {}
|
||||||
|
|
||||||
|
def create(self, conversation_id: str, participants: List[str]) -> Conversation:
|
||||||
|
conv = Conversation(
|
||||||
|
conversation_id=conversation_id,
|
||||||
|
participants=participants,
|
||||||
|
)
|
||||||
|
self._conversations[conversation_id] = conv
|
||||||
|
return conv
|
||||||
|
|
||||||
|
def add_turn(self, conversation_id: str, agent_id: str, content: str) -> Optional[Turn]:
|
||||||
|
conv = self._conversations.get(conversation_id)
|
||||||
|
if not conv:
|
||||||
|
return None
|
||||||
|
turn = Turn(agent_id=agent_id, content=content)
|
||||||
|
conv.turns.append(turn)
|
||||||
|
return turn
|
||||||
|
|
||||||
|
def get_history(self, conversation_id: str) -> Optional[List[Turn]]:
|
||||||
|
conv = self._conversations.get(conversation_id)
|
||||||
|
if conv:
|
||||||
|
return conv.turns
|
||||||
|
return None
|
||||||
|
|
||||||
|
def list_conversations(self) -> List[Conversation]:
|
||||||
|
return list(self._conversations.values())
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
"""
|
||||||
|
Episodic memory — stores past experiences as episodes with temporal context.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
from typing import Any, Dict, List, Optional
|
||||||
|
from dataclasses import dataclass, field
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Episode:
|
||||||
|
timestamp: datetime
|
||||||
|
context: Dict[str, Any]
|
||||||
|
outcome: Any
|
||||||
|
summary: str = ""
|
||||||
|
|
||||||
|
|
||||||
|
class EpisodicMemory:
|
||||||
|
"""Stores past experiences as episodes with full temporal context."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self._episodes: List[Episode] = []
|
||||||
|
self._max_episodes: int = 10000
|
||||||
|
|
||||||
|
def record(self, context: Dict[str, Any], outcome: Any, summary: str = "") -> Episode:
|
||||||
|
episode = Episode(
|
||||||
|
timestamp=datetime.now(),
|
||||||
|
context=context,
|
||||||
|
outcome=outcome,
|
||||||
|
summary=summary,
|
||||||
|
)
|
||||||
|
self._episodes.append(episode)
|
||||||
|
if len(self._episodes) > self._max_episodes:
|
||||||
|
self._episodes.pop(0)
|
||||||
|
return episode
|
||||||
|
|
||||||
|
def recall_recent(self, n: int = 10) -> List[Episode]:
|
||||||
|
return self._episodes[-n:]
|
||||||
|
|
||||||
|
def search_by_context(self, key: str, value: Any) -> List[Episode]:
|
||||||
|
return [
|
||||||
|
e for e in self._episodes
|
||||||
|
if e.context.get(key) == value
|
||||||
|
]
|
||||||
|
|
||||||
|
def episode_count(self) -> int:
|
||||||
|
return len(self._episodes)
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
"""
|
||||||
|
Long-term memory — persistent storage for important agent knowledge.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
from typing import Any, Dict, List, Optional
|
||||||
|
from datetime import datetime
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
|
class Importance(Enum):
|
||||||
|
LOW = "low"
|
||||||
|
MEDIUM = "medium"
|
||||||
|
HIGH = "high"
|
||||||
|
CRITICAL = "critical"
|
||||||
|
|
||||||
|
|
||||||
|
class LongTermMemory:
|
||||||
|
"""Persistent memory for important knowledge with consolidation."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self._store: Dict[str, Dict[str, Any]] = {}
|
||||||
|
|
||||||
|
def commit(self, key: str, value: Any, importance: Importance = Importance.MEDIUM) -> None:
|
||||||
|
self._store[key] = {
|
||||||
|
"value": value,
|
||||||
|
"importance": importance.value,
|
||||||
|
"committed_at": datetime.now().isoformat(),
|
||||||
|
}
|
||||||
|
|
||||||
|
def recall(self, key: str) -> Optional[Any]:
|
||||||
|
entry = self._store.get(key)
|
||||||
|
return entry["value"] if entry else None
|
||||||
|
|
||||||
|
def consolidate(self, working_items: Dict[str, Any]) -> int:
|
||||||
|
"""Consolidate important working memory items into long-term storage."""
|
||||||
|
count = 0
|
||||||
|
for key, value in working_items.items():
|
||||||
|
if key not in self._store:
|
||||||
|
self.commit(key, value, Importance.LOW)
|
||||||
|
count += 1
|
||||||
|
return count
|
||||||
|
|
||||||
|
def search(self, query: str) -> List[Dict[str, Any]]:
|
||||||
|
results = []
|
||||||
|
query_lower = query.lower()
|
||||||
|
for key, entry in self._store.items():
|
||||||
|
if query_lower in key.lower():
|
||||||
|
results.append({"key": key, **entry})
|
||||||
|
return results
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
"""
|
||||||
|
Memory facade — unified interface to all memory systems.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
from typing import Any, Dict, List, Optional
|
||||||
|
|
||||||
|
from .working import WorkingMemory
|
||||||
|
from .conversation import ConversationMemory
|
||||||
|
from .long_term import LongTermMemory
|
||||||
|
from .semantic import SemanticMemory
|
||||||
|
from .episodic import EpisodicMemory
|
||||||
|
from .procedural import ProceduralMemory
|
||||||
|
from .user_model import UserModel
|
||||||
|
from .world_model import WorldModel
|
||||||
|
|
||||||
|
|
||||||
|
class MemoryFacade:
|
||||||
|
"""
|
||||||
|
Unified facade that provides a single access point to all memory types.
|
||||||
|
Coordinates memory operations across working, long-term, semantic, etc.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.working = WorkingMemory()
|
||||||
|
self.conversation = ConversationMemory()
|
||||||
|
self.long_term = LongTermMemory()
|
||||||
|
self.semantic = SemanticMemory()
|
||||||
|
self.episodic = EpisodicMemory()
|
||||||
|
self.procedural = ProceduralMemory()
|
||||||
|
self.user_model = UserModel()
|
||||||
|
self.world_model = WorldModel()
|
||||||
|
|
||||||
|
def remember(self, key: str, value: Any, importance: str = "low") -> None:
|
||||||
|
"""Store in both working and long-term memory."""
|
||||||
|
self.working.store(key, value)
|
||||||
|
if importance in ("high", "critical"):
|
||||||
|
from .long_term import Importance
|
||||||
|
self.long_term.commit(key, value, Importance(importance))
|
||||||
|
|
||||||
|
def recall(self, key: str) -> Optional[Any]:
|
||||||
|
"""Retrieve from working, then long-term."""
|
||||||
|
value = self.working.recall(key)
|
||||||
|
if value is not None:
|
||||||
|
return value
|
||||||
|
return self.long_term.recall(key)
|
||||||
|
|
||||||
|
def search(self, query: str) -> Dict[str, List[Any]]:
|
||||||
|
"""Cross-memory search."""
|
||||||
|
return {
|
||||||
|
"working": [self.working.recall(query)],
|
||||||
|
"long_term": self.long_term.search(query),
|
||||||
|
"semantic": self.semantic.get_related(query),
|
||||||
|
}
|
||||||
|
|
||||||
|
def consolidate(self) -> int:
|
||||||
|
"""Move important working items to long-term storage."""
|
||||||
|
working_items = {
|
||||||
|
k: v["value"]
|
||||||
|
for k, v in self.working._items.items()
|
||||||
|
}
|
||||||
|
return self.long_term.consolidate(working_items)
|
||||||
|
|
||||||
|
def summary(self) -> Dict[str, int]:
|
||||||
|
return {
|
||||||
|
"working": self.working.size(),
|
||||||
|
"episodic": self.episodic.episode_count(),
|
||||||
|
"long_term": len(self.long_term._store),
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
"""
|
||||||
|
Procedural memory — stores learned procedures, skills, and know-how.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
from typing import Any, Callable, Dict, List, Optional
|
||||||
|
|
||||||
|
|
||||||
|
class ProceduralMemory:
|
||||||
|
"""Stores learned procedures, skills, and compiled know-how."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self._procedures: Dict[str, Dict[str, Any]] = {}
|
||||||
|
self._skills: Dict[str, Callable] = {}
|
||||||
|
|
||||||
|
def register_procedure(
|
||||||
|
self, name: str, steps: List[str],
|
||||||
|
preconditions: Optional[List[str]] = None,
|
||||||
|
postconditions: Optional[List[str]] = None,
|
||||||
|
) -> None:
|
||||||
|
self._procedures[name] = {
|
||||||
|
"steps": steps,
|
||||||
|
"preconditions": preconditions or [],
|
||||||
|
"postconditions": postconditions or [],
|
||||||
|
}
|
||||||
|
|
||||||
|
def register_skill(self, name: str, fn: Callable) -> None:
|
||||||
|
self._skills[name] = fn
|
||||||
|
|
||||||
|
def execute_procedure(self, name: str, context: Dict[str, Any]) -> Any:
|
||||||
|
procedure = self._procedures.get(name)
|
||||||
|
if not procedure:
|
||||||
|
raise KeyError(f"Procedure '{name}' not found")
|
||||||
|
return {"procedure": name, "steps": procedure["steps"], "executed": True}
|
||||||
|
|
||||||
|
def get_procedure(self, name: str) -> Optional[Dict[str, Any]]:
|
||||||
|
return self._procedures.get(name)
|
||||||
|
|
||||||
|
def list_procedures(self) -> List[str]:
|
||||||
|
return list(self._procedures.keys())
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
"""
|
||||||
|
Semantic memory — stores conceptual knowledge and relationships.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
from typing import Any, Dict, List, Optional
|
||||||
|
|
||||||
|
|
||||||
|
class SemanticMemory:
|
||||||
|
"""Stores conceptual knowledge, facts, and relationships between concepts."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self._facts: Dict[str, Dict[str, Any]] = {}
|
||||||
|
self._relationships: Dict[str, List[str]] = {}
|
||||||
|
|
||||||
|
def add_fact(self, concept: str, attribute: str, value: Any) -> None:
|
||||||
|
self._facts.setdefault(concept, {})[attribute] = value
|
||||||
|
|
||||||
|
def get_fact(self, concept: str, attribute: str) -> Optional[Any]:
|
||||||
|
facts = self._facts.get(concept)
|
||||||
|
return facts.get(attribute) if facts else None
|
||||||
|
|
||||||
|
def add_relationship(self, concept_a: str, concept_b: str) -> None:
|
||||||
|
self._relationships.setdefault(concept_a, []).append(concept_b)
|
||||||
|
self._relationships.setdefault(concept_b, []).append(concept_a)
|
||||||
|
|
||||||
|
def get_related(self, concept: str) -> List[str]:
|
||||||
|
return self._relationships.get(concept, [])
|
||||||
|
|
||||||
|
def query(self, attribute: str, value: Any) -> List[str]:
|
||||||
|
return [
|
||||||
|
concept for concept, facts in self._facts.items()
|
||||||
|
if facts.get(attribute) == value
|
||||||
|
]
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
"""
|
||||||
|
User model — stores user-specific preferences, behavior patterns, and history.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
from typing import Any, Dict, List, Optional
|
||||||
|
from dataclasses import dataclass, field
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class UserProfile:
|
||||||
|
user_id: str
|
||||||
|
name: str = ""
|
||||||
|
preferences: Dict[str, Any] = field(default_factory=dict)
|
||||||
|
interaction_count: int = 0
|
||||||
|
created_at: datetime = field(default_factory=datetime.now)
|
||||||
|
|
||||||
|
|
||||||
|
class UserModel:
|
||||||
|
"""Models user-specific preferences, behavior, and interaction history."""
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self._profiles: Dict[str, UserProfile] = {}
|
||||||
|
|
||||||
|
def get_or_create(self, user_id: str, name: str = "") -> UserProfile:
|
||||||
|
if user_id not in self._profiles:
|
||||||
|
self._profiles[user_id] = UserProfile(user_id=user_id, name=name)
|
||||||
|
return self._profiles[user_id]
|
||||||
|
|
||||||
|
def record_interaction(self, user_id: str, action: str) -> None:
|
||||||
|
profile = self._profiles.get(user_id)
|
||||||
|
if profile:
|
||||||
|
profile.interaction_count += 1
|
||||||
|
|
||||||
|
def set_preference(self, user_id: str, key: str, value: Any) -> None:
|
||||||
|
profile = self._profiles.get(user_id)
|
||||||
|
if profile:
|
||||||
|
profile.preferences[key] = value
|
||||||
|
|
||||||
|
def get_preference(self, user_id: str, key: str) -> Optional[Any]:
|
||||||
|
profile = self._profiles.get(user_id)
|
||||||
|
if profile:
|
||||||
|
return profile.preferences.get(key)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def list_users(self) -> List[UserProfile]:
|
||||||
|
return list(self._profiles.values())
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
"""
|
||||||
|
Working memory — short-term, high-access memory for active agent state.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
from typing import Any, Dict, List, Optional
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
|
class WorkingMemory:
|
||||||
|
"""Short-term memory for active agent state with automatic decay."""
|
||||||
|
|
||||||
|
def __init__(self, capacity: int = 1000) -> None:
|
||||||
|
self._items: Dict[str, Dict[str, Any]] = {}
|
||||||
|
self._capacity = capacity
|
||||||
|
self._access_log: Dict[str, datetime] = {}
|
||||||
|
|
||||||
|
def store(self, key: str, value: Any) -> None:
|
||||||
|
if len(self._items) >= self._capacity:
|
||||||
|
oldest = min(self._access_log, key=lambda k: self._access_log.get(k, datetime.min)) if self._access_log else None
|
||||||
|
if oldest:
|
||||||
|
self._items.pop(oldest, None)
|
||||||
|
self._access_log.pop(oldest, None)
|
||||||
|
self._items[key] = {"value": value, "stored_at": datetime.now()}
|
||||||
|
self._access_log[key] = datetime.now()
|
||||||
|
|
||||||
|
def recall(self, key: str) -> Optional[Any]:
|
||||||
|
if key in self._items:
|
||||||
|
self._access_log[key] = datetime.now()
|
||||||
|
return self._items[key]["value"]
|
||||||
|
return None
|
||||||
|
|
||||||
|
def contains(self, key: str) -> bool:
|
||||||
|
return key in self._items
|
||||||
|
|
||||||
|
def clear(self) -> None:
|
||||||
|
self._items.clear()
|
||||||
|
self._access_log.clear()
|
||||||
|
|
||||||
|
def size(self) -> int:
|
||||||
|
return len(self._items)
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user