flakepl 0.3.1__tar.gz
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.
- flakepl-0.3.1/PKG-INFO +126 -0
- flakepl-0.3.1/README.md +108 -0
- flakepl-0.3.1/pyproject.toml +44 -0
- flakepl-0.3.1/setup.cfg +4 -0
- flakepl-0.3.1/src/flake/__init__.py +102 -0
- flakepl-0.3.1/src/flake/actions.py +41 -0
- flakepl-0.3.1/src/flake/agent.py +107 -0
- flakepl-0.3.1/src/flake/dynamic.py +449 -0
- flakepl-0.3.1/src/flake/epistemic.py +2068 -0
- flakepl-0.3.1/src/flake/execution.py +892 -0
- flakepl-0.3.1/src/flake/explorer.py +196 -0
- flakepl-0.3.1/src/flake/formula.py +173 -0
- flakepl-0.3.1/src/flake/observation.py +500 -0
- flakepl-0.3.1/src/flake/process.py +342 -0
- flakepl-0.3.1/src/flake/propositions.py +46 -0
- flakepl-0.3.1/src/flake/py.typed +0 -0
- flakepl-0.3.1/src/flake/runtime.py +370 -0
- flakepl-0.3.1/src/flake/semantics.py +222 -0
- flakepl-0.3.1/src/flake/sos.py +97 -0
- flakepl-0.3.1/src/flake/temporal.py +109 -0
- flakepl-0.3.1/src/flake/verify.py +1081 -0
- flakepl-0.3.1/src/flakepl/__init__.py +8 -0
- flakepl-0.3.1/src/flakepl/_api.py +29 -0
- flakepl-0.3.1/src/flakepl/agent.py +9 -0
- flakepl-0.3.1/src/flakepl/explorer.py +19 -0
- flakepl-0.3.1/src/flakepl/process.py +31 -0
- flakepl-0.3.1/src/flakepl/py.typed +0 -0
- flakepl-0.3.1/src/flakepl/runtime.py +20 -0
- flakepl-0.3.1/src/flakepl/semantics.py +7 -0
- flakepl-0.3.1/src/flakepl/sos.py +5 -0
- flakepl-0.3.1/src/flakepl/verify.py +29 -0
- flakepl-0.3.1/src/flakepl.egg-info/PKG-INFO +126 -0
- flakepl-0.3.1/src/flakepl.egg-info/SOURCES.txt +51 -0
- flakepl-0.3.1/src/flakepl.egg-info/dependency_links.txt +1 -0
- flakepl-0.3.1/src/flakepl.egg-info/top_level.txt +2 -0
- flakepl-0.3.1/tests/test_action_model.py +377 -0
- flakepl-0.3.1/tests/test_dynamic.py +342 -0
- flakepl-0.3.1/tests/test_epistemic.py +171 -0
- flakepl-0.3.1/tests/test_epistemic_groups.py +223 -0
- flakepl-0.3.1/tests/test_epistemic_uncertainty.py +176 -0
- flakepl-0.3.1/tests/test_examples.py +59 -0
- flakepl-0.3.1/tests/test_execution_epistemics.py +395 -0
- flakepl-0.3.1/tests/test_flakepl_namespace.py +59 -0
- flakepl-0.3.1/tests/test_observation_builder.py +189 -0
- flakepl-0.3.1/tests/test_process_chaining.py +147 -0
- flakepl-0.3.1/tests/test_public_sos_api.py +14 -0
- flakepl-0.3.1/tests/test_runtime.py +153 -0
- flakepl-0.3.1/tests/test_runtime_propositions.py +132 -0
- flakepl-0.3.1/tests/test_sos.py +49 -0
- flakepl-0.3.1/tests/test_state_space_epistemic.py +120 -0
- flakepl-0.3.1/tests/test_temporal.py +313 -0
- flakepl-0.3.1/tests/test_verification.py +522 -0
- flakepl-0.3.1/tests/test_verification_counterexamples.py +397 -0
flakepl-0.3.1/PKG-INFO
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: flakepl
|
|
3
|
+
Version: 0.3.1
|
|
4
|
+
Summary: FlakePL – a Python framework for executable multi-agent process and epistemic models
|
|
5
|
+
Author: Elisson
|
|
6
|
+
Keywords: multi-agent systems,epistemic logic,process calculus,process algebra,formal verification,AI agents,temporal logic,dynamic epistemic logic
|
|
7
|
+
Classifier: Development Status :: 3 - Alpha
|
|
8
|
+
Classifier: Intended Audience :: Developers
|
|
9
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
10
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Requires-Python: >=3.11
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
|
|
19
|
+
# FlakePL
|
|
20
|
+
|
|
21
|
+
FlakePL is a small Python library for modeling and exploring finite multi-agent systems with process semantics, epistemic logic, temporal properties, dynamic epistemic updates, and executable protocol transitions.
|
|
22
|
+
|
|
23
|
+
The current goal is deliberately modest: provide a clean, testable MVP library. A dedicated FlakePL programming language is a later stage and is not part of the current release.
|
|
24
|
+
|
|
25
|
+
## MVP capabilities
|
|
26
|
+
|
|
27
|
+
- process algebra: `Nil`, `Prefix`, `Choice`, `Parallel`
|
|
28
|
+
- actions: `Tau`, `Send`, `Receive`
|
|
29
|
+
- executable system configurations and immutable agent state
|
|
30
|
+
- finite state-space exploration
|
|
31
|
+
- observations and epistemic relations
|
|
32
|
+
- `K`, `E`, `D`, `C` knowledge operators
|
|
33
|
+
- boolean formulas
|
|
34
|
+
- temporal operators `X`, `F`, `G`, `U`
|
|
35
|
+
- public announcements and action-model product updates
|
|
36
|
+
- process-aware epistemic execution
|
|
37
|
+
- counterexample traces for temporal verification
|
|
38
|
+
|
|
39
|
+
## Installation
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
python -m pip install flakepl
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
The public API is:
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
from flakepl import ...
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The old `flake` namespace remains available temporarily for compatibility with the prototype.
|
|
52
|
+
|
|
53
|
+
## Quick example
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
from flakepl import Agent, Configuration, GlobalState, explore, recv, send, stop
|
|
57
|
+
|
|
58
|
+
alice = Agent.create(
|
|
59
|
+
"alice",
|
|
60
|
+
send("channel", "secret") >> stop(),
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
bob = Agent.create(
|
|
64
|
+
"bob",
|
|
65
|
+
recv("channel", "value") >> stop(),
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
initial = Configuration(
|
|
69
|
+
state=GlobalState(),
|
|
70
|
+
agents=(alice, bob),
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
space = explore(initial)
|
|
74
|
+
|
|
75
|
+
print("states:", len(space.states))
|
|
76
|
+
print("transitions:", len(space.transitions))
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Epistemic model
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
from flakepl import Atom, EpistemicModel, K, observe_local_state
|
|
83
|
+
|
|
84
|
+
model = EpistemicModel.from_state_space(
|
|
85
|
+
space,
|
|
86
|
+
observations={
|
|
87
|
+
"alice": observe_local_state(),
|
|
88
|
+
"bob": observe_local_state(),
|
|
89
|
+
},
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
# Evaluate a registered proposition with model.check(...).
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
See `examples/` for complete runnable programs, including a two-phase-commit verification example.
|
|
96
|
+
|
|
97
|
+
## Development
|
|
98
|
+
|
|
99
|
+
Run the full test suite:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
python -m pytest -q
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Compile all sources:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
python -m compileall -q src tests
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Project layout
|
|
112
|
+
|
|
113
|
+
```text
|
|
114
|
+
src/flake/ implementation and legacy compatibility API
|
|
115
|
+
src/flakepl/ public FlakePL API
|
|
116
|
+
examples/ runnable MVP examples
|
|
117
|
+
tests/ unit, semantic, integration, and example tests
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Status
|
|
121
|
+
|
|
122
|
+
FlakePL is alpha software. The MVP API is intentionally small and may evolve before 1.0.
|
|
123
|
+
|
|
124
|
+
## License
|
|
125
|
+
|
|
126
|
+
The repository license will be added before the first public release.
|
flakepl-0.3.1/README.md
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# FlakePL
|
|
2
|
+
|
|
3
|
+
FlakePL is a small Python library for modeling and exploring finite multi-agent systems with process semantics, epistemic logic, temporal properties, dynamic epistemic updates, and executable protocol transitions.
|
|
4
|
+
|
|
5
|
+
The current goal is deliberately modest: provide a clean, testable MVP library. A dedicated FlakePL programming language is a later stage and is not part of the current release.
|
|
6
|
+
|
|
7
|
+
## MVP capabilities
|
|
8
|
+
|
|
9
|
+
- process algebra: `Nil`, `Prefix`, `Choice`, `Parallel`
|
|
10
|
+
- actions: `Tau`, `Send`, `Receive`
|
|
11
|
+
- executable system configurations and immutable agent state
|
|
12
|
+
- finite state-space exploration
|
|
13
|
+
- observations and epistemic relations
|
|
14
|
+
- `K`, `E`, `D`, `C` knowledge operators
|
|
15
|
+
- boolean formulas
|
|
16
|
+
- temporal operators `X`, `F`, `G`, `U`
|
|
17
|
+
- public announcements and action-model product updates
|
|
18
|
+
- process-aware epistemic execution
|
|
19
|
+
- counterexample traces for temporal verification
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
python -m pip install flakepl
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The public API is:
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
from flakepl import ...
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The old `flake` namespace remains available temporarily for compatibility with the prototype.
|
|
34
|
+
|
|
35
|
+
## Quick example
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
from flakepl import Agent, Configuration, GlobalState, explore, recv, send, stop
|
|
39
|
+
|
|
40
|
+
alice = Agent.create(
|
|
41
|
+
"alice",
|
|
42
|
+
send("channel", "secret") >> stop(),
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
bob = Agent.create(
|
|
46
|
+
"bob",
|
|
47
|
+
recv("channel", "value") >> stop(),
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
initial = Configuration(
|
|
51
|
+
state=GlobalState(),
|
|
52
|
+
agents=(alice, bob),
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
space = explore(initial)
|
|
56
|
+
|
|
57
|
+
print("states:", len(space.states))
|
|
58
|
+
print("transitions:", len(space.transitions))
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Epistemic model
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
from flakepl import Atom, EpistemicModel, K, observe_local_state
|
|
65
|
+
|
|
66
|
+
model = EpistemicModel.from_state_space(
|
|
67
|
+
space,
|
|
68
|
+
observations={
|
|
69
|
+
"alice": observe_local_state(),
|
|
70
|
+
"bob": observe_local_state(),
|
|
71
|
+
},
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
# Evaluate a registered proposition with model.check(...).
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
See `examples/` for complete runnable programs, including a two-phase-commit verification example.
|
|
78
|
+
|
|
79
|
+
## Development
|
|
80
|
+
|
|
81
|
+
Run the full test suite:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
python -m pytest -q
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Compile all sources:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
python -m compileall -q src tests
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Project layout
|
|
94
|
+
|
|
95
|
+
```text
|
|
96
|
+
src/flake/ implementation and legacy compatibility API
|
|
97
|
+
src/flakepl/ public FlakePL API
|
|
98
|
+
examples/ runnable MVP examples
|
|
99
|
+
tests/ unit, semantic, integration, and example tests
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Status
|
|
103
|
+
|
|
104
|
+
FlakePL is alpha software. The MVP API is intentionally small and may evolve before 1.0.
|
|
105
|
+
|
|
106
|
+
## License
|
|
107
|
+
|
|
108
|
+
The repository license will be added before the first public release.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "flakepl"
|
|
7
|
+
version = "0.3.1"
|
|
8
|
+
description = "FlakePL – a Python framework for executable multi-agent process and epistemic models"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
dependencies = []
|
|
12
|
+
|
|
13
|
+
authors = [
|
|
14
|
+
{ name = "Elisson" }
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
keywords = [
|
|
18
|
+
"multi-agent systems",
|
|
19
|
+
"epistemic logic",
|
|
20
|
+
"process calculus",
|
|
21
|
+
"process algebra",
|
|
22
|
+
"formal verification",
|
|
23
|
+
"AI agents",
|
|
24
|
+
"temporal logic",
|
|
25
|
+
"dynamic epistemic logic",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
classifiers = [
|
|
29
|
+
"Development Status :: 3 - Alpha",
|
|
30
|
+
"Intended Audience :: Developers",
|
|
31
|
+
"Topic :: Software Development :: Libraries",
|
|
32
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
33
|
+
"Programming Language :: Python :: 3",
|
|
34
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
35
|
+
"Programming Language :: Python :: 3.11",
|
|
36
|
+
"Programming Language :: Python :: 3.12",
|
|
37
|
+
"Programming Language :: Python :: 3.13",
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
[tool.setuptools]
|
|
41
|
+
package-dir = {"" = "src"}
|
|
42
|
+
|
|
43
|
+
[tool.setuptools.packages.find]
|
|
44
|
+
where = ["src"]
|
flakepl-0.3.1/setup.cfg
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
from .actions import Action, Receive, Send, Tau
|
|
2
|
+
from .agent import Agent
|
|
3
|
+
from .dynamic import (
|
|
4
|
+
ActionEvent,
|
|
5
|
+
ActionModel,
|
|
6
|
+
DynamicEvent,
|
|
7
|
+
PublicAnnouncement,
|
|
8
|
+
action_event,
|
|
9
|
+
announce,
|
|
10
|
+
event,
|
|
11
|
+
product_update,
|
|
12
|
+
public_announcement,
|
|
13
|
+
)
|
|
14
|
+
from .epistemic import (
|
|
15
|
+
CommonKnowledge,
|
|
16
|
+
DistributedKnowledge,
|
|
17
|
+
EpistemicModel,
|
|
18
|
+
EveryoneKnows,
|
|
19
|
+
Knowledge,
|
|
20
|
+
ProductWorld,
|
|
21
|
+
World,
|
|
22
|
+
C,
|
|
23
|
+
D,
|
|
24
|
+
E,
|
|
25
|
+
K,
|
|
26
|
+
)
|
|
27
|
+
from .explorer import StateSpace, explore, explore_many, explore_many_with, explore_with
|
|
28
|
+
from .execution import (
|
|
29
|
+
ActionObservation,
|
|
30
|
+
BlindActionObservation,
|
|
31
|
+
ProcessExecutionEvent,
|
|
32
|
+
TransitionObservation,
|
|
33
|
+
blind_action,
|
|
34
|
+
execute,
|
|
35
|
+
execute_transition,
|
|
36
|
+
observe_action,
|
|
37
|
+
step,
|
|
38
|
+
)
|
|
39
|
+
from .formula import And, Atom, Formula, Not, Or, iff, implies
|
|
40
|
+
from .observation import (
|
|
41
|
+
GlobalObservation,
|
|
42
|
+
LocalObservation,
|
|
43
|
+
ObservationBuilder,
|
|
44
|
+
global_,
|
|
45
|
+
local,
|
|
46
|
+
observe_global,
|
|
47
|
+
observe_local_process,
|
|
48
|
+
observe_local_state,
|
|
49
|
+
public,
|
|
50
|
+
same_observation,
|
|
51
|
+
)
|
|
52
|
+
from .process import Choice, Nil, Parallel, Prefix, Process, choice, parallel, recv, send, stop, tau
|
|
53
|
+
from .propositions import Proposition
|
|
54
|
+
from .runtime import Configuration, GlobalState, SystemTransition
|
|
55
|
+
from .semantics import synchronous_system_transitions
|
|
56
|
+
from .sos import Transition, transitions
|
|
57
|
+
from .temporal import Always, Eventually, Next, Until, F, G, U, X
|
|
58
|
+
from .verify import (
|
|
59
|
+
Trace,
|
|
60
|
+
VerificationResult,
|
|
61
|
+
find_always_counterexample,
|
|
62
|
+
find_eventually_counterexample,
|
|
63
|
+
find_next_counterexample,
|
|
64
|
+
find_path_to,
|
|
65
|
+
find_state_counterexample,
|
|
66
|
+
format_trace,
|
|
67
|
+
format_verification,
|
|
68
|
+
verify,
|
|
69
|
+
verify_always,
|
|
70
|
+
verify_eventually,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
# Backward-compatible system-level name.
|
|
74
|
+
system_transitions = synchronous_system_transitions
|
|
75
|
+
|
|
76
|
+
__all__ = [
|
|
77
|
+
"Action", "Tau", "Send", "Receive",
|
|
78
|
+
"Agent",
|
|
79
|
+
"Process", "Nil", "Prefix", "Choice", "Parallel",
|
|
80
|
+
"stop", "send", "recv", "tau", "choice", "parallel",
|
|
81
|
+
"GlobalState", "Configuration", "SystemTransition",
|
|
82
|
+
"Proposition",
|
|
83
|
+
"Transition", "transitions",
|
|
84
|
+
"StateSpace", "explore", "explore_many", "explore_with", "explore_many_with",
|
|
85
|
+
"system_transitions", "synchronous_system_transitions",
|
|
86
|
+
"LocalObservation", "GlobalObservation", "ObservationBuilder",
|
|
87
|
+
"local", "global_", "public", "observe_global", "observe_local_state",
|
|
88
|
+
"observe_local_process", "same_observation",
|
|
89
|
+
"Formula", "Atom", "Not", "And", "Or", "implies", "iff",
|
|
90
|
+
"World", "ProductWorld", "EpistemicModel",
|
|
91
|
+
"Knowledge", "EveryoneKnows", "DistributedKnowledge", "CommonKnowledge",
|
|
92
|
+
"K", "E", "D", "C",
|
|
93
|
+
"Next", "Eventually", "Always", "Until", "X", "F", "G", "U",
|
|
94
|
+
"DynamicEvent", "PublicAnnouncement", "ActionEvent", "ActionModel",
|
|
95
|
+
"announce", "public_announcement", "event", "action_event", "product_update",
|
|
96
|
+
"TransitionObservation", "ActionObservation", "BlindActionObservation",
|
|
97
|
+
"ProcessExecutionEvent", "observe_action", "blind_action", "execute_transition",
|
|
98
|
+
"execute", "step",
|
|
99
|
+
"Trace", "VerificationResult", "find_path_to", "find_state_counterexample",
|
|
100
|
+
"find_next_counterexample", "find_always_counterexample", "find_eventually_counterexample",
|
|
101
|
+
"verify_always", "verify_eventually", "verify", "format_trace", "format_verification",
|
|
102
|
+
]
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass(frozen=True, slots=True)
|
|
8
|
+
class Tau:
|
|
9
|
+
"""
|
|
10
|
+
Internal action.
|
|
11
|
+
|
|
12
|
+
Represents:
|
|
13
|
+
τ
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass(frozen=True, slots=True)
|
|
18
|
+
class Send:
|
|
19
|
+
"""
|
|
20
|
+
Output action:
|
|
21
|
+
|
|
22
|
+
channel!value
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
channel: str
|
|
26
|
+
value: Any
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@dataclass(frozen=True, slots=True)
|
|
30
|
+
class Receive:
|
|
31
|
+
"""
|
|
32
|
+
Input action:
|
|
33
|
+
|
|
34
|
+
channel?variable
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
channel: str
|
|
38
|
+
variable: str
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
Action = Tau | Send | Receive
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from .process import Process
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@dataclass(frozen=True, slots=True)
|
|
10
|
+
class Agent:
|
|
11
|
+
"""
|
|
12
|
+
Runtime agent.
|
|
13
|
+
|
|
14
|
+
Agent identity is its logical name.
|
|
15
|
+
|
|
16
|
+
Runtime state consists of:
|
|
17
|
+
|
|
18
|
+
process
|
|
19
|
+
local state
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
name: str
|
|
23
|
+
process: Process
|
|
24
|
+
state: tuple[tuple[str, Any], ...] = ()
|
|
25
|
+
|
|
26
|
+
@classmethod
|
|
27
|
+
def create(
|
|
28
|
+
cls,
|
|
29
|
+
name: str,
|
|
30
|
+
process: Process,
|
|
31
|
+
state: dict[str, Any] | None = None,
|
|
32
|
+
) -> Agent:
|
|
33
|
+
|
|
34
|
+
if not name:
|
|
35
|
+
raise ValueError(
|
|
36
|
+
"Agent name cannot be empty"
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
if state is None:
|
|
40
|
+
state = {}
|
|
41
|
+
|
|
42
|
+
return cls(
|
|
43
|
+
name=name,
|
|
44
|
+
process=process,
|
|
45
|
+
state=tuple(
|
|
46
|
+
sorted(
|
|
47
|
+
state.items(),
|
|
48
|
+
key=lambda item: item[0],
|
|
49
|
+
)
|
|
50
|
+
),
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
def get_state(
|
|
54
|
+
self,
|
|
55
|
+
key: str,
|
|
56
|
+
default: Any = None,
|
|
57
|
+
) -> Any:
|
|
58
|
+
"""
|
|
59
|
+
Read one local state variable.
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
return dict(
|
|
63
|
+
self.state
|
|
64
|
+
).get(
|
|
65
|
+
key,
|
|
66
|
+
default,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
def with_state(
|
|
70
|
+
self,
|
|
71
|
+
key: str,
|
|
72
|
+
value: Any,
|
|
73
|
+
) -> Agent:
|
|
74
|
+
"""
|
|
75
|
+
Return a new agent with updated local state.
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
state = dict(
|
|
79
|
+
self.state
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
state[key] = value
|
|
83
|
+
|
|
84
|
+
return Agent(
|
|
85
|
+
name=self.name,
|
|
86
|
+
process=self.process,
|
|
87
|
+
state=tuple(
|
|
88
|
+
sorted(
|
|
89
|
+
state.items(),
|
|
90
|
+
key=lambda item: item[0],
|
|
91
|
+
)
|
|
92
|
+
),
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
def with_process(
|
|
96
|
+
self,
|
|
97
|
+
process: Process,
|
|
98
|
+
) -> Agent:
|
|
99
|
+
"""
|
|
100
|
+
Return a new agent with updated process.
|
|
101
|
+
"""
|
|
102
|
+
|
|
103
|
+
return Agent(
|
|
104
|
+
name=self.name,
|
|
105
|
+
process=process,
|
|
106
|
+
state=self.state,
|
|
107
|
+
)
|