specialagent 0.0.1__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.
- specialagent-0.0.1/.github/workflows/pypi.yml +24 -0
- specialagent-0.0.1/PKG-INFO +8 -0
- specialagent-0.0.1/agent.py +105 -0
- specialagent-0.0.1/makefile +0 -0
- specialagent-0.0.1/pyproject.toml +25 -0
- specialagent-0.0.1/readme.md +0 -0
- specialagent-0.0.1/run +45 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
name: PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v*.*.*'
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
PyPI:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
permissions:
|
|
12
|
+
id-token: write
|
|
13
|
+
steps:
|
|
14
|
+
- name: Checkout
|
|
15
|
+
uses: actions/checkout@v5
|
|
16
|
+
|
|
17
|
+
- name: Setup uv
|
|
18
|
+
uses: astral-sh/setup-uv@v5
|
|
19
|
+
|
|
20
|
+
- name: Build
|
|
21
|
+
run: uv build
|
|
22
|
+
|
|
23
|
+
- name: Publish
|
|
24
|
+
run: uv publish
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: specialagent
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Author-email: Jon Craton <jncraton@gmail.com>
|
|
5
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
6
|
+
Classifier: Operating System :: OS Independent
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Requires-Python: >=3.9
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
import subprocess
|
|
4
|
+
|
|
5
|
+
def run_bash(command):
|
|
6
|
+
"""
|
|
7
|
+
Executes a bash command and returns the output.
|
|
8
|
+
>>> run_bash('echo "hello"')
|
|
9
|
+
'hello\\n'
|
|
10
|
+
"""
|
|
11
|
+
print(f"{command}")
|
|
12
|
+
|
|
13
|
+
result = subprocess.run(command, shell=True, capture_output=True, text=True)
|
|
14
|
+
return f'{result.stdout}{result.stderr}'
|
|
15
|
+
|
|
16
|
+
def write_file(path, content):
|
|
17
|
+
"""
|
|
18
|
+
Writes content to a file at the specified path.
|
|
19
|
+
>>> import tempfile
|
|
20
|
+
>>> with tempfile.NamedTemporaryFile() as tmp:
|
|
21
|
+
... write_file(tmp.name, 'test')
|
|
22
|
+
'File written to '...
|
|
23
|
+
"""
|
|
24
|
+
with open(path, 'w') as f:
|
|
25
|
+
f.write(content)
|
|
26
|
+
return f'File written to {path}'
|
|
27
|
+
|
|
28
|
+
def call_gemini(messages, tools):
|
|
29
|
+
import urllib.request
|
|
30
|
+
|
|
31
|
+
url = 'https://generativelanguage.googleapis.com/v1beta/models/gemma-4-26b-a4b-it:generateContent'
|
|
32
|
+
api_key = os.environ.get('GEMINI_API_KEY')
|
|
33
|
+
headers = {'Content-Type': 'application/json', 'x-goog-api-key': api_key}
|
|
34
|
+
data = json.dumps({'contents': messages, 'tools': [{'function_declarations': tools}]}).encode()
|
|
35
|
+
|
|
36
|
+
req = urllib.request.Request(url, data=data, headers=headers)
|
|
37
|
+
with urllib.request.urlopen(req) as response:
|
|
38
|
+
return json.loads(response.read().decode())
|
|
39
|
+
|
|
40
|
+
def main():
|
|
41
|
+
tools = [
|
|
42
|
+
{
|
|
43
|
+
'name': 'run_bash',
|
|
44
|
+
'description': 'Execute a command in the bash shell',
|
|
45
|
+
'parameters': {
|
|
46
|
+
'type': 'object',
|
|
47
|
+
'properties': {'command': {'type': 'string'}},
|
|
48
|
+
'required': ['command']
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
'name': 'write_file',
|
|
53
|
+
'description': 'Write text content to a file path',
|
|
54
|
+
'parameters': {
|
|
55
|
+
'type': 'object',
|
|
56
|
+
'properties': {
|
|
57
|
+
'path': {'type': 'string'},
|
|
58
|
+
'content': {'type': 'string'}
|
|
59
|
+
},
|
|
60
|
+
'required': ['path', 'content']
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
messages = []
|
|
66
|
+
user_input = input('Task: ')
|
|
67
|
+
messages.append({'role': 'user', 'parts': [{'text': user_input}]})
|
|
68
|
+
|
|
69
|
+
while True:
|
|
70
|
+
response = call_gemini(messages, tools)
|
|
71
|
+
parts = response['candidates'][0]['content']['parts']
|
|
72
|
+
text_parts = [p for p in parts if "text" in p]
|
|
73
|
+
function_calls = [p for p in parts if "functionCall" in p]
|
|
74
|
+
|
|
75
|
+
messages.append(response['candidates'][0]['content'])
|
|
76
|
+
|
|
77
|
+
if len(function_calls) == 0:
|
|
78
|
+
print(text_parts[0].get('text', 'Task complete.'))
|
|
79
|
+
break
|
|
80
|
+
|
|
81
|
+
for call in function_calls:
|
|
82
|
+
name = call['functionCall']['name']
|
|
83
|
+
args = call['functionCall']['args']
|
|
84
|
+
|
|
85
|
+
print(f'Executing {name} with {args}...')
|
|
86
|
+
|
|
87
|
+
if name == 'run_bash':
|
|
88
|
+
result = run_bash(args['command'])
|
|
89
|
+
elif name == 'write_file':
|
|
90
|
+
result = write_file(args['path'], args['content'])
|
|
91
|
+
else:
|
|
92
|
+
result = 'Error: unknown tool'
|
|
93
|
+
|
|
94
|
+
messages.append({
|
|
95
|
+
'role': 'user',
|
|
96
|
+
'parts': [{
|
|
97
|
+
'functionResponse': {
|
|
98
|
+
'name': name,
|
|
99
|
+
'response': {'content': result}
|
|
100
|
+
}
|
|
101
|
+
}]
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
if __name__ == '__main__':
|
|
105
|
+
main()
|
|
File without changes
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "specialagent"
|
|
7
|
+
version = "0.0.1"
|
|
8
|
+
description = ""
|
|
9
|
+
readme = "readme.md"
|
|
10
|
+
authors = [
|
|
11
|
+
{ name = "Jon Craton", email = "jncraton@gmail.com" }
|
|
12
|
+
]
|
|
13
|
+
classifiers = [
|
|
14
|
+
"Programming Language :: Python :: 3",
|
|
15
|
+
"License :: OSI Approved :: MIT License",
|
|
16
|
+
"Operating System :: OS Independent",
|
|
17
|
+
]
|
|
18
|
+
requires-python = ">=3.9"
|
|
19
|
+
dependencies = []
|
|
20
|
+
|
|
21
|
+
[project.scripts]
|
|
22
|
+
json2qti = "specialagent:main"
|
|
23
|
+
|
|
24
|
+
[tool.hatch.build.targets.wheel]
|
|
25
|
+
packages = ["specialagent.py"]
|
|
File without changes
|
specialagent-0.0.1/run
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Run within firejail sandbox
|
|
4
|
+
|
|
5
|
+
firejail \
|
|
6
|
+
--quiet \
|
|
7
|
+
--noprofile \
|
|
8
|
+
--caps.drop=all \
|
|
9
|
+
--seccomp \
|
|
10
|
+
--machine-id \
|
|
11
|
+
--disable-mnt \
|
|
12
|
+
--private-etc=localtime,ca-certificates,ssl,pki \
|
|
13
|
+
--private-dev \
|
|
14
|
+
--no3d \
|
|
15
|
+
--nodbus \
|
|
16
|
+
--nodvd \
|
|
17
|
+
--noinput \
|
|
18
|
+
--nosound \
|
|
19
|
+
--notv \
|
|
20
|
+
--nou2f \
|
|
21
|
+
--novideo \
|
|
22
|
+
--nonewprivs \
|
|
23
|
+
--dns=8.8.8.8 \
|
|
24
|
+
--dns=8.8.4.4 \
|
|
25
|
+
--protocol=inet,unix \
|
|
26
|
+
--hostname="hostname" \
|
|
27
|
+
--private-tmp \
|
|
28
|
+
--whitelist="$(pwd)" \
|
|
29
|
+
--whitelist=~/.profile \
|
|
30
|
+
--read-only=~/.profile \
|
|
31
|
+
--whitelist=~/.npm \
|
|
32
|
+
--whitelist=~/.cargo \
|
|
33
|
+
--read-only=~/.cargo \
|
|
34
|
+
--whitelist=~/.local/share/pipx \
|
|
35
|
+
--whitelist=~/.local/bin \
|
|
36
|
+
--read-only=~/.local/bin \
|
|
37
|
+
--whitelist=~/.cache/ms-playwright \
|
|
38
|
+
--whitelist=~/.cache/huggingface \
|
|
39
|
+
--whitelist=~/.cache/uv \
|
|
40
|
+
--rmenv=WINDOWID \
|
|
41
|
+
--rmenv=USER \
|
|
42
|
+
--rmenv=JOURNAL_STREAM \
|
|
43
|
+
--rmenv=DISPLAY \
|
|
44
|
+
--rmenv=TMUX \
|
|
45
|
+
python3 agent.py
|