academy-dashboard 0.1.0__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.
Files changed (44) hide show
  1. academy_dashboard-0.1.0/.github/workflows/publish.yml +107 -0
  2. academy_dashboard-0.1.0/.pre-commit-config.yaml +34 -0
  3. academy_dashboard-0.1.0/LICENSE +21 -0
  4. academy_dashboard-0.1.0/PKG-INFO +115 -0
  5. academy_dashboard-0.1.0/README.md +68 -0
  6. academy_dashboard-0.1.0/TODO.md +64 -0
  7. academy_dashboard-0.1.0/academy_dashboard/__init__.py +11 -0
  8. academy_dashboard-0.1.0/academy_dashboard/agents/__init__.py +6 -0
  9. academy_dashboard-0.1.0/academy_dashboard/agents/sleeper.py +28 -0
  10. academy_dashboard-0.1.0/academy_dashboard/agents/spinner.py +52 -0
  11. academy_dashboard-0.1.0/academy_dashboard/monitored_agent.py +215 -0
  12. academy_dashboard-0.1.0/academy_dashboard/user_agent/__init__.py +7 -0
  13. academy_dashboard-0.1.0/academy_dashboard/user_agent/assets/AS1224 University of Illinois.png +0 -0
  14. academy_dashboard-0.1.0/academy_dashboard/user_agent/assets/AS160 The University of Chicago.svg +247 -0
  15. academy_dashboard-0.1.0/academy_dashboard/user_agent/assets/AS2936 National Energy Research Scientific Computing Center.svg +801 -0
  16. academy_dashboard-0.1.0/academy_dashboard/user_agent/assets/AS32093 University of Texas at Austin.svg +1 -0
  17. academy_dashboard-0.1.0/academy_dashboard/user_agent/assets/AS3671 SLAC National Accelerator Laboratory.svg +163 -0
  18. academy_dashboard-0.1.0/academy_dashboard/user_agent/assets/AS397511 Purdue University.svg +7 -0
  19. academy_dashboard-0.1.0/academy_dashboard/user_agent/assets/AS683 Argonne National Laboratory.png +0 -0
  20. academy_dashboard-0.1.0/academy_dashboard/user_agent/assets/Ames National Laboratory.svg +1 -0
  21. academy_dashboard-0.1.0/academy_dashboard/user_agent/assets/Globus_logo_WHITE_square.png +0 -0
  22. academy_dashboard-0.1.0/academy_dashboard/user_agent/assets/ai_eye.html +123 -0
  23. academy_dashboard-0.1.0/academy_dashboard/user_agent/assets/logo-Academy-2025-200x200-dark-bg.png +0 -0
  24. academy_dashboard-0.1.0/academy_dashboard/user_agent/assets/logo.svg +56 -0
  25. academy_dashboard-0.1.0/academy_dashboard/user_agent/assets/logo_dark.svg +56 -0
  26. academy_dashboard-0.1.0/academy_dashboard/user_agent/dashboard.py +297 -0
  27. academy_dashboard-0.1.0/academy_dashboard/user_agent/message.py +58 -0
  28. academy_dashboard-0.1.0/academy_dashboard/user_agent/user_agent.py +113 -0
  29. academy_dashboard-0.1.0/academy_dashboard/user_agent/web_elements.py +1055 -0
  30. academy_dashboard-0.1.0/academy_dashboard/user_agent_launcher.py +125 -0
  31. academy_dashboard-0.1.0/academy_dashboard.egg-info/PKG-INFO +115 -0
  32. academy_dashboard-0.1.0/academy_dashboard.egg-info/SOURCES.txt +42 -0
  33. academy_dashboard-0.1.0/academy_dashboard.egg-info/dependency_links.txt +1 -0
  34. academy_dashboard-0.1.0/academy_dashboard.egg-info/entry_points.txt +2 -0
  35. academy_dashboard-0.1.0/academy_dashboard.egg-info/requires.txt +33 -0
  36. academy_dashboard-0.1.0/academy_dashboard.egg-info/top_level.txt +3 -0
  37. academy_dashboard-0.1.0/examples/__init__.py +0 -0
  38. academy_dashboard-0.1.0/examples/basic.py +81 -0
  39. academy_dashboard-0.1.0/examples/example.py +69 -0
  40. academy_dashboard-0.1.0/examples/federated_example.py +83 -0
  41. academy_dashboard-0.1.0/pyproject.toml +183 -0
  42. academy_dashboard-0.1.0/setup.cfg +4 -0
  43. academy_dashboard-0.1.0/tests/__init__.py +0 -0
  44. academy_dashboard-0.1.0/tests/user_agent_test.py +102 -0
