by-framework 0.2.2.dev2__py3-none-any.whl → 0.2.2.dev4__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.
- by_framework/client/client.py +15 -7
- by_framework/core/__init__.py +69 -0
- by_framework/core/availability.py +495 -0
- by_framework/core/delivery_gate.py +60 -0
- by_framework/core/discovery.py +359 -0
- by_framework/core/extensions/__init__.py +29 -0
- by_framework/core/extensions/agent_config.py +64 -0
- by_framework/core/extensions/plugin.py +312 -0
- by_framework/core/extensions/registry.py +704 -0
- by_framework/core/extensions/trace_provider.py +20 -0
- by_framework/core/protocol/__init__.py +99 -0
- by_framework/core/protocol/action_type.py +33 -0
- by_framework/core/protocol/agent_state.py +78 -0
- by_framework/core/protocol/byai_codec.py +96 -0
- by_framework/core/protocol/byai_command.py +53 -0
- by_framework/core/protocol/byai_types.py +7 -0
- by_framework/core/protocol/commands.py +285 -0
- by_framework/core/protocol/content_codec.py +17 -0
- by_framework/core/protocol/content_type.py +38 -0
- by_framework/core/protocol/data_message.py +45 -0
- by_framework/core/protocol/data_shapes.py +83 -0
- by_framework/core/protocol/event_type.py +34 -0
- by_framework/core/protocol/events.py +69 -0
- by_framework/core/protocol/message.py +99 -0
- by_framework/core/protocol/message_header.py +78 -0
- by_framework/core/protocol/responses.py +94 -0
- by_framework/core/protocol/results.py +149 -0
- by_framework/core/registry.py +1102 -0
- by_framework/core/runtime/__init__.py +27 -0
- by_framework/core/runtime/agent_config_manager.py +283 -0
- by_framework/core/runtime/agent_runtime_state.py +75 -0
- by_framework/core/runtime/file_manager.py +434 -0
- by_framework/core/runtime/file_paths.py +76 -0
- by_framework/core/runtime/file_permissions.py +71 -0
- by_framework/core/runtime/filestore/__init__.py +15 -0
- by_framework/core/runtime/filestore/base.py +140 -0
- by_framework/core/runtime/filestore/local.py +313 -0
- by_framework/core/runtime/history/__init__.py +10 -0
- by_framework/core/runtime/history/base.py +57 -0
- by_framework/core/runtime/history/history_manager.py +55 -0
- by_framework/core/runtime/history/in_memory.py +58 -0
- by_framework/core/runtime/session_manager.py +118 -0
- by_framework/core/wakeup_controller.py +149 -0
- by_framework/core/workspace.py +126 -0
- {by_framework-0.2.2.dev2.dist-info → by_framework-0.2.2.dev4.dist-info}/METADATA +1 -1
- by_framework-0.2.2.dev4.dist-info/RECORD +92 -0
- by_framework-0.2.2.dev2.dist-info/RECORD +0 -49
- {by_framework-0.2.2.dev2.dist-info → by_framework-0.2.2.dev4.dist-info}/WHEEL +0 -0
- {by_framework-0.2.2.dev2.dist-info → by_framework-0.2.2.dev4.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Plugin system core definitions.
|
|
3
|
+
|
|
4
|
+
This module provides the Plugin abstract base class and supporting types
|
|
5
|
+
for the extensible plugin architecture of the Gateway SDK.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import inspect
|
|
11
|
+
from abc import ABC, abstractmethod
|
|
12
|
+
from dataclasses import dataclass, field
|
|
13
|
+
from string import Formatter
|
|
14
|
+
from typing import TYPE_CHECKING, Any, List, Type
|
|
15
|
+
|
|
16
|
+
from .agent_config import AgentConfig
|
|
17
|
+
|
|
18
|
+
if TYPE_CHECKING:
|
|
19
|
+
from by_framework.core.protocol.commands import (AskAgentCommand,
|
|
20
|
+
CancelTaskCommand,
|
|
21
|
+
ResumeCommand)
|
|
22
|
+
from by_framework.worker.context import AgentContext
|
|
23
|
+
from by_framework.worker.worker import GatewayWorker
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass
|
|
27
|
+
class PromptTemplate:
|
|
28
|
+
"""Prompt template utility type that supports variable placeholders.
|
|
29
|
+
|
|
30
|
+
Can be placed in AgentConfig.prompts.
|
|
31
|
+
|
|
32
|
+
Attributes:
|
|
33
|
+
content: Template content string, supports {variable} format placeholders
|
|
34
|
+
variables: List of automatically extracted variable names
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
content: str
|
|
38
|
+
variables: List[str] = field(default_factory=list)
|
|
39
|
+
|
|
40
|
+
def __post_init__(self) -> None:
|
|
41
|
+
if not self.variables:
|
|
42
|
+
self.variables = self._extract_variables(self.content)
|
|
43
|
+
|
|
44
|
+
@staticmethod
|
|
45
|
+
def _extract_variables(content: str) -> List[str]:
|
|
46
|
+
"""Extract all variable names from template content."""
|
|
47
|
+
field_names: List[str] = []
|
|
48
|
+
for _, field_name, _, _ in Formatter().parse(content):
|
|
49
|
+
if field_name:
|
|
50
|
+
field_names.append(field_name)
|
|
51
|
+
return field_names
|
|
52
|
+
|
|
53
|
+
def render(self, **kwargs: Any) -> str:
|
|
54
|
+
"""Render the template using the provided variable values.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
**kwargs: Mapping of variable names to values
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
Rendered string
|
|
61
|
+
|
|
62
|
+
Raises:
|
|
63
|
+
KeyError: If provided variables are incomplete
|
|
64
|
+
"""
|
|
65
|
+
missing = [var for var in self.variables if var not in kwargs]
|
|
66
|
+
if missing:
|
|
67
|
+
raise KeyError(
|
|
68
|
+
f"Prompt missing variables: {missing}; "
|
|
69
|
+
f"provided keys: {sorted(kwargs.keys())}"
|
|
70
|
+
)
|
|
71
|
+
return self.content.format(**kwargs)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@dataclass
|
|
75
|
+
class PluginManifest:
|
|
76
|
+
"""Plugin manifest information.
|
|
77
|
+
|
|
78
|
+
Attributes:
|
|
79
|
+
plugin_id: Plugin unique identifier
|
|
80
|
+
version: Plugin version number
|
|
81
|
+
priority: Plugin priority, higher number runs earlier
|
|
82
|
+
enabled: Whether the plugin is enabled
|
|
83
|
+
"""
|
|
84
|
+
|
|
85
|
+
plugin_id: str
|
|
86
|
+
version: str = "1.0.0"
|
|
87
|
+
priority: int = 0
|
|
88
|
+
enabled: bool = True
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@dataclass
|
|
92
|
+
class PluginBuildContext:
|
|
93
|
+
"""Build context used during plugin registration phase (not runtime).
|
|
94
|
+
|
|
95
|
+
Provides read-only access and write capability to AgentConfig during
|
|
96
|
+
plugin registration.
|
|
97
|
+
"""
|
|
98
|
+
|
|
99
|
+
agent_configs: list[AgentConfig] = field(default_factory=list)
|
|
100
|
+
_prev_agent_configs: tuple[AgentConfig, ...] = ()
|
|
101
|
+
|
|
102
|
+
def set_agent_configs(self, new_configs: list[AgentConfig]) -> None:
|
|
103
|
+
"""Set new AgentConfig list."""
|
|
104
|
+
self.agent_configs = list(new_configs)
|
|
105
|
+
|
|
106
|
+
def list_agent_configs(self) -> list[AgentConfig]:
|
|
107
|
+
"""Return a copy of the current AgentConfig list."""
|
|
108
|
+
return list(self.agent_configs)
|
|
109
|
+
|
|
110
|
+
def freeze_prev_agent_configs(self) -> None:
|
|
111
|
+
"""Freeze current AgentConfigs as a read-only snapshot."""
|
|
112
|
+
self._prev_agent_configs = tuple(self.agent_configs)
|
|
113
|
+
|
|
114
|
+
def get_prev_agent_configs(self) -> tuple[AgentConfig, ...]:
|
|
115
|
+
"""Get the read-only snapshot of the previous version of AgentConfigs."""
|
|
116
|
+
return self._prev_agent_configs
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
@dataclass(frozen=True)
|
|
120
|
+
class AgentConfigsSnapshot:
|
|
121
|
+
"""Immutable view of a stable AgentConfig collection version."""
|
|
122
|
+
|
|
123
|
+
version: int
|
|
124
|
+
configs: tuple[AgentConfig, ...]
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
@dataclass(frozen=True)
|
|
128
|
+
class PluginReloadContext:
|
|
129
|
+
"""Context passed to plugin reload hooks.
|
|
130
|
+
|
|
131
|
+
The current_agent_configs field represents the working config list for the
|
|
132
|
+
current reload stage. Plugins can transform that list and return the next
|
|
133
|
+
full config version.
|
|
134
|
+
"""
|
|
135
|
+
|
|
136
|
+
plugin_id: str
|
|
137
|
+
reload_id: str
|
|
138
|
+
reason: str
|
|
139
|
+
current_agent_configs: tuple[AgentConfig, ...]
|
|
140
|
+
previous_stable_agent_configs: tuple[AgentConfig, ...]
|
|
141
|
+
current_version: int
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
@dataclass(frozen=True)
|
|
145
|
+
class PluginReloadResult:
|
|
146
|
+
"""Optional structured result for reload workflows."""
|
|
147
|
+
|
|
148
|
+
agent_configs: tuple[AgentConfig, ...]
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
class Plugin(ABC):
|
|
152
|
+
"""Plugin abstract base class.
|
|
153
|
+
|
|
154
|
+
Plugins are responsible for registering AgentConfig and optionally providing
|
|
155
|
+
lifecycle hooks. Create a plugin by inheriting from this class and implementing
|
|
156
|
+
the register_agent_configs method.
|
|
157
|
+
"""
|
|
158
|
+
|
|
159
|
+
_registered_plugins: List[Type["Plugin"]] = []
|
|
160
|
+
|
|
161
|
+
def __init_subclass__(cls, **kwargs):
|
|
162
|
+
super().__init_subclass__(**kwargs)
|
|
163
|
+
if not inspect.isabstract(cls):
|
|
164
|
+
Plugin._registered_plugins.append(cls)
|
|
165
|
+
|
|
166
|
+
@classmethod
|
|
167
|
+
def get_registered_plugins(cls) -> List[Type["Plugin"]]:
|
|
168
|
+
"""Get all registered plugin classes."""
|
|
169
|
+
return cls._registered_plugins
|
|
170
|
+
|
|
171
|
+
def __init__(
|
|
172
|
+
self, manifest: PluginManifest, hook_timeout_seconds: float | None = None
|
|
173
|
+
):
|
|
174
|
+
self.manifest = manifest
|
|
175
|
+
self.name = manifest.plugin_id
|
|
176
|
+
self.plugin_id = manifest.plugin_id
|
|
177
|
+
self.version = manifest.version
|
|
178
|
+
self.hook_timeout_seconds = hook_timeout_seconds
|
|
179
|
+
|
|
180
|
+
@abstractmethod
|
|
181
|
+
async def register_agent_configs(
|
|
182
|
+
self, build_context: PluginBuildContext
|
|
183
|
+
) -> list[AgentConfig] | None:
|
|
184
|
+
"""Plugin registration entry method.
|
|
185
|
+
|
|
186
|
+
Plugin can read the read-only snapshot of build_context and return a new
|
|
187
|
+
agent_configs list.
|
|
188
|
+
|
|
189
|
+
Args:
|
|
190
|
+
build_context: Plugin build context
|
|
191
|
+
|
|
192
|
+
Returns:
|
|
193
|
+
New AgentConfig list, or None
|
|
194
|
+
"""
|
|
195
|
+
raise NotImplementedError
|
|
196
|
+
|
|
197
|
+
async def reload(
|
|
198
|
+
self,
|
|
199
|
+
context: PluginReloadContext,
|
|
200
|
+
) -> list[AgentConfig] | PluginReloadResult | None:
|
|
201
|
+
"""Transform the current stable config chain into the next version.
|
|
202
|
+
|
|
203
|
+
Default behavior is a no-op so existing plugins remain compatible.
|
|
204
|
+
Plugins that support hot reload can override this method to return the
|
|
205
|
+
next full AgentConfig list for the current reload stage.
|
|
206
|
+
"""
|
|
207
|
+
return list(context.current_agent_configs)
|
|
208
|
+
|
|
209
|
+
async def on_worker_startup(self, worker: "GatewayWorker") -> None:
|
|
210
|
+
"""Hook called when Worker starts.
|
|
211
|
+
|
|
212
|
+
Args:
|
|
213
|
+
worker: GatewayWorker instance
|
|
214
|
+
"""
|
|
215
|
+
pass
|
|
216
|
+
|
|
217
|
+
async def on_worker_shutdown(self, worker: "GatewayWorker") -> None:
|
|
218
|
+
"""Hook called when Worker shuts down.
|
|
219
|
+
|
|
220
|
+
Args:
|
|
221
|
+
worker: GatewayWorker instance
|
|
222
|
+
"""
|
|
223
|
+
pass
|
|
224
|
+
|
|
225
|
+
async def on_task_start(self, context: "AgentContext") -> None:
|
|
226
|
+
"""Hook called when task starts.
|
|
227
|
+
|
|
228
|
+
Args:
|
|
229
|
+
context: AgentContext instance
|
|
230
|
+
"""
|
|
231
|
+
pass
|
|
232
|
+
|
|
233
|
+
async def on_task_complete(self, context: "AgentContext", result: Any) -> None:
|
|
234
|
+
"""Hook called when task completes.
|
|
235
|
+
|
|
236
|
+
Args:
|
|
237
|
+
context: AgentContext instance
|
|
238
|
+
result: Task execution result
|
|
239
|
+
"""
|
|
240
|
+
pass
|
|
241
|
+
|
|
242
|
+
async def on_task_error(self, context: "AgentContext", error: Exception) -> None:
|
|
243
|
+
"""Hook called when task encounters an error.
|
|
244
|
+
|
|
245
|
+
Args:
|
|
246
|
+
context: AgentContext instance
|
|
247
|
+
error: Exception object
|
|
248
|
+
"""
|
|
249
|
+
pass
|
|
250
|
+
|
|
251
|
+
async def on_task_cancel(
|
|
252
|
+
self, context: "AgentContext", command: "CancelTaskCommand"
|
|
253
|
+
) -> None:
|
|
254
|
+
"""Hook called when task is cancelled.
|
|
255
|
+
|
|
256
|
+
Args:
|
|
257
|
+
context: AgentContext instance
|
|
258
|
+
command: Cancel task command
|
|
259
|
+
"""
|
|
260
|
+
pass
|
|
261
|
+
|
|
262
|
+
async def on_call_agent_start(
|
|
263
|
+
self, context: "AgentContext", command: "AskAgentCommand"
|
|
264
|
+
) -> None:
|
|
265
|
+
"""Hook triggered before calling another Agent."""
|
|
266
|
+
pass
|
|
267
|
+
|
|
268
|
+
async def on_call_agent_complete(
|
|
269
|
+
self,
|
|
270
|
+
context: "AgentContext",
|
|
271
|
+
command: "AskAgentCommand",
|
|
272
|
+
result: Any,
|
|
273
|
+
) -> None:
|
|
274
|
+
"""Hook triggered after successfully enqueuing a call to another Agent."""
|
|
275
|
+
pass
|
|
276
|
+
|
|
277
|
+
async def on_call_agent_error(
|
|
278
|
+
self,
|
|
279
|
+
context: "AgentContext",
|
|
280
|
+
command: "AskAgentCommand",
|
|
281
|
+
error: Exception,
|
|
282
|
+
) -> None:
|
|
283
|
+
"""Hook triggered when calling another Agent fails."""
|
|
284
|
+
pass
|
|
285
|
+
|
|
286
|
+
async def on_agent_return_start(
|
|
287
|
+
self,
|
|
288
|
+
context: "AgentContext",
|
|
289
|
+
command: "AskAgentCommand",
|
|
290
|
+
callback_command: "ResumeCommand",
|
|
291
|
+
) -> None:
|
|
292
|
+
"""Hook triggered before enqueueing a ResumeCommand to the caller."""
|
|
293
|
+
pass
|
|
294
|
+
|
|
295
|
+
async def on_agent_return_complete(
|
|
296
|
+
self,
|
|
297
|
+
context: "AgentContext",
|
|
298
|
+
command: "AskAgentCommand",
|
|
299
|
+
callback_command: "ResumeCommand",
|
|
300
|
+
) -> None:
|
|
301
|
+
"""Hook triggered after successfully enqueueing a ResumeCommand."""
|
|
302
|
+
pass
|
|
303
|
+
|
|
304
|
+
async def on_agent_return_error(
|
|
305
|
+
self,
|
|
306
|
+
context: "AgentContext",
|
|
307
|
+
command: "AskAgentCommand",
|
|
308
|
+
callback_command: "ResumeCommand",
|
|
309
|
+
error: Exception,
|
|
310
|
+
) -> None:
|
|
311
|
+
"""Hook triggered when enqueueing a ResumeCommand fails."""
|
|
312
|
+
pass
|