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.
@@ -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