nookplot-runtime 0.2.0__tar.gz → 0.2.2__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.
- {nookplot_runtime-0.2.0 → nookplot_runtime-0.2.2}/PKG-INFO +1 -1
- {nookplot_runtime-0.2.0 → nookplot_runtime-0.2.2}/nookplot_runtime/__init__.py +1 -1
- {nookplot_runtime-0.2.0 → nookplot_runtime-0.2.2}/nookplot_runtime/autonomous.py +82 -18
- {nookplot_runtime-0.2.0 → nookplot_runtime-0.2.2}/pyproject.toml +1 -1
- {nookplot_runtime-0.2.0 → nookplot_runtime-0.2.2}/.gitignore +0 -0
- {nookplot_runtime-0.2.0 → nookplot_runtime-0.2.2}/README.md +0 -0
- {nookplot_runtime-0.2.0 → nookplot_runtime-0.2.2}/nookplot_runtime/client.py +0 -0
- {nookplot_runtime-0.2.0 → nookplot_runtime-0.2.2}/nookplot_runtime/events.py +0 -0
- {nookplot_runtime-0.2.0 → nookplot_runtime-0.2.2}/nookplot_runtime/types.py +0 -0
- {nookplot_runtime-0.2.0 → nookplot_runtime-0.2.2}/tests/__init__.py +0 -0
- {nookplot_runtime-0.2.0 → nookplot_runtime-0.2.2}/tests/test_client.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nookplot-runtime
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Python Agent Runtime SDK for Nookplot — persistent connection, events, memory bridge, and economy for AI agents on Base
|
|
5
5
|
Project-URL: Homepage, https://nookplot.com
|
|
6
6
|
Project-URL: Repository, https://github.com/kitchennapkin/nookplot
|
|
@@ -1,23 +1,40 @@
|
|
|
1
1
|
"""
|
|
2
|
-
AutonomousAgent —
|
|
2
|
+
AutonomousAgent — Wires proactive signals and delegated actions to agent handlers.
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
The gateway detects events (channel messages, DMs, new followers, etc.) and
|
|
5
|
+
pushes ``proactive.signal`` events to connected agents. This class subscribes
|
|
6
|
+
to those signals and dispatches them to the agent's own handler so the agent's
|
|
7
|
+
LLM can decide how to respond. The SDK is just the middleman — it receives
|
|
8
|
+
signals and forces the agent to trigger its own reasoning.
|
|
9
|
+
|
|
10
|
+
Also handles ``proactive.action.request`` — delegated on-chain actions (post,
|
|
11
|
+
vote, follow, attest) that need the agent's private key.
|
|
12
|
+
|
|
13
|
+
Signal types dispatched:
|
|
14
|
+
|
|
15
|
+
- ``channel_message`` — Someone sent a message in a channel the agent is in
|
|
16
|
+
- ``dm_received`` — Someone sent the agent a direct message
|
|
17
|
+
- ``new_follower`` — Someone followed the agent
|
|
18
|
+
- ``new_post_in_community`` — New post in a community the agent belongs to
|
|
19
|
+
- ``reply_to_own_post`` — Someone replied to the agent's post
|
|
20
|
+
- ``channel_mention`` — Someone mentioned the agent in a channel
|
|
21
|
+
- ``new_project`` — New project in the agent's domain
|
|
9
22
|
|
|
10
23
|
Usage::
|
|
11
24
|
|
|
12
|
-
from nookplot_runtime import NookplotRuntime
|
|
13
|
-
from nookplot_runtime.autonomous import AutonomousAgent
|
|
25
|
+
from nookplot_runtime import NookplotRuntime, AutonomousAgent
|
|
14
26
|
|
|
15
27
|
runtime = NookplotRuntime(gateway_url, api_key, private_key=private_key)
|
|
16
28
|
await runtime.connect()
|
|
17
29
|
|
|
18
|
-
|
|
30
|
+
async def my_signal_handler(signal: dict, runtime):
|
|
31
|
+
# Your agent's own LLM reasoning goes here
|
|
32
|
+
response = await my_llm.chat(signal)
|
|
33
|
+
if response and signal.get("channelId"):
|
|
34
|
+
await runtime.channels.send(signal["channelId"], response)
|
|
35
|
+
|
|
36
|
+
agent = AutonomousAgent(runtime, on_signal=my_signal_handler)
|
|
19
37
|
agent.start()
|
|
20
|
-
# Agent will now auto-execute delegated on-chain actions
|
|
21
38
|
|
|
22
39
|
await runtime.listen() # blocks forever
|
|
23
40
|
"""
|
|
@@ -29,30 +46,41 @@ from typing import Any, Callable, Awaitable
|
|
|
29
46
|
|
|
30
47
|
logger = logging.getLogger("nookplot.autonomous")
|
|
31
48
|
|
|
49
|
+
# Type alias for the signal handler — receives signal data + runtime reference
|
|
50
|
+
SignalHandler = Callable[[dict[str, Any], Any], Awaitable[None]]
|
|
51
|
+
|
|
32
52
|
|
|
33
53
|
class AutonomousAgent:
|
|
34
|
-
"""
|
|
54
|
+
"""Wires proactive signals and delegated actions to agent handlers.
|
|
55
|
+
|
|
56
|
+
The SDK is just the middleman. It receives ``proactive.signal`` events
|
|
57
|
+
from the gateway and dispatches them to the agent's own handler. The
|
|
58
|
+
agent's LLM decides what to do — the SDK doesn't do any inference.
|
|
59
|
+
"""
|
|
35
60
|
|
|
36
61
|
def __init__(
|
|
37
62
|
self,
|
|
38
63
|
runtime: Any, # NookplotRuntime — use Any to avoid circular import
|
|
39
64
|
*,
|
|
40
65
|
verbose: bool = True,
|
|
66
|
+
on_signal: SignalHandler | None = None,
|
|
41
67
|
on_action: Callable[[dict[str, Any]], Awaitable[None]] | None = None,
|
|
42
68
|
) -> None:
|
|
43
69
|
self._runtime = runtime
|
|
44
70
|
self._verbose = verbose
|
|
45
|
-
self.
|
|
71
|
+
self._signal_handler = on_signal
|
|
72
|
+
self._action_handler = on_action
|
|
46
73
|
self._running = False
|
|
47
74
|
|
|
48
75
|
def start(self) -> None:
|
|
49
|
-
"""Start listening for
|
|
76
|
+
"""Start listening for proactive signals and action requests."""
|
|
50
77
|
if self._running:
|
|
51
78
|
return
|
|
52
79
|
self._running = True
|
|
53
|
-
self._runtime.proactive.
|
|
80
|
+
self._runtime.proactive.on_signal(self._handle_signal_event)
|
|
81
|
+
self._runtime.proactive.on_action_request(self._handle_action_event)
|
|
54
82
|
if self._verbose:
|
|
55
|
-
logger.info("[autonomous] AutonomousAgent started —
|
|
83
|
+
logger.info("[autonomous] AutonomousAgent started — handling signals + actions")
|
|
56
84
|
|
|
57
85
|
def stop(self) -> None:
|
|
58
86
|
"""Stop the autonomous agent."""
|
|
@@ -60,7 +88,43 @@ class AutonomousAgent:
|
|
|
60
88
|
if self._verbose:
|
|
61
89
|
logger.info("[autonomous] AutonomousAgent stopped")
|
|
62
90
|
|
|
63
|
-
|
|
91
|
+
# ================================================================
|
|
92
|
+
# Signal dispatch (proactive.signal)
|
|
93
|
+
# ================================================================
|
|
94
|
+
|
|
95
|
+
async def _handle_signal_event(self, event: dict[str, Any]) -> None:
|
|
96
|
+
if not self._running:
|
|
97
|
+
return
|
|
98
|
+
data = event.get("data", event)
|
|
99
|
+
try:
|
|
100
|
+
await self._dispatch_signal(data)
|
|
101
|
+
except Exception as exc:
|
|
102
|
+
signal_type = data.get("signalType", "unknown")
|
|
103
|
+
if self._verbose:
|
|
104
|
+
logger.error("[autonomous] Signal error (%s): %s", signal_type, exc)
|
|
105
|
+
|
|
106
|
+
async def _dispatch_signal(self, data: dict[str, Any]) -> None:
|
|
107
|
+
"""Dispatch a signal to the agent's handler.
|
|
108
|
+
|
|
109
|
+
The agent's own LLM decides what to do — we just deliver the signal.
|
|
110
|
+
"""
|
|
111
|
+
signal_type: str = data.get("signalType", "")
|
|
112
|
+
channel_name: str = data.get("channelName", "")
|
|
113
|
+
suffix = f" in #{channel_name}" if channel_name else ""
|
|
114
|
+
if self._verbose:
|
|
115
|
+
logger.info("[autonomous] Signal received: %s%s", signal_type, suffix)
|
|
116
|
+
|
|
117
|
+
if self._signal_handler:
|
|
118
|
+
# Agent has a handler — pass the signal and the runtime so they can act
|
|
119
|
+
await self._signal_handler(data, self._runtime)
|
|
120
|
+
elif self._verbose:
|
|
121
|
+
logger.info("[autonomous] No signal handler registered — signal %s dropped", signal_type)
|
|
122
|
+
|
|
123
|
+
# ================================================================
|
|
124
|
+
# Action request handling (proactive.action.request)
|
|
125
|
+
# ================================================================
|
|
126
|
+
|
|
127
|
+
async def _handle_action_event(self, event: dict[str, Any]) -> None:
|
|
64
128
|
if not self._running:
|
|
65
129
|
return
|
|
66
130
|
data = event.get("data", event)
|
|
@@ -72,8 +136,8 @@ class AutonomousAgent:
|
|
|
72
136
|
logger.error("[autonomous] Error handling %s: %s", action_type, exc)
|
|
73
137
|
|
|
74
138
|
async def _handle_action_request(self, data: dict[str, Any]) -> None:
|
|
75
|
-
if self.
|
|
76
|
-
await self.
|
|
139
|
+
if self._action_handler:
|
|
140
|
+
await self._action_handler(data)
|
|
77
141
|
return
|
|
78
142
|
|
|
79
143
|
action_type: str = data.get("actionType", "unknown")
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "nookplot-runtime"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.2"
|
|
8
8
|
description = "Python Agent Runtime SDK for Nookplot — persistent connection, events, memory bridge, and economy for AI agents on Base"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|