langchain-skilllite 0.1.0__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.
- langchain_skilllite-0.1.0/LICENSE +22 -0
- langchain_skilllite-0.1.0/PKG-INFO +203 -0
- langchain_skilllite-0.1.0/README.md +157 -0
- langchain_skilllite-0.1.0/langchain_skilllite/__init__.py +54 -0
- langchain_skilllite-0.1.0/langchain_skilllite/_version.py +4 -0
- langchain_skilllite-0.1.0/langchain_skilllite/callbacks.py +166 -0
- langchain_skilllite-0.1.0/langchain_skilllite/tools.py +526 -0
- langchain_skilllite-0.1.0/langchain_skilllite.egg-info/PKG-INFO +203 -0
- langchain_skilllite-0.1.0/langchain_skilllite.egg-info/SOURCES.txt +12 -0
- langchain_skilllite-0.1.0/langchain_skilllite.egg-info/dependency_links.txt +1 -0
- langchain_skilllite-0.1.0/langchain_skilllite.egg-info/requires.txt +18 -0
- langchain_skilllite-0.1.0/langchain_skilllite.egg-info/top_level.txt +1 -0
- langchain_skilllite-0.1.0/pyproject.toml +95 -0
- langchain_skilllite-0.1.0/setup.cfg +4 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 SkillLite Team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: langchain-skilllite
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: LangChain integration for SkillLite - Lightweight sandboxed Python skill execution engine
|
|
5
|
+
Author-email: SkillLite Team <skilllite@example.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/EXboys/langchain-skilllite
|
|
8
|
+
Project-URL: Documentation, https://github.com/EXboys/langchain-skilllite#readme
|
|
9
|
+
Project-URL: Repository, https://github.com/EXboys/langchain-skilllite
|
|
10
|
+
Project-URL: Issues, https://github.com/EXboys/langchain-skilllite/issues
|
|
11
|
+
Project-URL: LangChain, https://python.langchain.com/
|
|
12
|
+
Project-URL: SkillLite, https://github.com/EXboys/skilllite
|
|
13
|
+
Keywords: langchain,skilllite,agent,tools,sandbox,llm,skills,python-execution
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Operating System :: MacOS
|
|
18
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
19
|
+
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
25
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
26
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
27
|
+
Requires-Python: >=3.9
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
License-File: LICENSE
|
|
30
|
+
Requires-Dist: langchain-core>=0.3.0
|
|
31
|
+
Requires-Dist: skilllite>=0.1.1
|
|
32
|
+
Provides-Extra: langgraph
|
|
33
|
+
Requires-Dist: langgraph>=0.2.0; extra == "langgraph"
|
|
34
|
+
Provides-Extra: test
|
|
35
|
+
Requires-Dist: pytest>=7.0; extra == "test"
|
|
36
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "test"
|
|
37
|
+
Requires-Dist: langchain-tests>=0.3.0; extra == "test"
|
|
38
|
+
Provides-Extra: dev
|
|
39
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
40
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
41
|
+
Requires-Dist: langchain-tests>=0.3.0; extra == "dev"
|
|
42
|
+
Requires-Dist: black>=23.0; extra == "dev"
|
|
43
|
+
Requires-Dist: mypy>=1.0; extra == "dev"
|
|
44
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
45
|
+
Dynamic: license-file
|
|
46
|
+
|
|
47
|
+
# langchain-skilllite
|
|
48
|
+
|
|
49
|
+
[](https://badge.fury.io/py/langchain-skilllite)
|
|
50
|
+
[](https://opensource.org/licenses/MIT)
|
|
51
|
+
|
|
52
|
+
LangChain integration for [SkillLite](https://github.com/EXboys/skilllite) - a lightweight sandboxed Python skill execution engine.
|
|
53
|
+
|
|
54
|
+
## Features
|
|
55
|
+
|
|
56
|
+
- 🔒 **Sandboxed Execution** - All skills run in a Rust-based sandbox (skillbox)
|
|
57
|
+
- 📝 **Declarative Skills** - Define skills via SKILL.md, no Python wrappers needed
|
|
58
|
+
- 🔍 **Security Scanning** - Pre-execution code analysis for dangerous operations
|
|
59
|
+
- ✅ **Confirmation Callbacks** - User approval for high-severity security issues
|
|
60
|
+
- ⚡ **Async Support** - Full async support for LangGraph agents
|
|
61
|
+
|
|
62
|
+
## Installation
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pip install langchain-skilllite
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
This will also install the required dependencies:
|
|
69
|
+
- `langchain-core>=0.3.0`
|
|
70
|
+
- `skilllite>=0.1.1`
|
|
71
|
+
|
|
72
|
+
## Quick Start
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
from langchain_skilllite import SkillLiteToolkit
|
|
76
|
+
from langchain_openai import ChatOpenAI
|
|
77
|
+
from langgraph.prebuilt import create_react_agent
|
|
78
|
+
|
|
79
|
+
# Load all skills from a directory as LangChain tools
|
|
80
|
+
tools = SkillLiteToolkit.from_directory("./skills")
|
|
81
|
+
|
|
82
|
+
# Create a LangGraph agent
|
|
83
|
+
agent = create_react_agent(ChatOpenAI(model="gpt-4"), tools)
|
|
84
|
+
|
|
85
|
+
# Run the agent
|
|
86
|
+
result = agent.invoke({
|
|
87
|
+
"messages": [("user", "Calculate 15 + 27 using the calculator skill")]
|
|
88
|
+
})
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Usage
|
|
92
|
+
|
|
93
|
+
### Basic Usage with SkillManager
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
from skilllite import SkillManager
|
|
97
|
+
from langchain_skilllite import SkillLiteToolkit
|
|
98
|
+
|
|
99
|
+
# Create a SkillManager
|
|
100
|
+
manager = SkillManager(skills_dir="./skills")
|
|
101
|
+
|
|
102
|
+
# Convert all skills to LangChain tools
|
|
103
|
+
tools = SkillLiteToolkit.from_manager(manager)
|
|
104
|
+
|
|
105
|
+
# Or select specific skills
|
|
106
|
+
tools = SkillLiteToolkit.from_manager(
|
|
107
|
+
manager,
|
|
108
|
+
skill_names=["calculator", "web_search"],
|
|
109
|
+
allow_network=True,
|
|
110
|
+
timeout=60
|
|
111
|
+
)
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Security Levels
|
|
115
|
+
|
|
116
|
+
SkillLite supports three sandbox security levels:
|
|
117
|
+
|
|
118
|
+
| Level | Description |
|
|
119
|
+
|-------|-------------|
|
|
120
|
+
| 1 | No sandbox - direct execution (fastest, least secure) |
|
|
121
|
+
| 2 | Sandbox isolation only |
|
|
122
|
+
| 3 | Sandbox + security scanning (default, most secure) |
|
|
123
|
+
|
|
124
|
+
```python
|
|
125
|
+
# Level 3 with confirmation callback for high-severity issues
|
|
126
|
+
def confirm_execution(report: str, scan_id: str) -> bool:
|
|
127
|
+
print(report)
|
|
128
|
+
return input("Proceed? [y/N]: ").lower() == 'y'
|
|
129
|
+
|
|
130
|
+
tools = SkillLiteToolkit.from_directory(
|
|
131
|
+
"./skills",
|
|
132
|
+
sandbox_level=3,
|
|
133
|
+
confirmation_callback=confirm_execution
|
|
134
|
+
)
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Async Confirmation (for LangGraph)
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
import asyncio
|
|
141
|
+
|
|
142
|
+
async def async_confirm(report: str, scan_id: str) -> bool:
|
|
143
|
+
print(report)
|
|
144
|
+
# In a real app, this might be a UI prompt
|
|
145
|
+
return True
|
|
146
|
+
|
|
147
|
+
tools = SkillLiteToolkit.from_directory(
|
|
148
|
+
"./skills",
|
|
149
|
+
sandbox_level=3,
|
|
150
|
+
async_confirmation_callback=async_confirm
|
|
151
|
+
)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Callback Handler for Monitoring
|
|
155
|
+
|
|
156
|
+
```python
|
|
157
|
+
from langchain_skilllite import SkillLiteCallbackHandler
|
|
158
|
+
|
|
159
|
+
handler = SkillLiteCallbackHandler(verbose=True)
|
|
160
|
+
|
|
161
|
+
# Use with agent
|
|
162
|
+
result = agent.invoke(
|
|
163
|
+
{"messages": [("user", "Run my skill")]},
|
|
164
|
+
config={"callbacks": [handler]}
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
# Get execution summary
|
|
168
|
+
print(handler.get_execution_summary())
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## API Reference
|
|
172
|
+
|
|
173
|
+
### SkillLiteTool
|
|
174
|
+
|
|
175
|
+
LangChain `BaseTool` adapter for a single SkillLite skill.
|
|
176
|
+
|
|
177
|
+
### SkillLiteToolkit
|
|
178
|
+
|
|
179
|
+
Factory class for creating multiple `SkillLiteTool` instances.
|
|
180
|
+
|
|
181
|
+
- `from_manager(manager, ...)` - Create tools from a SkillManager
|
|
182
|
+
- `from_directory(skills_dir, ...)` - Create tools from a skills directory
|
|
183
|
+
|
|
184
|
+
### SkillLiteCallbackHandler
|
|
185
|
+
|
|
186
|
+
LangChain callback handler for monitoring skill execution.
|
|
187
|
+
|
|
188
|
+
## Requirements
|
|
189
|
+
|
|
190
|
+
- Python >= 3.9
|
|
191
|
+
- langchain-core >= 0.3.0
|
|
192
|
+
- skilllite >= 0.1.1
|
|
193
|
+
|
|
194
|
+
## License
|
|
195
|
+
|
|
196
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
197
|
+
|
|
198
|
+
## Links
|
|
199
|
+
|
|
200
|
+
- [SkillLite Repository](https://github.com/EXboys/skilllite)
|
|
201
|
+
- [LangChain Documentation](https://python.langchain.com/)
|
|
202
|
+
- [LangGraph Documentation](https://langchain-ai.github.io/langgraph/)
|
|
203
|
+
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# langchain-skilllite
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/py/langchain-skilllite)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
6
|
+
LangChain integration for [SkillLite](https://github.com/EXboys/skilllite) - a lightweight sandboxed Python skill execution engine.
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- 🔒 **Sandboxed Execution** - All skills run in a Rust-based sandbox (skillbox)
|
|
11
|
+
- 📝 **Declarative Skills** - Define skills via SKILL.md, no Python wrappers needed
|
|
12
|
+
- 🔍 **Security Scanning** - Pre-execution code analysis for dangerous operations
|
|
13
|
+
- ✅ **Confirmation Callbacks** - User approval for high-severity security issues
|
|
14
|
+
- ⚡ **Async Support** - Full async support for LangGraph agents
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pip install langchain-skilllite
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
This will also install the required dependencies:
|
|
23
|
+
- `langchain-core>=0.3.0`
|
|
24
|
+
- `skilllite>=0.1.1`
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
from langchain_skilllite import SkillLiteToolkit
|
|
30
|
+
from langchain_openai import ChatOpenAI
|
|
31
|
+
from langgraph.prebuilt import create_react_agent
|
|
32
|
+
|
|
33
|
+
# Load all skills from a directory as LangChain tools
|
|
34
|
+
tools = SkillLiteToolkit.from_directory("./skills")
|
|
35
|
+
|
|
36
|
+
# Create a LangGraph agent
|
|
37
|
+
agent = create_react_agent(ChatOpenAI(model="gpt-4"), tools)
|
|
38
|
+
|
|
39
|
+
# Run the agent
|
|
40
|
+
result = agent.invoke({
|
|
41
|
+
"messages": [("user", "Calculate 15 + 27 using the calculator skill")]
|
|
42
|
+
})
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Usage
|
|
46
|
+
|
|
47
|
+
### Basic Usage with SkillManager
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
from skilllite import SkillManager
|
|
51
|
+
from langchain_skilllite import SkillLiteToolkit
|
|
52
|
+
|
|
53
|
+
# Create a SkillManager
|
|
54
|
+
manager = SkillManager(skills_dir="./skills")
|
|
55
|
+
|
|
56
|
+
# Convert all skills to LangChain tools
|
|
57
|
+
tools = SkillLiteToolkit.from_manager(manager)
|
|
58
|
+
|
|
59
|
+
# Or select specific skills
|
|
60
|
+
tools = SkillLiteToolkit.from_manager(
|
|
61
|
+
manager,
|
|
62
|
+
skill_names=["calculator", "web_search"],
|
|
63
|
+
allow_network=True,
|
|
64
|
+
timeout=60
|
|
65
|
+
)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Security Levels
|
|
69
|
+
|
|
70
|
+
SkillLite supports three sandbox security levels:
|
|
71
|
+
|
|
72
|
+
| Level | Description |
|
|
73
|
+
|-------|-------------|
|
|
74
|
+
| 1 | No sandbox - direct execution (fastest, least secure) |
|
|
75
|
+
| 2 | Sandbox isolation only |
|
|
76
|
+
| 3 | Sandbox + security scanning (default, most secure) |
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
# Level 3 with confirmation callback for high-severity issues
|
|
80
|
+
def confirm_execution(report: str, scan_id: str) -> bool:
|
|
81
|
+
print(report)
|
|
82
|
+
return input("Proceed? [y/N]: ").lower() == 'y'
|
|
83
|
+
|
|
84
|
+
tools = SkillLiteToolkit.from_directory(
|
|
85
|
+
"./skills",
|
|
86
|
+
sandbox_level=3,
|
|
87
|
+
confirmation_callback=confirm_execution
|
|
88
|
+
)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Async Confirmation (for LangGraph)
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
import asyncio
|
|
95
|
+
|
|
96
|
+
async def async_confirm(report: str, scan_id: str) -> bool:
|
|
97
|
+
print(report)
|
|
98
|
+
# In a real app, this might be a UI prompt
|
|
99
|
+
return True
|
|
100
|
+
|
|
101
|
+
tools = SkillLiteToolkit.from_directory(
|
|
102
|
+
"./skills",
|
|
103
|
+
sandbox_level=3,
|
|
104
|
+
async_confirmation_callback=async_confirm
|
|
105
|
+
)
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Callback Handler for Monitoring
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
from langchain_skilllite import SkillLiteCallbackHandler
|
|
112
|
+
|
|
113
|
+
handler = SkillLiteCallbackHandler(verbose=True)
|
|
114
|
+
|
|
115
|
+
# Use with agent
|
|
116
|
+
result = agent.invoke(
|
|
117
|
+
{"messages": [("user", "Run my skill")]},
|
|
118
|
+
config={"callbacks": [handler]}
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
# Get execution summary
|
|
122
|
+
print(handler.get_execution_summary())
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## API Reference
|
|
126
|
+
|
|
127
|
+
### SkillLiteTool
|
|
128
|
+
|
|
129
|
+
LangChain `BaseTool` adapter for a single SkillLite skill.
|
|
130
|
+
|
|
131
|
+
### SkillLiteToolkit
|
|
132
|
+
|
|
133
|
+
Factory class for creating multiple `SkillLiteTool` instances.
|
|
134
|
+
|
|
135
|
+
- `from_manager(manager, ...)` - Create tools from a SkillManager
|
|
136
|
+
- `from_directory(skills_dir, ...)` - Create tools from a skills directory
|
|
137
|
+
|
|
138
|
+
### SkillLiteCallbackHandler
|
|
139
|
+
|
|
140
|
+
LangChain callback handler for monitoring skill execution.
|
|
141
|
+
|
|
142
|
+
## Requirements
|
|
143
|
+
|
|
144
|
+
- Python >= 3.9
|
|
145
|
+
- langchain-core >= 0.3.0
|
|
146
|
+
- skilllite >= 0.1.1
|
|
147
|
+
|
|
148
|
+
## License
|
|
149
|
+
|
|
150
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
151
|
+
|
|
152
|
+
## Links
|
|
153
|
+
|
|
154
|
+
- [SkillLite Repository](https://github.com/EXboys/skilllite)
|
|
155
|
+
- [LangChain Documentation](https://python.langchain.com/)
|
|
156
|
+
- [LangGraph Documentation](https://langchain-ai.github.io/langgraph/)
|
|
157
|
+
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""
|
|
2
|
+
LangChain integration for SkillLite.
|
|
3
|
+
|
|
4
|
+
This package provides LangChain-compatible tools for executing SkillLite skills
|
|
5
|
+
in a sandboxed environment. It acts as a thin adapter layer on top of the
|
|
6
|
+
skilllite core package.
|
|
7
|
+
|
|
8
|
+
Key Features:
|
|
9
|
+
- SkillLiteTool: LangChain BaseTool adapter for individual skills
|
|
10
|
+
- SkillLiteToolkit: Convenient toolkit for loading multiple skills
|
|
11
|
+
- Security scanning and confirmation callbacks for sandbox level 3
|
|
12
|
+
- Full async support for LangGraph agents
|
|
13
|
+
|
|
14
|
+
Installation:
|
|
15
|
+
pip install langchain-skilllite
|
|
16
|
+
|
|
17
|
+
Quick Start:
|
|
18
|
+
```python
|
|
19
|
+
from langchain_skilllite import SkillLiteToolkit
|
|
20
|
+
from langchain_openai import ChatOpenAI
|
|
21
|
+
from langgraph.prebuilt import create_react_agent
|
|
22
|
+
|
|
23
|
+
# Load skills as LangChain tools
|
|
24
|
+
tools = SkillLiteToolkit.from_directory("./skills")
|
|
25
|
+
|
|
26
|
+
# Use with any LangChain agent
|
|
27
|
+
agent = create_react_agent(ChatOpenAI(), tools)
|
|
28
|
+
result = agent.invoke({"messages": [("user", "Run my skill")]})
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
For more information, see:
|
|
32
|
+
- SkillLite: https://github.com/EXboys/skilllite
|
|
33
|
+
- LangChain: https://python.langchain.com/
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
from langchain_skilllite.tools import (
|
|
37
|
+
SkillLiteTool,
|
|
38
|
+
SkillLiteToolkit,
|
|
39
|
+
)
|
|
40
|
+
from langchain_skilllite.callbacks import (
|
|
41
|
+
SkillLiteCallbackHandler,
|
|
42
|
+
)
|
|
43
|
+
from langchain_skilllite._version import __version__
|
|
44
|
+
|
|
45
|
+
__all__ = [
|
|
46
|
+
# Core Tools
|
|
47
|
+
"SkillLiteTool",
|
|
48
|
+
"SkillLiteToolkit",
|
|
49
|
+
# Callbacks
|
|
50
|
+
"SkillLiteCallbackHandler",
|
|
51
|
+
# Version
|
|
52
|
+
"__version__",
|
|
53
|
+
]
|
|
54
|
+
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"""
|
|
2
|
+
LangChain callback handlers for SkillLite.
|
|
3
|
+
|
|
4
|
+
This module provides callback handlers for integrating SkillLite
|
|
5
|
+
with LangChain's callback system for logging, tracing, and monitoring.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import logging
|
|
11
|
+
from typing import Any, Dict, List, Optional, TYPE_CHECKING, Union
|
|
12
|
+
from uuid import UUID
|
|
13
|
+
|
|
14
|
+
from langchain_core.callbacks import BaseCallbackHandler
|
|
15
|
+
from langchain_core.outputs import LLMResult
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from langchain_core.agents import AgentAction, AgentFinish
|
|
19
|
+
from langchain_core.messages import BaseMessage
|
|
20
|
+
|
|
21
|
+
logger = logging.getLogger(__name__)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class SkillLiteCallbackHandler(BaseCallbackHandler):
|
|
25
|
+
"""
|
|
26
|
+
LangChain callback handler for SkillLite skill execution.
|
|
27
|
+
|
|
28
|
+
This handler logs skill execution events and can be used for
|
|
29
|
+
monitoring, debugging, and auditing SkillLite tool usage.
|
|
30
|
+
|
|
31
|
+
Usage:
|
|
32
|
+
from langchain_skilllite import SkillLiteCallbackHandler
|
|
33
|
+
|
|
34
|
+
handler = SkillLiteCallbackHandler(verbose=True)
|
|
35
|
+
|
|
36
|
+
# Use with LangChain agent
|
|
37
|
+
agent.invoke({"input": "..."}, config={"callbacks": [handler]})
|
|
38
|
+
|
|
39
|
+
Attributes:
|
|
40
|
+
verbose: Whether to print execution details
|
|
41
|
+
execution_log: List of execution events
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
def __init__(
|
|
45
|
+
self,
|
|
46
|
+
verbose: bool = False,
|
|
47
|
+
log_level: int = logging.INFO,
|
|
48
|
+
):
|
|
49
|
+
"""
|
|
50
|
+
Initialize the callback handler.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
verbose: If True, print execution details to stdout
|
|
54
|
+
log_level: Logging level for internal logging
|
|
55
|
+
"""
|
|
56
|
+
super().__init__()
|
|
57
|
+
self.verbose = verbose
|
|
58
|
+
self.log_level = log_level
|
|
59
|
+
self.execution_log: List[Dict[str, Any]] = []
|
|
60
|
+
self._current_tool: Optional[str] = None
|
|
61
|
+
|
|
62
|
+
def on_tool_start(
|
|
63
|
+
self,
|
|
64
|
+
serialized: Dict[str, Any],
|
|
65
|
+
input_str: str,
|
|
66
|
+
*,
|
|
67
|
+
run_id: UUID,
|
|
68
|
+
parent_run_id: Optional[UUID] = None,
|
|
69
|
+
tags: Optional[List[str]] = None,
|
|
70
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
71
|
+
inputs: Optional[Dict[str, Any]] = None,
|
|
72
|
+
**kwargs: Any,
|
|
73
|
+
) -> None:
|
|
74
|
+
"""Called when a tool starts running."""
|
|
75
|
+
tool_name = serialized.get("name", "unknown")
|
|
76
|
+
self._current_tool = tool_name
|
|
77
|
+
|
|
78
|
+
event = {
|
|
79
|
+
"event": "tool_start",
|
|
80
|
+
"tool_name": tool_name,
|
|
81
|
+
"run_id": str(run_id),
|
|
82
|
+
"input": input_str[:200] if input_str else None,
|
|
83
|
+
}
|
|
84
|
+
self.execution_log.append(event)
|
|
85
|
+
|
|
86
|
+
if self.verbose:
|
|
87
|
+
print(f"🔧 [SkillLite] Starting tool: {tool_name}")
|
|
88
|
+
logger.log(self.log_level, f"Tool started: {tool_name}")
|
|
89
|
+
|
|
90
|
+
def on_tool_end(
|
|
91
|
+
self,
|
|
92
|
+
output: Any,
|
|
93
|
+
*,
|
|
94
|
+
run_id: UUID,
|
|
95
|
+
parent_run_id: Optional[UUID] = None,
|
|
96
|
+
**kwargs: Any,
|
|
97
|
+
) -> None:
|
|
98
|
+
"""Called when a tool finishes."""
|
|
99
|
+
# Handle different output types (str, ToolMessage, etc.)
|
|
100
|
+
if isinstance(output, str):
|
|
101
|
+
output_preview = output[:200] if output else None
|
|
102
|
+
elif hasattr(output, "content"):
|
|
103
|
+
# ToolMessage or similar object
|
|
104
|
+
content = output.content
|
|
105
|
+
output_preview = content[:200] if isinstance(content, str) and content else str(content)[:200]
|
|
106
|
+
else:
|
|
107
|
+
output_preview = str(output)[:200] if output else None
|
|
108
|
+
|
|
109
|
+
event = {
|
|
110
|
+
"event": "tool_end",
|
|
111
|
+
"tool_name": self._current_tool,
|
|
112
|
+
"run_id": str(run_id),
|
|
113
|
+
"output_preview": output_preview,
|
|
114
|
+
"success": True,
|
|
115
|
+
}
|
|
116
|
+
self.execution_log.append(event)
|
|
117
|
+
|
|
118
|
+
if self.verbose:
|
|
119
|
+
print(f"✅ [SkillLite] Tool completed: {self._current_tool}")
|
|
120
|
+
logger.log(self.log_level, f"Tool completed: {self._current_tool}")
|
|
121
|
+
|
|
122
|
+
self._current_tool = None
|
|
123
|
+
|
|
124
|
+
def on_tool_error(
|
|
125
|
+
self,
|
|
126
|
+
error: BaseException,
|
|
127
|
+
*,
|
|
128
|
+
run_id: UUID,
|
|
129
|
+
parent_run_id: Optional[UUID] = None,
|
|
130
|
+
**kwargs: Any,
|
|
131
|
+
) -> None:
|
|
132
|
+
"""Called when a tool errors."""
|
|
133
|
+
event = {
|
|
134
|
+
"event": "tool_error",
|
|
135
|
+
"tool_name": self._current_tool,
|
|
136
|
+
"run_id": str(run_id),
|
|
137
|
+
"error": str(error),
|
|
138
|
+
"success": False,
|
|
139
|
+
}
|
|
140
|
+
self.execution_log.append(event)
|
|
141
|
+
|
|
142
|
+
if self.verbose:
|
|
143
|
+
print(f"❌ [SkillLite] Tool error: {self._current_tool} - {error}")
|
|
144
|
+
logger.error(f"Tool error: {self._current_tool} - {error}")
|
|
145
|
+
|
|
146
|
+
self._current_tool = None
|
|
147
|
+
|
|
148
|
+
def get_execution_summary(self) -> Dict[str, Any]:
|
|
149
|
+
"""Get a summary of all execution events."""
|
|
150
|
+
total = len(self.execution_log)
|
|
151
|
+
tool_starts = sum(1 for e in self.execution_log if e["event"] == "tool_start")
|
|
152
|
+
tool_ends = sum(1 for e in self.execution_log if e["event"] == "tool_end")
|
|
153
|
+
tool_errors = sum(1 for e in self.execution_log if e["event"] == "tool_error")
|
|
154
|
+
|
|
155
|
+
return {
|
|
156
|
+
"total_events": total,
|
|
157
|
+
"tool_executions": tool_starts,
|
|
158
|
+
"successful": tool_ends,
|
|
159
|
+
"errors": tool_errors,
|
|
160
|
+
"success_rate": tool_ends / tool_starts if tool_starts > 0 else 0,
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
def clear_log(self) -> None:
|
|
164
|
+
"""Clear the execution log."""
|
|
165
|
+
self.execution_log.clear()
|
|
166
|
+
|