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.
Files changed (81) hide show
  1. toolplane/__init__.py +106 -0
  2. toolplane/common/__init__.py +93 -0
  3. toolplane/common/base_config.py +129 -0
  4. toolplane/common/base_connection_manager.py +171 -0
  5. toolplane/common/base_session_manager.py +321 -0
  6. toolplane/common/base_tool_manager.py +347 -0
  7. toolplane/common/constants.py +47 -0
  8. toolplane/common/utils.py +310 -0
  9. toolplane/core/__init__.py +67 -0
  10. toolplane/core/config.py +107 -0
  11. toolplane/core/connection.py +285 -0
  12. toolplane/core/errors.py +298 -0
  13. toolplane/core/machine.py +480 -0
  14. toolplane/core/request.py +775 -0
  15. toolplane/core/session.py +332 -0
  16. toolplane/core/session_context.py +514 -0
  17. toolplane/core/task.py +130 -0
  18. toolplane/core/tool.py +329 -0
  19. toolplane/http_core/__init__.py +37 -0
  20. toolplane/http_core/http_config.py +97 -0
  21. toolplane/http_core/http_connection.py +409 -0
  22. toolplane/http_core/http_machine.py +298 -0
  23. toolplane/http_core/http_request.py +748 -0
  24. toolplane/http_core/http_session.py +348 -0
  25. toolplane/http_core/http_session_context.py +491 -0
  26. toolplane/http_core/http_task.py +101 -0
  27. toolplane/http_core/http_tool.py +400 -0
  28. toolplane/interfaces/__init__.py +27 -0
  29. toolplane/interfaces/client_interface.py +122 -0
  30. toolplane/interfaces/connection_interface.py +193 -0
  31. toolplane/interfaces/event_interface.py +290 -0
  32. toolplane/interfaces/request_interface.py +439 -0
  33. toolplane/interfaces/session_interface.py +288 -0
  34. toolplane/interfaces/tool_interface.py +441 -0
  35. toolplane/proto/__init__.py +0 -0
  36. toolplane/proto/service_pb2.py +315 -0
  37. toolplane/proto/service_pb2_grpc.py +2240 -0
  38. toolplane/provider_cli.py +268 -0
  39. toolplane/provider_registry.py +77 -0
  40. toolplane/provider_runtime.py +302 -0
  41. toolplane/toolkits/__init__.py +0 -0
  42. toolplane/toolkits/standalone_tools/__init__.py +0 -0
  43. toolplane/toolkits/standalone_tools/create_directory.py +94 -0
  44. toolplane/toolkits/standalone_tools/create_file.py +124 -0
  45. toolplane/toolkits/standalone_tools/file_search.py +229 -0
  46. toolplane/toolkits/standalone_tools/grep_search.py +372 -0
  47. toolplane/toolkits/standalone_tools/launcher.py +146 -0
  48. toolplane/toolkits/standalone_tools/list_dir.py +395 -0
  49. toolplane/toolkits/standalone_tools/read_file.py +346 -0
  50. toolplane/toolkits/standalone_tools/replace_string_in_file.py +407 -0
  51. toolplane/toolkits/standalone_tools/run_tests.py +66 -0
  52. toolplane/toolkits/standalone_tools/semantic_search.py +485 -0
  53. toolplane/toolkits/standalone_tools/standalone_toolkit.py +979 -0
  54. toolplane/toolkits/standalone_tools/test_failure_analysis.py +618 -0
  55. toolplane/toolkits/standalone_tools/test_standalone_toolkit.py +517 -0
  56. toolplane/toolkits/swe/__init__.py +35 -0
  57. toolplane/toolkits/swe/create_directory.py +15 -0
  58. toolplane/toolkits/swe/create_file.py +15 -0
  59. toolplane/toolkits/swe/descriptions.py +273 -0
  60. toolplane/toolkits/swe/execute_bash.py +93 -0
  61. toolplane/toolkits/swe/file_editor.py +775 -0
  62. toolplane/toolkits/swe/file_search.py +16 -0
  63. toolplane/toolkits/swe/finish.py +50 -0
  64. toolplane/toolkits/swe/grep_search.py +19 -0
  65. toolplane/toolkits/swe/list_dir.py +407 -0
  66. toolplane/toolkits/swe/read_file.py +18 -0
  67. toolplane/toolkits/swe/replace_string_in_file.py +17 -0
  68. toolplane/toolkits/swe/search.py +260 -0
  69. toolplane/toolkits/swe/semantic_search.py +20 -0
  70. toolplane/toolkits/swe/str_replace_editor.py +647 -0
  71. toolplane/toolkits/swe/submit.py +29 -0
  72. toolplane/toolkits/swe/swe_toolkit.py +1296 -0
  73. toolplane/toolplane_client.py +686 -0
  74. toolplane/toolplane_http_client.py +681 -0
  75. toolplane/utils/__init__.py +3 -0
  76. toolplane/utils/schema.py +146 -0
  77. toolplane_python_client-0.1.0.dist-info/METADATA +543 -0
  78. toolplane_python_client-0.1.0.dist-info/RECORD +81 -0
  79. toolplane_python_client-0.1.0.dist-info/WHEEL +5 -0
  80. toolplane_python_client-0.1.0.dist-info/entry_points.txt +2 -0
  81. 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