pi-python-core 0.10.0__py3-none-any.whl → 0.10.1__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.
- pi_python/_version.py +1 -1
- pi_python/plugins/__init__.py +19 -3
- pi_python/plugins/_compose.py +15 -0
- {pi_python_core-0.10.0.dist-info → pi_python_core-0.10.1.dist-info}/METADATA +2 -1
- {pi_python_core-0.10.0.dist-info → pi_python_core-0.10.1.dist-info}/RECORD +8 -8
- {pi_python_core-0.10.0.dist-info → pi_python_core-0.10.1.dist-info}/WHEEL +0 -0
- {pi_python_core-0.10.0.dist-info → pi_python_core-0.10.1.dist-info}/licenses/LICENSE +0 -0
- {pi_python_core-0.10.0.dist-info → pi_python_core-0.10.1.dist-info}/licenses/NOTICE +0 -0
pi_python/_version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.10.
|
|
1
|
+
__version__ = "0.10.1"
|
pi_python/plugins/__init__.py
CHANGED
|
@@ -21,6 +21,7 @@ import hashlib
|
|
|
21
21
|
import importlib
|
|
22
22
|
import importlib.machinery
|
|
23
23
|
import importlib.util
|
|
24
|
+
import inspect
|
|
24
25
|
import json
|
|
25
26
|
import math
|
|
26
27
|
import os
|
|
@@ -49,6 +50,7 @@ from ..tools import Tool, ToolContext, ToolResult, invoke
|
|
|
49
50
|
from .._mcp_interaction import MCPCallbacks
|
|
50
51
|
from ._compose import (
|
|
51
52
|
HOOK_NAMES,
|
|
53
|
+
HOOK_PARAMETERS,
|
|
52
54
|
PluginFailure,
|
|
53
55
|
compose_hooks,
|
|
54
56
|
isolated_listener,
|
|
@@ -286,7 +288,9 @@ class PluginAPI:
|
|
|
286
288
|
raise ConfigurationError(f"Unknown hook {hook!r}; hooks are {', '.join(HOOK_NAMES)}")
|
|
287
289
|
|
|
288
290
|
def register(function: F) -> F:
|
|
289
|
-
_require_callable(
|
|
291
|
+
_require_callable(
|
|
292
|
+
function, f"the {hook} handler of plugin {self.name!r}", HOOK_PARAMETERS[hook]
|
|
293
|
+
)
|
|
290
294
|
self._handlers.append((hook, function))
|
|
291
295
|
return function
|
|
292
296
|
|
|
@@ -294,7 +298,7 @@ class PluginAPI:
|
|
|
294
298
|
|
|
295
299
|
def subscribe(self, listener: EventListener) -> None:
|
|
296
300
|
"""Receive the events of agents built from this set; failures are reported, not raised."""
|
|
297
|
-
_require_callable(listener, f"an event listener of plugin {self.name!r}")
|
|
301
|
+
_require_callable(listener, f"an event listener of plugin {self.name!r}", ("event",))
|
|
298
302
|
self._listeners.append(listener)
|
|
299
303
|
|
|
300
304
|
def _path(self, path: str | os.PathLike[str]) -> Path:
|
|
@@ -1087,9 +1091,21 @@ def _redact(text: str, secrets: set[str] | None) -> str:
|
|
|
1087
1091
|
return text
|
|
1088
1092
|
|
|
1089
1093
|
|
|
1090
|
-
def _require_callable(value: Any, what: str) -> None:
|
|
1094
|
+
def _require_callable(value: Any, what: str, arguments: tuple[str, ...] = ()) -> None:
|
|
1095
|
+
"""Reject a callback now if it cannot take the positional `arguments` it will be called
|
|
1096
|
+
with; otherwise each call would fail and, for a hook, only be logged and skipped."""
|
|
1091
1097
|
if not callable(value):
|
|
1092
1098
|
raise ConfigurationError(f"{what} must be callable, not {type(value).__name__}")
|
|
1099
|
+
try:
|
|
1100
|
+
# Not following __wrapped__: a decorator's own wrapper is what gets called.
|
|
1101
|
+
signature = inspect.signature(value, follow_wrapped=False)
|
|
1102
|
+
except (TypeError, ValueError):
|
|
1103
|
+
return # no signature to inspect, as for some builtins
|
|
1104
|
+
try:
|
|
1105
|
+
signature.bind(*arguments)
|
|
1106
|
+
except TypeError as exc:
|
|
1107
|
+
expected = f"the arguments ({', '.join(arguments)})" if arguments else "no arguments"
|
|
1108
|
+
raise ConfigurationError(f"{what} must accept {expected}: {exc}") from None
|
|
1093
1109
|
|
|
1094
1110
|
|
|
1095
1111
|
def _looks_like_path(text: str) -> bool:
|
pi_python/plugins/_compose.py
CHANGED
|
@@ -34,6 +34,21 @@ from ..hooks import Hooks, RunContext, TurnUpdate
|
|
|
34
34
|
from ..tools import ToolResult, ToolResultUpdate, apply_result_update, invoke
|
|
35
35
|
|
|
36
36
|
HOOK_NAMES = tuple(f.name for f in fields(Hooks))
|
|
37
|
+
# The positional arguments the composed hooks below pass to each handler.
|
|
38
|
+
HOOK_PARAMETERS: dict[str, tuple[str, ...]] = {
|
|
39
|
+
"before_tool_call": ("call", "args", "context"),
|
|
40
|
+
"after_tool_call": ("call", "result", "context"),
|
|
41
|
+
"transform_context": ("messages", "cancel"),
|
|
42
|
+
"convert_to_llm": ("messages",),
|
|
43
|
+
"prepare_request": ("context", "cancel"),
|
|
44
|
+
"prepare_next_turn": ("context", "cancel"),
|
|
45
|
+
"finish_turn": ("context", "cancel"),
|
|
46
|
+
"get_api_key": ("provider",),
|
|
47
|
+
"on_payload": ("payload",),
|
|
48
|
+
"on_response": ("response",),
|
|
49
|
+
"on_provider_stream_event": ("event",),
|
|
50
|
+
}
|
|
51
|
+
assert set(HOOK_PARAMETERS) == set(HOOK_NAMES)
|
|
37
52
|
logger = logging.getLogger("pi_python.plugins")
|
|
38
53
|
|
|
39
54
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pi-python-core
|
|
3
|
-
Version: 0.10.
|
|
3
|
+
Version: 0.10.1
|
|
4
4
|
Summary: An embeddable asyncio agent core with opt-in Claude and OpenAI providers
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -99,6 +99,7 @@ To try it offline first: `python examples/quickstart.py`.
|
|
|
99
99
|
| Use MCP tools | `async with connect_stdio(...) as tools`, or `connect_http(url)` for a remote server | [mcp_tools](examples/mcp_tools.py) |
|
|
100
100
|
| Let one agent call another | Wrap the sub-agent as a tool; cancellation propagates down. Plugins can also define subagents in Markdown | [subagent](examples/subagent.py) |
|
|
101
101
|
| Package and share capabilities | A plugin bundles tools, instructions, hooks, skills, prompt templates, subagents and MCP servers; load it by name or path with `load_plugins` and build the agent with `plugins.agent(...)` | [plugin_demo](examples/plugin_demo.py) |
|
|
102
|
+
| Remember across conversations | Not built in, as in Pi's core; an example plugin saves facts to a file and puts them in the system prompt, ready to copy and adapt | [memory_demo](examples/memory_demo.py) |
|
|
102
103
|
| Intervene mid-run | `steer` injects guidance, `follow_up` queues the next task, `abort` cancels at any time (callable from any thread) | |
|
|
103
104
|
| Context full, service errors | `is_context_overflow` and `is_retryable_error` tell you why, `continue_run()` retries, `transform_context` compacts | [recovery](examples/recovery.py) |
|
|
104
105
|
| Save and restore conversations | `encode_messages` / `decode_messages`; your application decides where to store them | [save_restore](examples/save_restore.py) |
|
|
@@ -3,7 +3,7 @@ pi_python/_mcp_host.py,sha256=CXio-tiEeUCUfdl65tatwSrzIOYdgecdS00sO6tNy5k,8630
|
|
|
3
3
|
pi_python/_mcp_interaction.py,sha256=jPL-C8wLjBDV9tOdvGVFfXOl8-1FQIDJLq-MojlzXaM,43851
|
|
4
4
|
pi_python/_mcp_process.py,sha256=4szi5gMEP_0GUGOcV-oLPUuVQAUSb0ToAaiM979zHME,6324
|
|
5
5
|
pi_python/_mcp_sampling.py,sha256=BcWCrPgjsRC-GNx65fIB-JPq2WzWnoBK2w9iTnyPUww,12148
|
|
6
|
-
pi_python/_version.py,sha256=
|
|
6
|
+
pi_python/_version.py,sha256=v7Gyp89umFzDtY45tTjCdXqZnQ2RN01AibdYNxEvxYo,23
|
|
7
7
|
pi_python/agent.py,sha256=I4P4waCdkcURDd022H4XgBbHNhpa7LrI5Iwb5ncxhGU,16021
|
|
8
8
|
pi_python/cancellation.py,sha256=DoQVdX7DcQdVLkl4OvhcpMhKZJEW0Kscl2-xxF6i6Y0,608
|
|
9
9
|
pi_python/errors.py,sha256=65lT0nYfzqxRfUlFG-Y9vgYxfDHEuFiBfgqmFnX9_O8,675
|
|
@@ -31,8 +31,8 @@ pi_python/testing.py,sha256=XfTSOkEv0CenqrBILI_T205jOhyitW53YQZ9yiMXir4,1046
|
|
|
31
31
|
pi_python/tools.py,sha256=zBrYVoPOgrVHqvrL5sIhMXCf501QjyuDNdmR-tV6Ads,23274
|
|
32
32
|
pi_python/transcript.py,sha256=g6Tg8eiyMCAK43iLpcBv220MHBq8kO7Ty-6OYLCzw2A,6685
|
|
33
33
|
pi_python/data/models.json,sha256=oa_LGv7vaRrS-l7_Z7iu8f7WTyoJJLPhUQyptUz7OmE,77549
|
|
34
|
-
pi_python/plugins/__init__.py,sha256=
|
|
35
|
-
pi_python/plugins/_compose.py,sha256=
|
|
34
|
+
pi_python/plugins/__init__.py,sha256=FeYHYxgaOjKuq3QBBv1ezOyfORi5Fl2SdnImN_O0IrE,56156
|
|
35
|
+
pi_python/plugins/_compose.py,sha256=vmIh901G6D298uQBn_IhiKkczIBymsqCPWo7SxXUrTM,11411
|
|
36
36
|
pi_python/plugins/_frontmatter.py,sha256=_i5QeDcPlz9n8ou9W7b20TNWMVoeYThI1f4j68ZbuCk,16127
|
|
37
37
|
pi_python/plugins/_resources.py,sha256=uK5TSyJc1H6aptJqKw5FI83Gyp2MghxcUvgxOmWQu08,13531
|
|
38
38
|
pi_python/plugins/_subagents.py,sha256=HhUYK4z7gdtX2_DSh3vFfxyJCKo2zz0zSOjRE1j8CmY,10252
|
|
@@ -43,8 +43,8 @@ pi_python/providers/completions.py,sha256=vcqoLfJ-9quMREEEAJcHYs3Oq-A0Sz8Q1NV1QL
|
|
|
43
43
|
pi_python/providers/oauth.py,sha256=ZY8j7P-I-R6hZ8sInkGao957KWNGsqfvMF0F-YzlSgU,22786
|
|
44
44
|
pi_python/providers/openai.py,sha256=p0WHDnojAYb7mUX8EbComwEU_XskcYoMhMIR07QlSfc,30196
|
|
45
45
|
pi_python/providers/transport.py,sha256=B1mGKlVEqYGVK1MlcA9opwRhnuUYGuaYuTslNC3O8xs,26772
|
|
46
|
-
pi_python_core-0.10.
|
|
47
|
-
pi_python_core-0.10.
|
|
48
|
-
pi_python_core-0.10.
|
|
49
|
-
pi_python_core-0.10.
|
|
50
|
-
pi_python_core-0.10.
|
|
46
|
+
pi_python_core-0.10.1.dist-info/METADATA,sha256=AncCL6Sz-4xE1Kx9_iHB2TmHcOtq8jJjBFHxAGExpxs,8939
|
|
47
|
+
pi_python_core-0.10.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
48
|
+
pi_python_core-0.10.1.dist-info/licenses/LICENSE,sha256=BFf1vOw7OyEWBd-10aSQQv1jjzaGpBD-CZwkolrxPEg,1069
|
|
49
|
+
pi_python_core-0.10.1.dist-info/licenses/NOTICE,sha256=fJna16fm1ECHN7zVZhtyNmjLw8KGxGp8mL9blISF1K0,633
|
|
50
|
+
pi_python_core-0.10.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|