haiku-skills-code-execution 0.7.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.
- haiku_skills_code_execution-0.7.0/.gitignore +26 -0
- haiku_skills_code_execution-0.7.0/PKG-INFO +36 -0
- haiku_skills_code_execution-0.7.0/README.md +15 -0
- haiku_skills_code_execution-0.7.0/haiku_skills_code_execution/__init__.py +83 -0
- haiku_skills_code_execution-0.7.0/haiku_skills_code_execution/code-execution/SKILL.md +27 -0
- haiku_skills_code_execution-0.7.0/haiku_skills_code_execution/scripts/__init__.py +0 -0
- haiku_skills_code_execution-0.7.0/haiku_skills_code_execution/scripts/run_code.py +45 -0
- haiku_skills_code_execution-0.7.0/pyproject.toml +33 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Python-generated files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[oc]
|
|
4
|
+
build/
|
|
5
|
+
dist/
|
|
6
|
+
wheels/
|
|
7
|
+
*.egg-info
|
|
8
|
+
**/.DS_Store
|
|
9
|
+
|
|
10
|
+
# Virtual environments
|
|
11
|
+
.venv
|
|
12
|
+
|
|
13
|
+
# tests
|
|
14
|
+
.coverage*
|
|
15
|
+
.pytest_cache/
|
|
16
|
+
.ruff_cache/
|
|
17
|
+
|
|
18
|
+
# mkdocs
|
|
19
|
+
site/
|
|
20
|
+
|
|
21
|
+
# environment variables and config files
|
|
22
|
+
.env
|
|
23
|
+
TODO.md
|
|
24
|
+
PLAN.md
|
|
25
|
+
DEVNOTES.md
|
|
26
|
+
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: haiku-skills-code-execution
|
|
3
|
+
Version: 0.7.0
|
|
4
|
+
Summary: Code execution skill for haiku.skills
|
|
5
|
+
Project-URL: Homepage, https://github.com/ggozad/haiku.skills
|
|
6
|
+
Project-URL: Repository, https://github.com/ggozad/haiku.skills
|
|
7
|
+
Project-URL: Issues, https://github.com/ggozad/haiku.skills/issues
|
|
8
|
+
Author-email: Yiorgis Gozadinos <ggozadinos@gmail.com>
|
|
9
|
+
License: MIT
|
|
10
|
+
Keywords: agent-skills,code-execution,haiku-skills,pydantic-ai,sandbox
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Operating System :: MacOS
|
|
14
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Typing :: Typed
|
|
17
|
+
Requires-Python: >=3.13
|
|
18
|
+
Requires-Dist: haiku-skills>=0.7.0
|
|
19
|
+
Requires-Dist: pydantic-monty>=0.0.4
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
# code-execution
|
|
23
|
+
|
|
24
|
+
Sandboxed Python code execution skill for [haiku.skills](https://github.com/ggozad/haiku.skills) using [pydantic-monty](https://github.com/pydantic/pydantic-monty).
|
|
25
|
+
|
|
26
|
+
Code runs in a minimal sandboxed interpreter with no file, network, or environment access. See the SKILL.md for full sandbox limitations.
|
|
27
|
+
|
|
28
|
+
## Tools
|
|
29
|
+
|
|
30
|
+
- **run_code** — Execute Python code in the sandbox and return the output
|
|
31
|
+
|
|
32
|
+
## Installation
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
uv add haiku-skills-code-execution
|
|
36
|
+
```
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# code-execution
|
|
2
|
+
|
|
3
|
+
Sandboxed Python code execution skill for [haiku.skills](https://github.com/ggozad/haiku.skills) using [pydantic-monty](https://github.com/pydantic/pydantic-monty).
|
|
4
|
+
|
|
5
|
+
Code runs in a minimal sandboxed interpreter with no file, network, or environment access. See the SKILL.md for full sandbox limitations.
|
|
6
|
+
|
|
7
|
+
## Tools
|
|
8
|
+
|
|
9
|
+
- **run_code** — Execute Python code in the sandbox and return the output
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
uv add haiku-skills-code-execution
|
|
15
|
+
```
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel
|
|
4
|
+
from pydantic_ai import RunContext
|
|
5
|
+
|
|
6
|
+
from haiku.skills.models import Skill, SkillSource
|
|
7
|
+
from haiku.skills.parser import parse_skill_md
|
|
8
|
+
from haiku.skills.state import SkillRunDeps
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Execution(BaseModel):
|
|
12
|
+
code: str
|
|
13
|
+
stdout: str
|
|
14
|
+
result: str | None
|
|
15
|
+
success: bool
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class CodeState(BaseModel):
|
|
19
|
+
executions: list[Execution] = []
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def run_code(ctx: RunContext[SkillRunDeps], code: str) -> str:
|
|
23
|
+
"""Execute Python code and return the output.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
code: The Python code to execute.
|
|
27
|
+
"""
|
|
28
|
+
from haiku_skills_code_execution.scripts.run_code import main
|
|
29
|
+
|
|
30
|
+
result = main(code)
|
|
31
|
+
|
|
32
|
+
if ctx.deps and ctx.deps.state and isinstance(ctx.deps.state, CodeState):
|
|
33
|
+
# Parse the formatted output to extract stdout and result
|
|
34
|
+
stdout = ""
|
|
35
|
+
result_value = None
|
|
36
|
+
success = True
|
|
37
|
+
|
|
38
|
+
lines = result.split("\n")
|
|
39
|
+
i = 0
|
|
40
|
+
# Skip the code block
|
|
41
|
+
while i < len(lines) and not (
|
|
42
|
+
lines[i].startswith("stdout:")
|
|
43
|
+
or lines[i].startswith("result:")
|
|
44
|
+
or "no output" in lines[i].lower()
|
|
45
|
+
):
|
|
46
|
+
i += 1
|
|
47
|
+
|
|
48
|
+
if i < len(lines) and lines[i].startswith("stdout:"):
|
|
49
|
+
stdout_parts = [lines[i][len("stdout:") :].strip()]
|
|
50
|
+
i += 1
|
|
51
|
+
while i < len(lines) and not lines[i].startswith("result:"):
|
|
52
|
+
stdout_parts.append(lines[i])
|
|
53
|
+
i += 1
|
|
54
|
+
stdout = "\n".join(stdout_parts).strip()
|
|
55
|
+
|
|
56
|
+
if i < len(lines) and lines[i].startswith("result:"):
|
|
57
|
+
result_value = lines[i][len("result:") :].strip()
|
|
58
|
+
|
|
59
|
+
ctx.deps.state.executions.append(
|
|
60
|
+
Execution(
|
|
61
|
+
code=code,
|
|
62
|
+
stdout=stdout,
|
|
63
|
+
result=result_value,
|
|
64
|
+
success=success,
|
|
65
|
+
)
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
return result
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def create_skill() -> Skill:
|
|
72
|
+
skill_dir = Path(__file__).parent / "code-execution"
|
|
73
|
+
metadata, instructions = parse_skill_md(skill_dir / "SKILL.md")
|
|
74
|
+
|
|
75
|
+
return Skill(
|
|
76
|
+
metadata=metadata,
|
|
77
|
+
source=SkillSource.ENTRYPOINT,
|
|
78
|
+
path=skill_dir,
|
|
79
|
+
instructions=instructions,
|
|
80
|
+
tools=[run_code],
|
|
81
|
+
state_type=CodeState,
|
|
82
|
+
state_namespace="code-execution",
|
|
83
|
+
)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: code-execution
|
|
3
|
+
description: Write and execute Python code to solve tasks.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Code Execution
|
|
7
|
+
|
|
8
|
+
You are a coding agent. When given a task description, write Python code to
|
|
9
|
+
accomplish it and execute it using the run_code tool.
|
|
10
|
+
|
|
11
|
+
- Translate the task description into working Python code
|
|
12
|
+
- Execute the code and return the result
|
|
13
|
+
- Report any errors clearly and retry with a fix if needed
|
|
14
|
+
|
|
15
|
+
## Sandbox limitations
|
|
16
|
+
|
|
17
|
+
Code runs in Monty, a minimal sandboxed Python interpreter. Only these
|
|
18
|
+
features are available:
|
|
19
|
+
|
|
20
|
+
- Basic types: int, float, str, bool, list, dict, tuple, None
|
|
21
|
+
- Control flow: if/elif/else, for, while, break, continue
|
|
22
|
+
- Functions: def, lambda, return (no classes)
|
|
23
|
+
- Built-in modules: sys, typing, asyncio, dataclasses, json
|
|
24
|
+
- Built-in functions: print, len, range, enumerate, zip, map, filter, sorted, reversed, min, max, sum, abs, round, isinstance, type, str, int, float, bool, list, dict, tuple, set
|
|
25
|
+
|
|
26
|
+
**Not available**: standard library (os, math, re, etc.), third-party packages,
|
|
27
|
+
file/network/environment access, classes, match statements.
|
|
File without changes
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# /// script
|
|
2
|
+
# requires-python = ">=3.13"
|
|
3
|
+
# dependencies = ["pydantic-monty"]
|
|
4
|
+
# ///
|
|
5
|
+
"""Execute Python code safely in a sandboxed environment."""
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
import sys
|
|
9
|
+
import tempfile
|
|
10
|
+
|
|
11
|
+
from pydantic_monty import Monty
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def main(code: str) -> str:
|
|
15
|
+
"""Execute Python code and return the output.
|
|
16
|
+
|
|
17
|
+
Args:
|
|
18
|
+
code: The Python code to execute.
|
|
19
|
+
"""
|
|
20
|
+
old_fd = os.dup(1)
|
|
21
|
+
tmp = tempfile.TemporaryFile(mode="w+")
|
|
22
|
+
os.dup2(tmp.fileno(), 1)
|
|
23
|
+
try:
|
|
24
|
+
result = Monty(code).run()
|
|
25
|
+
finally:
|
|
26
|
+
os.dup2(old_fd, 1)
|
|
27
|
+
os.close(old_fd)
|
|
28
|
+
|
|
29
|
+
tmp.seek(0)
|
|
30
|
+
stdout = tmp.read()
|
|
31
|
+
tmp.close()
|
|
32
|
+
|
|
33
|
+
parts = [f"```python\n{code}\n```"]
|
|
34
|
+
if stdout:
|
|
35
|
+
parts.append(f"stdout:\n{stdout}")
|
|
36
|
+
if result is not None:
|
|
37
|
+
parts.append(f"result: {result}")
|
|
38
|
+
if not stdout and result is None:
|
|
39
|
+
parts.append("Code executed successfully (no output).")
|
|
40
|
+
|
|
41
|
+
return "\n".join(parts)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
if __name__ == "__main__":
|
|
45
|
+
print(main(sys.argv[1]))
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "haiku-skills-code-execution"
|
|
3
|
+
version = "0.7.0"
|
|
4
|
+
description = "Code execution skill for haiku.skills"
|
|
5
|
+
authors = [{ name = "Yiorgis Gozadinos", email = "ggozadinos@gmail.com" }]
|
|
6
|
+
license = { text = "MIT" }
|
|
7
|
+
readme = { file = "README.md", content-type = "text/markdown" }
|
|
8
|
+
requires-python = ">=3.13"
|
|
9
|
+
keywords = ["haiku-skills", "agent-skills", "pydantic-ai", "code-execution", "sandbox"]
|
|
10
|
+
classifiers = [
|
|
11
|
+
"Development Status :: 4 - Beta",
|
|
12
|
+
"Intended Audience :: Developers",
|
|
13
|
+
"Operating System :: MacOS",
|
|
14
|
+
"Operating System :: POSIX :: Linux",
|
|
15
|
+
"Programming Language :: Python :: 3.13",
|
|
16
|
+
"Typing :: Typed",
|
|
17
|
+
]
|
|
18
|
+
dependencies = ["haiku.skills>=0.7.0", "pydantic-monty>=0.0.4"]
|
|
19
|
+
|
|
20
|
+
[project.urls]
|
|
21
|
+
Homepage = "https://github.com/ggozad/haiku.skills"
|
|
22
|
+
Repository = "https://github.com/ggozad/haiku.skills"
|
|
23
|
+
Issues = "https://github.com/ggozad/haiku.skills/issues"
|
|
24
|
+
|
|
25
|
+
[project.entry-points."haiku.skills"]
|
|
26
|
+
code-execution = "haiku_skills_code_execution:create_skill"
|
|
27
|
+
|
|
28
|
+
[tool.uv.sources]
|
|
29
|
+
haiku-skills = { workspace = true }
|
|
30
|
+
|
|
31
|
+
[build-system]
|
|
32
|
+
requires = ["hatchling"]
|
|
33
|
+
build-backend = "hatchling.build"
|