aaax 0.0.1a0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
aaax/__init__.py ADDED
@@ -0,0 +1,20 @@
1
+ from importlib.metadata import PackageNotFoundError, version
2
+
3
+ from aaax.bootstrap import bootstrap_kernel
4
+ from aaax.config import AAAXConfig, LibOSConfig, ModuleConfig, NetworkConfig
5
+ from aaax.kernel import AAAXKernel
6
+
7
+ try:
8
+ __version__ = version("aaax")
9
+ except PackageNotFoundError:
10
+ __version__ = "0.1.0"
11
+
12
+ __all__ = [
13
+ "__version__",
14
+ "AAAXConfig",
15
+ "LibOSConfig",
16
+ "ModuleConfig",
17
+ "NetworkConfig",
18
+ "AAAXKernel",
19
+ "bootstrap_kernel",
20
+ ]
aaax/__main__.py ADDED
@@ -0,0 +1,5 @@
1
+ from aaax.cli import main
2
+
3
+
4
+ if __name__ == "__main__":
5
+ main()
aaax/_vendor.py ADDED
@@ -0,0 +1,16 @@
1
+ from __future__ import annotations
2
+
3
+ import sys
4
+ from pathlib import Path
5
+
6
+
7
+ def ensure_vendor_paths() -> None:
8
+ """Prefer vendored local framework repos when they exist in the workspace."""
9
+ root = Path(__file__).resolve().parents[1]
10
+ for name in ("sssn", "lllm"):
11
+ candidate = root / name
12
+ if not candidate.is_dir():
13
+ continue
14
+ path = str(candidate)
15
+ if path not in sys.path:
16
+ sys.path.insert(0, path)
aaax/action_gate.py ADDED
@@ -0,0 +1,77 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ from aaax.capability import CapabilityManager
6
+ from aaax.policy import PolicyEngine
7
+
8
+
9
+ def _message_content_data(msg) -> dict[str, Any]:
10
+ content = getattr(msg, "content", None)
11
+ data = getattr(content, "data", None)
12
+ return data if isinstance(data, dict) else {}
13
+
14
+
15
+ def _requester_id(msg, payload: dict[str, Any]) -> str:
16
+ return str(payload.get("from") or payload.get("system_id") or msg.sender_id)
17
+
18
+
19
+ class ActionGate:
20
+ """Authorize and classify side-effecting operations."""
21
+
22
+ async def process(
23
+ self,
24
+ msg,
25
+ policy: PolicyEngine,
26
+ capabilities: CapabilityManager,
27
+ ) -> dict[str, Any]:
28
+ content = _message_content_data(msg)
29
+ system_id = _requester_id(msg, content)
30
+ action = str(content["action"])
31
+ executor = str(content["executor"])
32
+ target = str(content["target"])
33
+ payload = content.get("payload", {})
34
+ cap_token = content.get("capability")
35
+ risk_level = str(content.get("risk_level", "medium"))
36
+
37
+ if not cap_token:
38
+ return {
39
+ "type": "action_denied",
40
+ "request_id": msg.id,
41
+ "reason": "Missing execute capability token",
42
+ }
43
+
44
+ if not capabilities.validate(system_id, cap_token, executor, "execute"):
45
+ return {
46
+ "type": "action_denied",
47
+ "request_id": msg.id,
48
+ "reason": "Invalid or expired capability token",
49
+ }
50
+
51
+ decision = await policy.evaluate_action(
52
+ system_id=system_id,
53
+ action=action,
54
+ executor=executor,
55
+ target=target,
56
+ payload=payload,
57
+ risk_level=risk_level,
58
+ )
59
+ if decision.escalate:
60
+ return {
61
+ "type": "action_escalated",
62
+ "request_id": msg.id,
63
+ "reason": decision.reason,
64
+ "escalated_to": decision.escalate_to,
65
+ }
66
+ if not decision.allowed:
67
+ return {
68
+ "type": "action_denied",
69
+ "request_id": msg.id,
70
+ "reason": decision.reason,
71
+ }
72
+ return {
73
+ "type": "action_approved",
74
+ "request_id": msg.id,
75
+ "executor": executor,
76
+ "modified_payload": decision.modified_payload or payload,
77
+ }
aaax/bootstrap.py ADDED
@@ -0,0 +1,13 @@
1
+ from __future__ import annotations
2
+
3
+ from aaax.config import AAAXConfig
4
+ from aaax.kernel import AAAXKernel
5
+
6
+
7
+ async def bootstrap_kernel(config: AAAXConfig, *, start_channels: bool = False) -> AAAXKernel:
8
+ kernel = AAAXKernel(config)
9
+ await kernel.setup()
10
+ kernel._setup_done = True
11
+ if start_channels:
12
+ await kernel.start_owned_channels()
13
+ return kernel
aaax/capability.py ADDED
@@ -0,0 +1,125 @@
1
+ from __future__ import annotations
2
+
3
+ import time
4
+ import uuid
5
+ from dataclasses import dataclass, field
6
+ from typing import Any
7
+
8
+ from aaax.policy import PolicyEngine
9
+
10
+ ACCESS_LEVELS = {"read": 0, "write": 1, "execute": 2}
11
+
12
+
13
+ def _message_content_data(msg) -> dict[str, Any]:
14
+ content = getattr(msg, "content", None)
15
+ data = getattr(content, "data", None)
16
+ return data if isinstance(data, dict) else {}
17
+
18
+
19
+ def _requester_id(msg, payload: dict[str, Any]) -> str:
20
+ return str(payload.get("from") or payload.get("system_id") or msg.sender_id)
21
+
22
+
23
+ @dataclass(slots=True)
24
+ class Capability:
25
+ token: str
26
+ system_id: str
27
+ resource: str
28
+ access: str
29
+ issued_at: float
30
+ expires_at: float
31
+ scope: dict[str, Any] = field(default_factory=dict)
32
+
33
+
34
+ class CapabilityManager:
35
+ """AAAX-local capability tokens for mediated resources."""
36
+
37
+ def __init__(self) -> None:
38
+ self._capabilities: dict[str, Capability] = {}
39
+ self._by_system: dict[str, set[str]] = {}
40
+
41
+ async def process_request(self, msg, policy: PolicyEngine) -> dict[str, Any]:
42
+ content = _message_content_data(msg)
43
+ system_id = _requester_id(msg, content)
44
+ resource = str(content["resource"])
45
+ access = str(content["access"])
46
+ scope = content.get("scope", {})
47
+ context = content.get("context", {})
48
+
49
+ decision = await policy.evaluate_capability(
50
+ system_id=system_id,
51
+ resource=resource,
52
+ access=access,
53
+ context=context,
54
+ )
55
+ if not decision.allowed:
56
+ return {
57
+ "type": "capability_deny",
58
+ "resource": resource,
59
+ "reason": decision.reason,
60
+ }
61
+
62
+ return await self.issue(
63
+ system_id=system_id,
64
+ resource=resource,
65
+ access=access,
66
+ scope=scope,
67
+ )
68
+
69
+ async def issue(
70
+ self,
71
+ system_id: str,
72
+ resource: str,
73
+ access: str,
74
+ scope: dict[str, Any] | None = None,
75
+ ) -> dict[str, Any]:
76
+ scope = scope or {}
77
+ ttl = float(scope.get("ttl", 3600.0))
78
+ token = uuid.uuid4().hex
79
+ now = time.time()
80
+ capability = Capability(
81
+ token=token,
82
+ system_id=system_id,
83
+ resource=resource,
84
+ access=access,
85
+ issued_at=now,
86
+ expires_at=now + ttl,
87
+ scope=scope,
88
+ )
89
+ self._capabilities[token] = capability
90
+ self._by_system.setdefault(system_id, set()).add(token)
91
+ return {
92
+ "type": "capability_grant",
93
+ "resource": resource,
94
+ "token": token,
95
+ "expires": capability.expires_at,
96
+ }
97
+
98
+ def validate(self, system_id: str, token: str, resource: str, access: str) -> bool:
99
+ capability = self._capabilities.get(token)
100
+ if capability is None:
101
+ return False
102
+ if capability.expires_at < time.time():
103
+ self._capabilities.pop(token, None)
104
+ self._by_system.get(capability.system_id, set()).discard(token)
105
+ return False
106
+ if capability.system_id != system_id:
107
+ return False
108
+ if capability.resource != resource:
109
+ return False
110
+ return ACCESS_LEVELS.get(capability.access, -1) >= ACCESS_LEVELS.get(access, 0)
111
+
112
+ def revoke_all(self, system_id: str) -> None:
113
+ tokens = self._by_system.pop(system_id, set())
114
+ for token in tokens:
115
+ self._capabilities.pop(token, None)
116
+
117
+ def expire_stale(self) -> None:
118
+ now = time.time()
119
+ expired = [token for token, cap in self._capabilities.items() if cap.expires_at < now]
120
+ for token in expired:
121
+ cap = self._capabilities.pop(token)
122
+ self._by_system.get(cap.system_id, set()).discard(token)
123
+
124
+ def active_count(self) -> int:
125
+ return len(self._capabilities)
aaax/cli.py ADDED
@@ -0,0 +1,13 @@
1
+ import click
2
+
3
+ from aaax.cli_kernel import launch, modules
4
+
5
+
6
+ @click.group()
7
+ @click.version_option(package_name="aaax")
8
+ def main() -> None:
9
+ """AAAX CLI."""
10
+
11
+
12
+ main.add_command(launch)
13
+ main.add_command(modules)
aaax/cli_kernel.py ADDED
@@ -0,0 +1,71 @@
1
+ from __future__ import annotations
2
+
3
+ import asyncio
4
+
5
+ import click
6
+
7
+ from aaax.bootstrap import bootstrap_kernel
8
+ from aaax.config import AAAXConfig
9
+
10
+
11
+ def _print_kernel_snapshot(kernel, *, host: str | None = None, port: int | None = None) -> None:
12
+ click.echo(f"kernel_id={kernel.id}")
13
+ click.echo(f"docked_systems={kernel._constellation.system_ids()}")
14
+ click.echo("channels:")
15
+ for channel in kernel.all_channels:
16
+ click.echo(f" - {channel.id}")
17
+ if host is not None and port is not None:
18
+ click.echo(f"http_transport=http://{host}:{port} (PUBLIC channels only)")
19
+
20
+
21
+ @click.command()
22
+ @click.argument("config_path", type=click.Path(exists=True, dir_okay=False))
23
+ @click.option("--publish", is_flag=True, help="Publish public channels over HTTP.")
24
+ @click.option(
25
+ "--once",
26
+ is_flag=True,
27
+ help="Bootstrap the kernel, run one step, print a summary, and exit.",
28
+ )
29
+ def launch(config_path: str, publish: bool, once: bool) -> None:
30
+ """Launch an AAAX kernel from a TOML config."""
31
+
32
+ if publish and once:
33
+ raise click.UsageError("--once cannot be combined with --publish.")
34
+
35
+ async def _run() -> None:
36
+ config = AAAXConfig.from_file(config_path)
37
+ kernel = await bootstrap_kernel(config, start_channels=once)
38
+ if once:
39
+ await kernel.step()
40
+ _print_kernel_snapshot(kernel)
41
+ return
42
+
43
+ click.echo(f"Starting AAAX runtime for '{config.name}' ({kernel.id}).")
44
+ if publish:
45
+ _print_kernel_snapshot(
46
+ kernel,
47
+ host=config.network.host,
48
+ port=config.network.port,
49
+ )
50
+ click.echo("Press Ctrl+C to stop.")
51
+ await kernel.publish(host=config.network.host, port=config.network.port)
52
+ else:
53
+ _print_kernel_snapshot(kernel)
54
+ click.echo("Press Ctrl+C to stop.")
55
+ await kernel.launch()
56
+
57
+ try:
58
+ asyncio.run(_run())
59
+ except KeyboardInterrupt:
60
+ click.echo("\nStopped AAAX runtime.")
61
+
62
+
63
+ @click.group()
64
+ def modules() -> None:
65
+ """Module management commands."""
66
+
67
+
68
+ @modules.command("list")
69
+ def list_modules() -> None:
70
+ """Placeholder until persistent module registry commands are implemented."""
71
+ click.echo("Module registry commands require a running kernel instance.")
aaax/config.py ADDED
@@ -0,0 +1,52 @@
1
+ from __future__ import annotations
2
+
3
+ from pathlib import Path
4
+ from typing import Any
5
+
6
+ from pydantic import BaseModel, Field
7
+
8
+
9
+ def _load_toml(path: str | Path) -> dict[str, Any]:
10
+ try:
11
+ import tomllib # type: ignore[attr-defined]
12
+ except ModuleNotFoundError:
13
+ import tomli as tomllib # type: ignore[no-redef]
14
+
15
+ with open(path, "rb") as handle:
16
+ return tomllib.load(handle)
17
+
18
+
19
+ class NetworkConfig(BaseModel):
20
+ publish: bool = False
21
+ host: str = "0.0.0.0"
22
+ port: int = 8100
23
+
24
+
25
+ class LibOSConfig(BaseModel):
26
+ name: str = "lllm"
27
+ strict_boot: bool = True
28
+ discover_shared_packages: bool = False
29
+
30
+
31
+ class ModuleConfig(BaseModel):
32
+ id: str
33
+ framework: str = "lllm"
34
+ lllm_toml: str | None = None
35
+ channels: list[str] = Field(default_factory=list)
36
+ executors: list[str] = Field(default_factory=list)
37
+ remote_channels: list[str] = Field(default_factory=list)
38
+ manifest: dict[str, Any] | None = None
39
+
40
+
41
+ class AAAXConfig(BaseModel):
42
+ id: str = "aaax-main"
43
+ name: str = "AAAX Kernel"
44
+ policy: str | dict[str, Any] | None = "default"
45
+ libos: LibOSConfig = Field(default_factory=LibOSConfig)
46
+ modules: list[ModuleConfig] = Field(default_factory=list)
47
+ network: NetworkConfig = Field(default_factory=NetworkConfig)
48
+
49
+ @classmethod
50
+ def from_file(cls, path: str | Path) -> "AAAXConfig":
51
+ raw = _load_toml(path)
52
+ return cls(**raw.get("aaax", {}))
aaax/constellation.py ADDED
@@ -0,0 +1,84 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass, field
4
+
5
+ from aaax._vendor import ensure_vendor_paths
6
+
7
+ ensure_vendor_paths()
8
+
9
+ from sssn.core.channel import BaseChannel
10
+ from sssn.core.system import BaseSystem
11
+
12
+
13
+ @dataclass(slots=True)
14
+ class DockRecord:
15
+ system_id: str
16
+ system: BaseSystem
17
+ granted_channels: set[str] = field(default_factory=set)
18
+ provided_channels: set[str] = field(default_factory=set)
19
+ privileged: bool = False
20
+ status: str = "docked"
21
+
22
+
23
+ class ConstellationManager:
24
+ def __init__(self) -> None:
25
+ self._systems: dict[str, DockRecord] = {}
26
+ self._channels: dict[str, BaseChannel] = {}
27
+
28
+ def register(
29
+ self,
30
+ system: BaseSystem,
31
+ channels: list[str] | None = None,
32
+ *,
33
+ privileged: bool = False,
34
+ ) -> DockRecord:
35
+ if system.id in self._systems:
36
+ raise ValueError(f"System '{system.id}' is already docked.")
37
+
38
+ provided_channels: set[str] = set()
39
+ for channel in system.all_channels:
40
+ existing = self._channels.get(channel.id)
41
+ if existing is not None and existing is not channel:
42
+ raise ValueError(f"Channel '{channel.id}' already registered by another system.")
43
+ self._channels[channel.id] = channel
44
+ provided_channels.add(channel.id)
45
+
46
+ record = DockRecord(
47
+ system_id=system.id,
48
+ system=system,
49
+ granted_channels=set(channels or []),
50
+ provided_channels=provided_channels,
51
+ privileged=privileged,
52
+ )
53
+ self._systems[system.id] = record
54
+ return record
55
+
56
+ def unregister(self, system_id: str) -> DockRecord | None:
57
+ record = self._systems.pop(system_id, None)
58
+ if record is None:
59
+ return None
60
+ for channel_id in record.provided_channels:
61
+ channel = self._channels.get(channel_id)
62
+ if channel is not None and channel in record.system.all_channels:
63
+ self._channels.pop(channel_id, None)
64
+ return record
65
+
66
+ def get(self, system_id: str) -> DockRecord | None:
67
+ return self._systems.get(system_id)
68
+
69
+ def set_status(self, system_id: str, status: str) -> None:
70
+ record = self._systems.get(system_id)
71
+ if record is not None:
72
+ record.status = status
73
+
74
+ def resolve_channel(self, channel_id: str) -> BaseChannel | None:
75
+ return self._channels.get(channel_id)
76
+
77
+ def systems(self) -> list[DockRecord]:
78
+ return list(self._systems.values())
79
+
80
+ def system_ids(self) -> list[str]:
81
+ return sorted(self._systems.keys())
82
+
83
+ def active_count(self) -> int:
84
+ return len(self._systems)