toolplane-python-client 0.1.0__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.
- toolplane/__init__.py +106 -0
- toolplane/common/__init__.py +93 -0
- toolplane/common/base_config.py +129 -0
- toolplane/common/base_connection_manager.py +171 -0
- toolplane/common/base_session_manager.py +321 -0
- toolplane/common/base_tool_manager.py +347 -0
- toolplane/common/constants.py +47 -0
- toolplane/common/utils.py +310 -0
- toolplane/core/__init__.py +67 -0
- toolplane/core/config.py +107 -0
- toolplane/core/connection.py +285 -0
- toolplane/core/errors.py +298 -0
- toolplane/core/machine.py +480 -0
- toolplane/core/request.py +775 -0
- toolplane/core/session.py +332 -0
- toolplane/core/session_context.py +514 -0
- toolplane/core/task.py +130 -0
- toolplane/core/tool.py +329 -0
- toolplane/http_core/__init__.py +37 -0
- toolplane/http_core/http_config.py +97 -0
- toolplane/http_core/http_connection.py +409 -0
- toolplane/http_core/http_machine.py +298 -0
- toolplane/http_core/http_request.py +748 -0
- toolplane/http_core/http_session.py +348 -0
- toolplane/http_core/http_session_context.py +491 -0
- toolplane/http_core/http_task.py +101 -0
- toolplane/http_core/http_tool.py +400 -0
- toolplane/interfaces/__init__.py +27 -0
- toolplane/interfaces/client_interface.py +122 -0
- toolplane/interfaces/connection_interface.py +193 -0
- toolplane/interfaces/event_interface.py +290 -0
- toolplane/interfaces/request_interface.py +439 -0
- toolplane/interfaces/session_interface.py +288 -0
- toolplane/interfaces/tool_interface.py +441 -0
- toolplane/proto/__init__.py +0 -0
- toolplane/proto/service_pb2.py +315 -0
- toolplane/proto/service_pb2_grpc.py +2240 -0
- toolplane/provider_cli.py +268 -0
- toolplane/provider_registry.py +77 -0
- toolplane/provider_runtime.py +302 -0
- toolplane/toolkits/__init__.py +0 -0
- toolplane/toolkits/standalone_tools/__init__.py +0 -0
- toolplane/toolkits/standalone_tools/create_directory.py +94 -0
- toolplane/toolkits/standalone_tools/create_file.py +124 -0
- toolplane/toolkits/standalone_tools/file_search.py +229 -0
- toolplane/toolkits/standalone_tools/grep_search.py +372 -0
- toolplane/toolkits/standalone_tools/launcher.py +146 -0
- toolplane/toolkits/standalone_tools/list_dir.py +395 -0
- toolplane/toolkits/standalone_tools/read_file.py +346 -0
- toolplane/toolkits/standalone_tools/replace_string_in_file.py +407 -0
- toolplane/toolkits/standalone_tools/run_tests.py +66 -0
- toolplane/toolkits/standalone_tools/semantic_search.py +485 -0
- toolplane/toolkits/standalone_tools/standalone_toolkit.py +979 -0
- toolplane/toolkits/standalone_tools/test_failure_analysis.py +618 -0
- toolplane/toolkits/standalone_tools/test_standalone_toolkit.py +517 -0
- toolplane/toolkits/swe/__init__.py +35 -0
- toolplane/toolkits/swe/create_directory.py +15 -0
- toolplane/toolkits/swe/create_file.py +15 -0
- toolplane/toolkits/swe/descriptions.py +273 -0
- toolplane/toolkits/swe/execute_bash.py +93 -0
- toolplane/toolkits/swe/file_editor.py +775 -0
- toolplane/toolkits/swe/file_search.py +16 -0
- toolplane/toolkits/swe/finish.py +50 -0
- toolplane/toolkits/swe/grep_search.py +19 -0
- toolplane/toolkits/swe/list_dir.py +407 -0
- toolplane/toolkits/swe/read_file.py +18 -0
- toolplane/toolkits/swe/replace_string_in_file.py +17 -0
- toolplane/toolkits/swe/search.py +260 -0
- toolplane/toolkits/swe/semantic_search.py +20 -0
- toolplane/toolkits/swe/str_replace_editor.py +647 -0
- toolplane/toolkits/swe/submit.py +29 -0
- toolplane/toolkits/swe/swe_toolkit.py +1296 -0
- toolplane/toolplane_client.py +686 -0
- toolplane/toolplane_http_client.py +681 -0
- toolplane/utils/__init__.py +3 -0
- toolplane/utils/schema.py +146 -0
- toolplane_python_client-0.1.0.dist-info/METADATA +543 -0
- toolplane_python_client-0.1.0.dist-info/RECORD +81 -0
- toolplane_python_client-0.1.0.dist-info/WHEEL +5 -0
- toolplane_python_client-0.1.0.dist-info/entry_points.txt +2 -0
- toolplane_python_client-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
"""Session management interface definitions."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from abc import ABC, abstractmethod
|
|
5
|
+
from enum import Enum
|
|
6
|
+
from typing import Any, Callable, Dict, List, Optional, Protocol, runtime_checkable
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class SessionState(Enum):
|
|
12
|
+
"""Session states."""
|
|
13
|
+
|
|
14
|
+
CREATED = "created"
|
|
15
|
+
ACTIVE = "active"
|
|
16
|
+
SUSPENDED = "suspended"
|
|
17
|
+
TERMINATED = "terminated"
|
|
18
|
+
ERROR = "error"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@runtime_checkable
|
|
22
|
+
class ISessionContext(Protocol):
|
|
23
|
+
"""Protocol interface for session contexts."""
|
|
24
|
+
|
|
25
|
+
@property
|
|
26
|
+
def session_id(self) -> str:
|
|
27
|
+
"""Get session ID."""
|
|
28
|
+
...
|
|
29
|
+
|
|
30
|
+
@property
|
|
31
|
+
def machine_id(self) -> Optional[str]:
|
|
32
|
+
"""Get machine ID for this session."""
|
|
33
|
+
...
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
def state(self) -> SessionState:
|
|
37
|
+
"""Get session state."""
|
|
38
|
+
...
|
|
39
|
+
|
|
40
|
+
def register_machine(self) -> bool:
|
|
41
|
+
"""Register a machine for this session."""
|
|
42
|
+
...
|
|
43
|
+
|
|
44
|
+
def register_tool(
|
|
45
|
+
self,
|
|
46
|
+
name: str,
|
|
47
|
+
func: Callable,
|
|
48
|
+
schema: Optional[Dict] = None,
|
|
49
|
+
description: Optional[str] = None,
|
|
50
|
+
stream: bool = False,
|
|
51
|
+
tags: Optional[List[str]] = None,
|
|
52
|
+
) -> None:
|
|
53
|
+
"""Register a tool for this session."""
|
|
54
|
+
...
|
|
55
|
+
|
|
56
|
+
def invoke(self, tool_name: str, **params) -> Any:
|
|
57
|
+
"""Invoke a tool in this session."""
|
|
58
|
+
...
|
|
59
|
+
|
|
60
|
+
async def ainvoke(self, tool_name: str, **params) -> str:
|
|
61
|
+
"""Invoke a tool asynchronously."""
|
|
62
|
+
...
|
|
63
|
+
|
|
64
|
+
def stream(
|
|
65
|
+
self, tool_name: str, callback: Callable[[Any, bool], None], **params
|
|
66
|
+
) -> List[Any]:
|
|
67
|
+
"""Stream tool execution."""
|
|
68
|
+
...
|
|
69
|
+
|
|
70
|
+
async def astream(
|
|
71
|
+
self, tool_name: str, callback: Callable[[Any, bool], None], **params
|
|
72
|
+
) -> List[Any]:
|
|
73
|
+
"""Awaitable stream: resolves with the collected chunks."""
|
|
74
|
+
...
|
|
75
|
+
|
|
76
|
+
def get_available_tools(self) -> Dict[str, Any]:
|
|
77
|
+
"""Get available tools for this session."""
|
|
78
|
+
...
|
|
79
|
+
|
|
80
|
+
def get_request_status(self, request_id: str) -> Dict[str, Any]:
|
|
81
|
+
"""Get request status."""
|
|
82
|
+
...
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
@runtime_checkable
|
|
86
|
+
class ISessionManager(Protocol):
|
|
87
|
+
"""Protocol interface for session management."""
|
|
88
|
+
|
|
89
|
+
def create_session(
|
|
90
|
+
self,
|
|
91
|
+
session_id: Optional[str] = None,
|
|
92
|
+
user_id: Optional[str] = None,
|
|
93
|
+
name: Optional[str] = None,
|
|
94
|
+
description: Optional[str] = None,
|
|
95
|
+
namespace: Optional[str] = None,
|
|
96
|
+
api_key: Optional[str] = None,
|
|
97
|
+
) -> str:
|
|
98
|
+
"""Create a new session."""
|
|
99
|
+
...
|
|
100
|
+
|
|
101
|
+
def get_session(self, session_id: str) -> Optional[Dict[str, Any]]:
|
|
102
|
+
"""Get session information."""
|
|
103
|
+
...
|
|
104
|
+
|
|
105
|
+
def list_sessions(self) -> List[Dict[str, Any]]:
|
|
106
|
+
"""List all sessions."""
|
|
107
|
+
...
|
|
108
|
+
|
|
109
|
+
def delete_session(self, session_id: str) -> bool:
|
|
110
|
+
"""Delete a session."""
|
|
111
|
+
...
|
|
112
|
+
|
|
113
|
+
def register_session_context(
|
|
114
|
+
self, session_id: str, context: ISessionContext
|
|
115
|
+
) -> None:
|
|
116
|
+
"""Register a session context."""
|
|
117
|
+
...
|
|
118
|
+
|
|
119
|
+
def get_session_context(self, session_id: str) -> Optional[ISessionContext]:
|
|
120
|
+
"""Get session context by ID."""
|
|
121
|
+
...
|
|
122
|
+
|
|
123
|
+
def list_session_contexts(self) -> List[ISessionContext]:
|
|
124
|
+
"""List all session contexts."""
|
|
125
|
+
...
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
class ISessionLifecycleHandler(ABC):
|
|
129
|
+
"""Abstract interface for session lifecycle handling."""
|
|
130
|
+
|
|
131
|
+
@abstractmethod
|
|
132
|
+
def on_session_created(self, session_id: str, context: Dict[str, Any]) -> None:
|
|
133
|
+
"""Handle session creation."""
|
|
134
|
+
pass
|
|
135
|
+
|
|
136
|
+
@abstractmethod
|
|
137
|
+
def on_session_activated(self, session_id: str) -> None:
|
|
138
|
+
"""Handle session activation."""
|
|
139
|
+
pass
|
|
140
|
+
|
|
141
|
+
@abstractmethod
|
|
142
|
+
def on_session_suspended(self, session_id: str, reason: str) -> None:
|
|
143
|
+
"""Handle session suspension."""
|
|
144
|
+
pass
|
|
145
|
+
|
|
146
|
+
@abstractmethod
|
|
147
|
+
def on_session_terminated(self, session_id: str, reason: str) -> None:
|
|
148
|
+
"""Handle session termination."""
|
|
149
|
+
pass
|
|
150
|
+
|
|
151
|
+
@abstractmethod
|
|
152
|
+
def on_session_error(self, session_id: str, error: Exception) -> None:
|
|
153
|
+
"""Handle session error."""
|
|
154
|
+
pass
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
class DefaultSessionLifecycleHandler(ISessionLifecycleHandler):
|
|
158
|
+
"""Default implementation of session lifecycle handler."""
|
|
159
|
+
|
|
160
|
+
def __init__(self, log_func: Optional[Callable[[str], None]] = None):
|
|
161
|
+
self.log_func = log_func or print
|
|
162
|
+
|
|
163
|
+
def on_session_created(self, session_id: str, context: Dict[str, Any]) -> None:
|
|
164
|
+
"""Handle session creation."""
|
|
165
|
+
self.log_func(f"Session created: {session_id}")
|
|
166
|
+
|
|
167
|
+
def on_session_activated(self, session_id: str) -> None:
|
|
168
|
+
"""Handle session activation."""
|
|
169
|
+
self.log_func(f"Session activated: {session_id}")
|
|
170
|
+
|
|
171
|
+
def on_session_suspended(self, session_id: str, reason: str) -> None:
|
|
172
|
+
"""Handle session suspension."""
|
|
173
|
+
self.log_func(f"Session suspended: {session_id}, reason: {reason}")
|
|
174
|
+
|
|
175
|
+
def on_session_terminated(self, session_id: str, reason: str) -> None:
|
|
176
|
+
"""Handle session termination."""
|
|
177
|
+
self.log_func(f"Session terminated: {session_id}, reason: {reason}")
|
|
178
|
+
|
|
179
|
+
def on_session_error(self, session_id: str, error: Exception) -> None:
|
|
180
|
+
"""Handle session error."""
|
|
181
|
+
self.log_func(f"Session error: {session_id}, error: {error}")
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
class SessionRegistry:
|
|
185
|
+
"""Registry for managing session contexts and lifecycle handlers."""
|
|
186
|
+
|
|
187
|
+
def __init__(self):
|
|
188
|
+
self._contexts: Dict[str, ISessionContext] = {}
|
|
189
|
+
self._handlers: List[ISessionLifecycleHandler] = []
|
|
190
|
+
self._session_metadata: Dict[str, Dict[str, Any]] = {}
|
|
191
|
+
|
|
192
|
+
def register_context(self, session_id: str, context: ISessionContext) -> None:
|
|
193
|
+
"""Register a session context."""
|
|
194
|
+
self._contexts[session_id] = context
|
|
195
|
+
self._session_metadata[session_id] = {
|
|
196
|
+
"created_at": __import__("datetime").datetime.now(),
|
|
197
|
+
"state": SessionState.CREATED,
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
# Notify handlers
|
|
201
|
+
for handler in self._handlers:
|
|
202
|
+
try:
|
|
203
|
+
handler.on_session_created(
|
|
204
|
+
session_id, self._session_metadata[session_id]
|
|
205
|
+
)
|
|
206
|
+
except Exception as e:
|
|
207
|
+
logger.warning("Error in session lifecycle handler: %s", e)
|
|
208
|
+
|
|
209
|
+
def unregister_context(self, session_id: str, reason: str = "manual") -> bool:
|
|
210
|
+
"""Unregister a session context."""
|
|
211
|
+
if session_id not in self._contexts:
|
|
212
|
+
return False
|
|
213
|
+
|
|
214
|
+
# Notify handlers
|
|
215
|
+
for handler in self._handlers:
|
|
216
|
+
try:
|
|
217
|
+
handler.on_session_terminated(session_id, reason)
|
|
218
|
+
except Exception as e:
|
|
219
|
+
logger.warning("Error in session lifecycle handler: %s", e)
|
|
220
|
+
|
|
221
|
+
del self._contexts[session_id]
|
|
222
|
+
if session_id in self._session_metadata:
|
|
223
|
+
del self._session_metadata[session_id]
|
|
224
|
+
|
|
225
|
+
return True
|
|
226
|
+
|
|
227
|
+
def get_context(self, session_id: str) -> Optional[ISessionContext]:
|
|
228
|
+
"""Get session context by ID."""
|
|
229
|
+
return self._contexts.get(session_id)
|
|
230
|
+
|
|
231
|
+
def list_contexts(self) -> List[ISessionContext]:
|
|
232
|
+
"""List all session contexts."""
|
|
233
|
+
return list(self._contexts.values())
|
|
234
|
+
|
|
235
|
+
def add_lifecycle_handler(self, handler: ISessionLifecycleHandler) -> None:
|
|
236
|
+
"""Add a session lifecycle handler."""
|
|
237
|
+
self._handlers.append(handler)
|
|
238
|
+
|
|
239
|
+
def remove_lifecycle_handler(self, handler: ISessionLifecycleHandler) -> bool:
|
|
240
|
+
"""Remove a session lifecycle handler."""
|
|
241
|
+
if handler in self._handlers:
|
|
242
|
+
self._handlers.remove(handler)
|
|
243
|
+
return True
|
|
244
|
+
return False
|
|
245
|
+
|
|
246
|
+
def update_session_state(self, session_id: str, state: SessionState) -> None:
|
|
247
|
+
"""Update session state and notify handlers."""
|
|
248
|
+
if session_id not in self._session_metadata:
|
|
249
|
+
return
|
|
250
|
+
|
|
251
|
+
old_state = self._session_metadata[session_id].get("state")
|
|
252
|
+
self._session_metadata[session_id]["state"] = state
|
|
253
|
+
|
|
254
|
+
# Notify handlers based on state change
|
|
255
|
+
for handler in self._handlers:
|
|
256
|
+
try:
|
|
257
|
+
if state == SessionState.ACTIVE and old_state != SessionState.ACTIVE:
|
|
258
|
+
handler.on_session_activated(session_id)
|
|
259
|
+
elif state == SessionState.SUSPENDED:
|
|
260
|
+
handler.on_session_suspended(session_id, "state_change")
|
|
261
|
+
elif state == SessionState.ERROR:
|
|
262
|
+
handler.on_session_error(
|
|
263
|
+
session_id, Exception("Session state changed to ERROR")
|
|
264
|
+
)
|
|
265
|
+
except Exception as e:
|
|
266
|
+
logger.warning("Error in session lifecycle handler: %s", e)
|
|
267
|
+
|
|
268
|
+
def get_session_metadata(self, session_id: str) -> Optional[Dict[str, Any]]:
|
|
269
|
+
"""Get session metadata."""
|
|
270
|
+
return self._session_metadata.get(session_id)
|
|
271
|
+
|
|
272
|
+
def cleanup_expired_sessions(self, max_age_hours: int = 24) -> List[str]:
|
|
273
|
+
"""Clean up expired sessions."""
|
|
274
|
+
import datetime
|
|
275
|
+
|
|
276
|
+
expired_sessions = []
|
|
277
|
+
cutoff_time = datetime.datetime.now() - datetime.timedelta(hours=max_age_hours)
|
|
278
|
+
|
|
279
|
+
for session_id, metadata in self._session_metadata.items():
|
|
280
|
+
created_at = metadata.get("created_at")
|
|
281
|
+
if created_at and created_at < cutoff_time:
|
|
282
|
+
expired_sessions.append(session_id)
|
|
283
|
+
|
|
284
|
+
# Remove expired sessions
|
|
285
|
+
for session_id in expired_sessions:
|
|
286
|
+
self.unregister_context(session_id, "expired")
|
|
287
|
+
|
|
288
|
+
return expired_sessions
|