@@ -0,0 +1,107 @@
1
+ # Release process (read carefully):
2
+ #
3
+ # 1. Choose the next semver version number (e.g., 1.3.2) with optional
4
+ # release candidate segments. See: https://peps.python.org/pep-0440/
5
+ #
6
+ # 2. Open and merge any PRs required for documentation updates
7
+ # (e.g., migration guides for version bumps with breaking changes).
8
+ # Documentation changes must be made *before* running this publish
9
+ # workflow for the changes to be included in the tagged version of
10
+ # the docs site.
11
+ #
12
+ # 3. Tag the target commit on main for the release. Note that
13
+ # setuptools_scm requires the version tag is prepended with "v".
14
+ # This command creates a signed tag (recommended) using your GPG key.
15
+ #
16
+ # export VERSION=v1.3.2
17
+ # git tag -s $VERSION <SHORT_COMMIT_HASH> -m "Dashboard $VERSION"
18
+ # git push origin $VERSION
19
+ #
20
+ # 4. Create a new release on GitHub corresponding to the tag. Releases
21
+ # will trigger this publish workflow that will publish the package
22
+ # to PyPI and push a new version of the docs.
23
+ #
24
+ # * Go to https://github.com/academy-agents/nexus/releases
25
+ # * Click "Draft a new release"
26
+ # * Select the tag you created
27
+ #
28
+ # Official releases:
29
+ #
30
+ # * Select the previous tag as the previous *official* release. For
31
+ # example, use v0.4.0 as the previous release tag and NOT v0.4.0rc1.
32
+ # This is necessary for generating the diff link on the release
33
+ # correctly
34
+ # * Click "Generate release notes"
35
+ # * Add an "Upgrade Steps" section at the top (see previous releases
36
+ # for examples)
37
+ # * Review the generated notes and edit as needed. PRs are organized
38
+ # by tag, but some PRs will be missing tags and need to be moved
39
+ # from the "Other Changes" section to the correct section
40
+ # * Select "Set as the latest release"
41
+ # * Publish the release
42
+ #
43
+ # Pre releases:
44
+ #
45
+ # * Do NOT generate release notes. A description of "Development
46
+ # pre-release for <VERSION>" is sufficient
47
+ # * Leave the previous tag as "auto"
48
+ # * Select "Set as a pre-release"
49
+ # * Publish the release
50
+ #
51
+ name: publish
52
+
53
+ on:
54
+ release:
55
+ types: [published]
56
+ workflow_dispatch:
57
+
58
+ permissions:
59
+ contents: write
60
+ id-token: write
61
+
62
+ jobs:
63
+ publish:
64
+ runs-on: ubuntu-latest
65
+ steps:
66
+ - name: Checkout
67
+ uses: actions/checkout@v6
68
+ with:
69
+ fetch-depth: 0
70
+
71
+ - name: Extract package version from tag
72
+ run: |
73
+ # Removes 'v' prefix from tag (e.g., v1.0.0 -> 1.0.0)
74
+ VERSION=${GITHUB_REF_NAME#v}
75
+ echo "PACKAGE_VERSION=$VERSION" >> $GITHUB_ENV
76
+ echo "Extracted version from tag: $VERSION"
77
+
78
+ - name: Setup Python 3.13
79
+ uses: actions/setup-python@v6
80
+ with:
81
+ python-version: '3.13'
82
+
83
+ - name: Install pypa/build and build
84
+ run: |
85
+ pip install build
86
+ python -m build --sdist --wheel --outdir dist/ .
87
+
88
+ - name: Upload files to release
89
+ if: startsWith(github.ref, 'refs/tags/')
90
+ uses: softprops/action-gh-release@v3
91
+ with:
92
+ files: dist/*
93
+
94
+ - name: Publish to PyPI
95
+ if: startsWith(github.ref, 'refs/tags')
96
+ uses: pypa/gh-action-pypi-publish@release/v1
97
+
98
+ - name: Configure git
99
+ run: |
100
+ git config --local user.name "GitHub Actions Bot"
101
+ git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
102
+
103
+ - name: Deploy docs for release version to gh-pages branch
104
+ if: startsWith(github.ref, 'refs/tags/')
105
+ run: |
106
+ pip install .[docs]
107
+ mike deploy --push --update-aliases "${{ env.PACKAGE_VERSION }}" stable
@@ -0,0 +1,34 @@
1
+ ci:
2
+ autofix_prs: false
3
+ repos:
4
+ - repo: 'https://github.com/pre-commit/pre-commit-hooks'
5
+ rev: v6.0.0
6
+ hooks:
7
+ - id: mixed-line-ending
8
+ - id: trailing-whitespace
9
+ - id: end-of-file-fixer
10
+ - id: check-added-large-files
11
+ - id: check-docstring-first
12
+ - id: check-json
13
+ - id: check-yaml
14
+ - id: check-merge-conflict
15
+ - id: name-tests-test
16
+ - repo: 'https://github.com/codespell-project/codespell'
17
+ rev: v2.4.2
18
+ hooks:
19
+ - id: codespell
20
+ exclude: ".svg$"
21
+ - repo: 'https://github.com/astral-sh/ruff-pre-commit'
22
+ rev: v0.14.11
23
+ hooks:
24
+ - id: ruff-check
25
+ args:
26
+ - '--fix'
27
+ - '--exit-non-zero-on-fix'
28
+ - id: ruff-format
29
+ - repo: 'https://github.com/pre-commit/mirrors-mypy'
30
+ rev: v1.19.1
31
+ hooks:
32
+ - id: mypy
33
+ additional_dependencies:
34
+ - types-requests
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Academy Agents
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,115 @@
1
+ Metadata-Version: 2.4
2
+ Name: academy-dashboard
3
+ Version: 0.1.0
4
+ Summary: Observability and Oversight components for Academy Agents
5
+ Author: ModCon BASE Core Agentic Frameworks Team
6
+ Author-email: yadunand@uchicago.edu
7
+ License: MIT
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3 :: Only
11
+ Classifier: Programming Language :: Python :: Implementation :: CPython
12
+ Requires-Python: ==3.13.*
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE
15
+ Requires-Dist: requests
16
+ Requires-Dist: academy-py>=0.5.0
17
+ Requires-Dist: dotenv
18
+ Requires-Dist: globus-compute-sdk
19
+ Requires-Dist: tox>=4.34.1
20
+ Requires-Dist: flask>=3.1
21
+ Requires-Dist: psutil
22
+ Provides-Extra: dev
23
+ Requires-Dist: covdefaults>=2.2; extra == "dev"
24
+ Requires-Dist: coverage; extra == "dev"
25
+ Requires-Dist: mypy; extra == "dev"
26
+ Requires-Dist: types-requests; extra == "dev"
27
+ Requires-Dist: pre-commit; extra == "dev"
28
+ Requires-Dist: pytest; extra == "dev"
29
+ Requires-Dist: pytest-cov; extra == "dev"
30
+ Requires-Dist: pytest-asyncio; extra == "dev"
31
+ Requires-Dist: pre-commit>=4.5.1; extra == "dev"
32
+ Requires-Dist: ruff>=0.15.0; extra == "dev"
33
+ Requires-Dist: tox; extra == "dev"
34
+ Requires-Dist: virtualenv; extra == "dev"
35
+ Provides-Extra: docs
36
+ Requires-Dist: black==24.4.2; extra == "docs"
37
+ Requires-Dist: mkdocs-autorefs==1.3.1; extra == "docs"
38
+ Requires-Dist: mkdocs-click==0.8.1; extra == "docs"
39
+ Requires-Dist: mkdocs-gen-files==0.5.0; extra == "docs"
40
+ Requires-Dist: mkdocs-literate-nav==0.6.1; extra == "docs"
41
+ Requires-Dist: mkdocs-material==9.5.32; extra == "docs"
42
+ Requires-Dist: mkdocs-section-index==0.3.9; extra == "docs"
43
+ Requires-Dist: mkdocstrings==0.25.2; extra == "docs"
44
+ Requires-Dist: mkdocstrings-python==1.10.8; extra == "docs"
45
+ Requires-Dist: mike==2.1.3; extra == "docs"
46
+ Dynamic: license-file
47
+
48
+ # Academy-Dashboard
49
+
50
+ **Observability and Oversight for Academy Agents**
51
+
52
+ As agents act autonomously, the ability to observe what they are doing and intervene
53
+ when appropriate becomes a critical capability. `academy-dashboard` addresses these
54
+ challenges in agentic deployments through the following extensions for `Academy`:
55
+
56
+ * `UserAgent`: Specialized Academy agents that 1. accepts information from MonitoredAgents \
57
+ and 2. presents this information over a web based dashboard.
58
+ * `MonitoredAgent`: Extends academy's `Agent` class to support observability and control features.
59
+
60
+ Here are some of the supported capabilities:
61
+
62
+ * Logging: Live log stream from `MonitoredAgents` is presented via the `UserAgent`
63
+ * Human-in-the-loop: `MonitoredAgents` can send user prompts to the `UserAgent` where a user can respond over a webpage
64
+ * Performance Stats: Dashboard presents performance stats collected from `MonitoredAgents`
65
+ * Shutdown: `MonitoredAgent`s can be terminated from the dashboard provided by `UserAgents`
66
+ * Location: Locate your agents on a map
67
+
68
+ ## Using the `UserAgent`
69
+
70
+ There are two supported modes for using starting a `UserAgent`:
71
+
72
+
73
+ #### `Hosted UserAgent`
74
+
75
+ >> Go to [dashboard.academy-agents.org](https://dashboard.academy-agents.org/)
76
+
77
+ 1) Login with Globus Auth \
78
+ 2) Click the `[+]` button to launch a new `UserAgent` \
79
+ 3) Copy the agent UUID and plug this back into your scripts \
80
+
81
+ ### `Local Deployment`:
82
+
83
+ Launch locally with: `user-agent-launcher`,
84
+
85
+ ```bash
86
+ :>user-agent-launcher
87
+ User Agent UUID >>>>
88
+ a9337401-3d22-4205-923a-0040bb8d3a7b
89
+ * Serving Flask app 'academy_dashboard.user_agent.dashboard'
90
+ * Debug mode: off
91
+
92
+ ```
93
+
94
+ > NOTE: MonitoredAgents need the User Agent's UUID (printed above) to establish a connection.
95
+
96
+ ```bash
97
+ :> user-agent-launcher -h
98
+ usage: user-agent-launcher [-h] [-p PORT] [-r REGISTRATION_FILE] [-l {DEBUG,INFO,WARNING,ERROR,CRITICAL}]
99
+
100
+ options:
101
+ -h, --help show this help message and exit
102
+ -p, --port PORT Port at which the flask service is listening
103
+ -r, --registration_file REGISTRATION_FILE
104
+ UserAgent registration file
105
+ -l, --log_level {DEBUG,INFO,WARNING,ERROR,CRITICAL}
106
+ Log level
107
+ ```
108
+
109
+ ## Using the `MonitoredAgent`
110
+
111
+ ```python
112
+ import os
113
+
114
+ USER_AGENT_ID=os.environ('USER_AGENT_UUID')
115
+ ```
@@ -0,0 +1,68 @@
1
+ # Academy-Dashboard
2
+
3
+ **Observability and Oversight for Academy Agents**
4
+
5
+ As agents act autonomously, the ability to observe what they are doing and intervene
6
+ when appropriate becomes a critical capability. `academy-dashboard` addresses these
7
+ challenges in agentic deployments through the following extensions for `Academy`:
8
+
9
+ * `UserAgent`: Specialized Academy agents that 1. accepts information from MonitoredAgents \
10
+ and 2. presents this information over a web based dashboard.
11
+ * `MonitoredAgent`: Extends academy's `Agent` class to support observability and control features.
12
+
13
+ Here are some of the supported capabilities:
14
+
15
+ * Logging: Live log stream from `MonitoredAgents` is presented via the `UserAgent`
16
+ * Human-in-the-loop: `MonitoredAgents` can send user prompts to the `UserAgent` where a user can respond over a webpage
17
+ * Performance Stats: Dashboard presents performance stats collected from `MonitoredAgents`
18
+ * Shutdown: `MonitoredAgent`s can be terminated from the dashboard provided by `UserAgents`
19
+ * Location: Locate your agents on a map
20
+
21
+ ## Using the `UserAgent`
22
+
23
+ There are two supported modes for using starting a `UserAgent`:
24
+
25
+
26
+ #### `Hosted UserAgent`
27
+
28
+ >> Go to [dashboard.academy-agents.org](https://dashboard.academy-agents.org/)
29
+
30
+ 1) Login with Globus Auth \
31
+ 2) Click the `[+]` button to launch a new `UserAgent` \
32
+ 3) Copy the agent UUID and plug this back into your scripts \
33
+
34
+ ### `Local Deployment`:
35
+
36
+ Launch locally with: `user-agent-launcher`,
37
+
38
+ ```bash
39
+ :>user-agent-launcher
40
+ User Agent UUID >>>>
41
+ a9337401-3d22-4205-923a-0040bb8d3a7b
42
+ * Serving Flask app 'academy_dashboard.user_agent.dashboard'
43
+ * Debug mode: off
44
+
45
+ ```
46
+
47
+ > NOTE: MonitoredAgents need the User Agent's UUID (printed above) to establish a connection.
48
+
49
+ ```bash
50
+ :> user-agent-launcher -h
51
+ usage: user-agent-launcher [-h] [-p PORT] [-r REGISTRATION_FILE] [-l {DEBUG,INFO,WARNING,ERROR,CRITICAL}]
52
+
53
+ options:
54
+ -h, --help show this help message and exit
55
+ -p, --port PORT Port at which the flask service is listening
56
+ -r, --registration_file REGISTRATION_FILE
57
+ UserAgent registration file
58
+ -l, --log_level {DEBUG,INFO,WARNING,ERROR,CRITICAL}
59
+ Log level
60
+ ```
61
+
62
+ ## Using the `MonitoredAgent`
63
+
64
+ ```python
65
+ import os
66
+
67
+ USER_AGENT_ID=os.environ('USER_AGENT_UUID')
68
+ ```
@@ -0,0 +1,64 @@
1
+ Known bugs:
2
+
3
+
4
+ # Heartbeats don't work
5
+ [Pending]
6
+ The UserAgent treats every message from an agent as a heartbeat,
7
+ but this mechanism appears to be broken now.
8
+ We should switch over to using mailbox/agent liveness info provided
9
+ by the exchange directly.
10
+
11
+ # Shutdown doesn't work
12
+ [Pending]
13
+ The shutdown button on the agent cards no longer trigger agent shutdown
14
+
15
+
16
+ # Log issues
17
+ [Pending]
18
+ Logging issues are being worked out with the switch away from `init_logging()` to the `recommended` loggers from BenC.
19
+ The issue here is that logConfig objects are handled by the manager and we do not use a manager in the `user-agent-launcher`.
20
+ We use `http_exchange_client.register_agent -> make Runtime(registration=AgentReg)` which leaves out a point to plug in log configuration.
21
+
22
+ # HTTP Timeouts
23
+ [Addressed]
24
+ The following bug was addressed by upgrading academy-py to latest which has support for handling
25
+ aiohttp timeouts within the HTTPExchangeClient. The fix basically is:
26
+
27
+ > factory = HttpExchangeFactory(client_timeout=aiohttp.ClientTimeout(total=None, sock_connect=30))
28
+
29
+ ```
30
+ [2026-05-15 23:35:57.671] ERROR (academy.logging) Background task raised an exception.
31
+ Traceback (most recent call last):
32
+ File "/Users/yadu/src/nexus/.venv/lib/python3.13/site-packages/aiohttp/streams.py", line 372, in _wait
33
+ await waiter
34
+ asyncio.exceptions.CancelledError
35
+
36
+ The above exception was the direct cause of the following exception:
37
+
38
+ Traceback (most recent call last):
39
+ File "/Users/yadu/src/nexus/.venv/lib/python3.13/site-packages/academy/logging.py", line 213, in execute_and_log_traceback
40
+ return await fut
41
+ ^^^^^^^^^
42
+ File "/Users/yadu/src/nexus/.venv/lib/python3.13/site-packages/academy/exchange/client.py", line 224, in _listen_for_messages
43
+ async for message in self._transport.listen():
44
+ ...<10 lines>...
45
+ await asyncio.sleep(0)
46
+ File "/Users/yadu/src/nexus/.venv/lib/python3.13/site-packages/academy/exchange/cloud/client.py", line 252, in listen
47
+ async for line_in_bytes in response.content:
48
+ ...<11 lines>...
49
+ current_message_lines.append(line)
50
+ File "/Users/yadu/src/nexus/.venv/lib/python3.13/site-packages/aiohttp/streams.py", line 53, in __anext__
51
+ rv = await self.read_func()
52
+ ^^^^^^^^^^^^^^^^^^^^^^
53
+ File "/Users/yadu/src/nexus/.venv/lib/python3.13/site-packages/aiohttp/streams.py", line 377, in readline
54
+ return await self.readuntil(max_size=max_line_length)
55
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
56
+ File "/Users/yadu/src/nexus/.venv/lib/python3.13/site-packages/aiohttp/streams.py", line 414, in readuntil
57
+ await self._wait("readuntil")
58
+ File "/Users/yadu/src/nexus/.venv/lib/python3.13/site-packages/aiohttp/streams.py", line 371, in _wait
59
+ with self._timer:
60
+ ^^^^^^^^^^^
61
+ File "/Users/yadu/src/nexus/.venv/lib/python3.13/site-packages/aiohttp/helpers.py", line 713, in __exit__
62
+ raise asyncio.TimeoutError from exc_val
63
+ TimeoutError
64
+ ```
@@ -0,0 +1,11 @@
1
+ """Observability components for agentic blueprints."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from academy_dashboard.monitored_agent import MonitoredAgent
6
+ from academy_dashboard.user_agent.user_agent import UserAgent
7
+
8
+ __all__ = [
9
+ 'MonitoredAgent',
10
+ 'UserAgent',
11
+ ]
@@ -0,0 +1,6 @@
1
+ from __future__ import annotations
2
+
3
+ from academy_dashboard.agents.sleeper import Sleeper
4
+ from academy_dashboard.agents.spinner import Spinner
5
+
6
+ __all__ = ['Sleeper', 'Spinner']
@@ -0,0 +1,28 @@
1
+ from __future__ import annotations
2
+
3
+ import asyncio
4
+ import logging
5
+
6
+ from academy.agent import loop
7
+ from academy.handle import Handle
8
+
9
+ from academy_dashboard.monitored_agent import MonitoredAgent
10
+ from academy_dashboard.user_agent.user_agent import UserAgent
11
+
12
+
13
+ class Sleeper(MonitoredAgent):
14
+ """An Agent that sleeps."""
15
+
16
+ def __init__(self, user_agent_handle: Handle[UserAgent]) -> None:
17
+ super().__init__(user_agent_handle=user_agent_handle)
18
+ print('Spinner init done')
19
+
20
+ @loop
21
+ async def cycle(self, shutdown: asyncio.Event) -> None:
22
+ """Log and sleep in loop."""
23
+ counter = 0
24
+ while not shutdown.is_set():
25
+ await asyncio.sleep(30)
26
+ logging.info('Sleeper iteration %d', counter)
27
+ counter += 1
28
+ logging.info('Sleeper exiting!!!! ')
@@ -0,0 +1,52 @@
1
+ from __future__ import annotations
2
+
3
+ import asyncio
4
+ import logging
5
+
6
+ from academy.agent import action
7
+ from academy.handle import Handle
8
+
9
+ from academy_dashboard.monitored_agent import MonitoredAgent
10
+ from academy_dashboard.user_agent.user_agent import UserAgent
11
+
12
+
13
+ class Spinner(MonitoredAgent):
14
+ """A concrete MonitoredAgent that does some work and reports progress."""
15
+
16
+ def __init__(self, user_agent_handle: Handle[UserAgent]) -> None:
17
+ super().__init__(user_agent_handle=user_agent_handle)
18
+ print('Spinner init done')
19
+
20
+ @action
21
+ async def run(self, iterations: int = 3) -> str:
22
+ """Simulate work and emit log messages that are forwarded to UserAgent."""
23
+ logging.info('Starting run!')
24
+ for i in range(iterations):
25
+ logging.info(
26
+ f'{self.agent_name} iteration %d/%d',
27
+ i + 1,
28
+ iterations,
29
+ )
30
+ await asyncio.sleep(10)
31
+ logging.warning('Finishing run!')
32
+ return f'Finished {iterations} iterations'
33
+
34
+ @action
35
+ async def poke(self) -> int:
36
+ """Mock action that emits a log."""
37
+ logging.warning('I just got Poked!')
38
+ return 4
39
+
40
+ @action
41
+ async def trigger_user_query(self) -> None:
42
+ """Trigger a user query."""
43
+ logging.info('Triggering user query!')
44
+ response = await self.prompt_user_agent(
45
+ 'Should I continue?',
46
+ responses=['Yes', 'No'],
47
+ )
48
+ try:
49
+ _ = 5 / 0
50
+ except ZeroDivisionError:
51
+ logging.exception('Something went wrong!')
52
+ logging.info(f'Got response: {response} from user query')