autosh 0.0.0__py3-none-any.whl → 0.0.1__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.
autosh/session.py ADDED
@@ -0,0 +1,193 @@
1
+ from pathlib import Path
2
+ import sys
3
+ from agentia import Agent
4
+ from agentia.chat_completion import MessageStream
5
+ from agentia.message import UserMessage
6
+ from agentia.plugins import PluginInitError
7
+
8
+ from autosh.config import CLI_OPTIONS, CONFIG
9
+ from autosh.md import stream_md
10
+ from .plugins import create_plugins
11
+ import rich
12
+ import platform
13
+
14
+
15
+ INSTRUCTIONS = f"""
16
+ You are now acting as a AI-powered terminal shell, operating on the user's real computer.
17
+
18
+ The user will send you questions, prompts, or descriptions of the tasks.
19
+ You should take the prompts, and either answer the user's questions, or fullfill the tasks.
20
+ When necessary, generate the system commands, and execute them to fullfill the tasks.
21
+
22
+ Don't do anything else that the user doesn't ask for, or not relevant to the tasks.
23
+ The system command output are displayed to the user directly, so don't repeat the output in your response.
24
+ Just respond with the text if you want to simply print something to the terminal, no need to use `echo` or `print`.
25
+
26
+ If the prompt mentions it requires some arguments/options/flags, look for then in the command line arguments list and use them to complete the tasks.
27
+
28
+ You may use markdown to format your responses.
29
+
30
+ YOUR HOST OS INFO: {platform.platform()}
31
+ """
32
+
33
+
34
+ class Session:
35
+ def __init__(self):
36
+ self.agent = Agent(
37
+ model=CONFIG.model if not CLI_OPTIONS.think else CONFIG.think_model,
38
+ api_key=CONFIG.api_key,
39
+ instructions=INSTRUCTIONS,
40
+ tools=create_plugins(),
41
+ )
42
+
43
+ async def init(self):
44
+ try:
45
+ await self.agent.init()
46
+ except PluginInitError as e:
47
+ rich.print(
48
+ f"[bold red]Error:[/bold red] [red]Plugin [bold italic]{e.plugin}[/bold italic] failed to initialize: {str(e.original)}[/red]"
49
+ )
50
+ sys.exit(1)
51
+
52
+ def _exit_with_error(self, msg: str):
53
+ rich.print(f"[bold red]Error:[/bold red] [red]{msg}")
54
+ sys.exit(1)
55
+
56
+ async def _print_help_and_exit(self, prompt: str):
57
+ agent = Agent(
58
+ model="openai/gpt-4o-mini",
59
+ api_key=CONFIG.api_key,
60
+ instructions=f"""
61
+ This is a CLI program logic written in natural language.
62
+ Please help me to generate the CLI --help message for this CLI app.
63
+ Just output the help message, no need to add any other text.
64
+
65
+ RESPONSE FORMAT:
66
+
67
+ **Usage:** ...
68
+
69
+ The description of the program.
70
+
71
+ **Options:**
72
+
73
+ * -f, --foo Description of foo
74
+ * -b, --bar Description of bar
75
+ * --baz Description of baz
76
+ ...
77
+ * -h, --help Show this message and exit.
78
+ """,
79
+ )
80
+ agent.history.add(self._get_argv_message())
81
+ completion = agent.chat_completion(prompt, stream=True)
82
+ async for stream in completion:
83
+ await self.__render_streamed_markdown(stream)
84
+ sys.exit(0)
85
+
86
+ def _get_argv_message(self):
87
+ args = str(CLI_OPTIONS.args)
88
+ if not CLI_OPTIONS.script:
89
+ cmd = "PROMPT"
90
+ else:
91
+ cmd = CLI_OPTIONS.script.name
92
+ return UserMessage(
93
+ content=f"PROGRAM NAME: {cmd}\n\nCOMMAND LINE ARGS: {args}",
94
+ role="user",
95
+ )
96
+
97
+ async def exec_prompt(self, prompt: str):
98
+ # Clean up the prompt
99
+ if prompt is not None:
100
+ prompt = prompt.strip()
101
+ if not prompt:
102
+ sys.exit(0)
103
+ # skip shebang line
104
+ if prompt.startswith("#!"):
105
+ prompt = prompt.split("\n", 1)[1]
106
+ if len(CLI_OPTIONS.args) == 1 and (
107
+ CLI_OPTIONS.args[0] == "-h" or CLI_OPTIONS.args[0] == "--help"
108
+ ):
109
+ await self._print_help_and_exit(prompt)
110
+ # Execute the prompt
111
+ CLI_OPTIONS.prompt = prompt
112
+ self.agent.history.add(self._get_argv_message())
113
+ if CLI_OPTIONS.stdin_has_data():
114
+ self.agent.history.add(
115
+ UserMessage(
116
+ content="IMPORTANT: The user is using piped stdin to feed additional data to you. Please use tools to read when necessary.",
117
+ role="user",
118
+ )
119
+ )
120
+ completion = self.agent.chat_completion(prompt, stream=True)
121
+ async for stream in completion:
122
+ if await self.__render_streamed_markdown(stream):
123
+ print()
124
+
125
+ async def exec_from_stdin(self):
126
+ if sys.stdin.isatty():
127
+ self._exit_with_error("No prompt is piped to stdin.")
128
+ prompt = sys.stdin.read()
129
+ if not prompt:
130
+ sys.exit(0)
131
+ CLI_OPTIONS.stdin_is_script = True
132
+ await self.exec_prompt(prompt)
133
+
134
+ async def exec_script(self, script: Path):
135
+ CLI_OPTIONS.script = script
136
+ with open(script, "r") as f:
137
+ prompt = f.read()
138
+ await self.exec_prompt(prompt)
139
+
140
+ async def run_repl(self):
141
+ console = rich.console.Console()
142
+ while True:
143
+ try:
144
+ prompt = console.input("[bold]>[/bold] ").strip()
145
+ if prompt in ["exit", "quit"]:
146
+ break
147
+ if len(prompt) == 0:
148
+ continue
149
+ completion = self.agent.chat_completion(prompt, stream=True)
150
+ async for stream in completion:
151
+ if await self.__render_streamed_markdown(stream):
152
+ print()
153
+ except KeyboardInterrupt:
154
+ break
155
+
156
+ async def __render_streamed_markdown(self, stream: MessageStream):
157
+ if sys.stdout.isatty():
158
+ # buffer first few chars so we don't need to launch glow if there is no output
159
+ chunks = aiter(stream)
160
+ buf = ""
161
+ while len(buf) < 8:
162
+ try:
163
+ buf += await anext(chunks)
164
+ except StopAsyncIteration:
165
+ if len(buf) == 0:
166
+ return False
167
+ break
168
+
169
+ content = {"v": ""}
170
+
171
+ async def gen():
172
+ content["v"] = buf
173
+ if buf:
174
+ yield buf
175
+ while True:
176
+ try:
177
+ s = await anext(chunks)
178
+ content["v"] += s
179
+ for c in s:
180
+ yield c
181
+ except StopAsyncIteration:
182
+ break
183
+
184
+ await stream_md(gen())
185
+ return True
186
+ else:
187
+ has_content = False
188
+ async for chunk in stream:
189
+ if chunk == "":
190
+ continue
191
+ has_content = True
192
+ print(chunk, end="", flush=True)
193
+ return has_content
@@ -0,0 +1,77 @@
1
+ Metadata-Version: 2.4
2
+ Name: autosh
3
+ Version: 0.0.1
4
+ Summary: Add your description here
5
+ License-File: LICENSE
6
+ Requires-Python: >=3.13
7
+ Requires-Dist: agentia>=0.0.5
8
+ Requires-Dist: asyncio>=3.4.3
9
+ Requires-Dist: markdownify>=1.1.0
10
+ Requires-Dist: pydantic>=2.11.3
11
+ Requires-Dist: python-dotenv>=1.1.0
12
+ Requires-Dist: rich>=14.0.0
13
+ Requires-Dist: tavily-python>=0.5.4
14
+ Requires-Dist: typer>=0.12.5
15
+ Requires-Dist: tzlocal>=5.3.1
16
+ Description-Content-Type: text/markdown
17
+
18
+ # `autosh` - The AI-powered, noob-friendly interactive shell
19
+
20
+ # Getting Started
21
+
22
+ ## Install
23
+
24
+ ```bash
25
+ uv tool install autosh
26
+ ```
27
+
28
+ ## Usage
29
+
30
+ As an interactive shell: `ash` (alternatively, `autosh`)
31
+
32
+ Execute a single prompt: `ash "list current directory"`
33
+
34
+ Process piped data: `cat README.md | ash "summarise"`
35
+
36
+ ## Scripting
37
+
38
+ Write AI-powered shell scripts in Markdown using natural language!
39
+
40
+ Example script ([simple.a.md](examples/simple.a.md)):
41
+
42
+ ```markdown
43
+ #!/usr/bin/env ash
44
+
45
+ # This is a simple file manipulation script
46
+
47
+ First, please display a welcome message:)
48
+
49
+ Write "Hello, world" to _test.log
50
+ ```
51
+
52
+ * Run the script: `ash simple.a.md` or `chmod +x simple.a.md && simple.a.md`
53
+ * Auto generate help messages:
54
+
55
+ ```console
56
+ $ ash simple.a.md -h
57
+
58
+ Usage: simple.a.md [OPTIONS]
59
+
60
+ This is a simple file manipulation script that writes "Hello, world" to a log file named _x.log.
61
+
62
+ Options:
63
+
64
+ • -h, --help Show this message and exit.
65
+ ```
66
+
67
+ ## Plugins
68
+
69
+ `autosh` is equipped with several plugins to expand its potential:
70
+
71
+ * `ash "Create a directory "my-news", list the latest news, for each news, put the summary in a separate markdown file in this directory"`
72
+
73
+ # TODO
74
+
75
+ - [ ] Image generation
76
+ - [ ] Image input
77
+ - [ ] RAG for non-text files
@@ -0,0 +1,17 @@
1
+ autosh/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ autosh/config.py,sha256=XHVICbostoBn01kyzIT5IMvqwpyJDYNYP7awOfIljfw,2141
3
+ autosh/main.py,sha256=myRolKqfHyQEgujqmUndDSm9J0C21w3zqA9-SYNX1kY,4961
4
+ autosh/md.py,sha256=306onJ24sqYXmDpr_hLaqgo9mbQuZr18vEEDOGvqemI,13729
5
+ autosh/session.py,sha256=fDPM9addcTDmCPysaqqd_z3rEseLI2tIa_dLfn3o5Uc,6800
6
+ autosh/plugins/__init__.py,sha256=yOTobuyYFpUWl5BCowGzJG8rZX2Whlagail_QyHVlo4,2487
7
+ autosh/plugins/calc.py,sha256=qo0EajIpNPv9PtLNLygyEjVaxo1F6_S62kmoJZq5oLM,581
8
+ autosh/plugins/cli.py,sha256=joMxIIcNL0y7F9k4e9c6Pu6zmOmGb0pSsR8zFMB7J_0,7366
9
+ autosh/plugins/clock.py,sha256=GGi0HAG6f6-FP1qqGoyCcUj11q_VnkaGArumsMk0CkY,542
10
+ autosh/plugins/code.py,sha256=0JwFzq6ejgbisCqBm_RG1r1WEVNou64ue-siVIpvZqs,2291
11
+ autosh/plugins/search.py,sha256=1d3Gqq6uXu0ntTBpw44Ab_haAySvZLMj3e2MQd3DHO0,2736
12
+ autosh/plugins/web.py,sha256=lmD2JnsqVI1qKgSFrk39851jCZoPyPRaVvHeEFYXylA,2597
13
+ autosh-0.0.1.dist-info/METADATA,sha256=oXsOPAcYzBj7xKTsnpJcauOJFM2CKTFZAfTIUaJf4wU,1720
14
+ autosh-0.0.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
15
+ autosh-0.0.1.dist-info/entry_points.txt,sha256=BV7bzUnxG6Z5InEkrfajGCxjooYORC5tZDDZctOPenQ,67
16
+ autosh-0.0.1.dist-info/licenses/LICENSE,sha256=BnLDJsIJe-Dm18unR9DOoSv7QOfAz6LeIQc1yHAjxp0,1066
17
+ autosh-0.0.1.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.9.0
2
+ Generator: hatchling 1.27.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ ash = autosh.main:main
3
+ autosh = autosh.main:main
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2021 Arnaud Blois
3
+ Copyright (c) 2024 Wenyu Zhao
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,16 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: autosh
3
- Version: 0.0.0
4
- Summary: reserved
5
- License: MIT
6
- Author: Wenyu Zhao
7
- Author-email: wenyu.zhao@anu.edu.au
8
- Requires-Python: >=3.10
9
- Classifier: License :: OSI Approved :: MIT License
10
- Classifier: Programming Language :: Python :: 3
11
- Classifier: Programming Language :: Python :: 3.10
12
- Classifier: Programming Language :: Python :: 3.11
13
- Classifier: Programming Language :: Python :: 3.12
14
- Description-Content-Type: text/markdown
15
-
16
- reserved
@@ -1,5 +0,0 @@
1
- reserved/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- autosh-0.0.0.dist-info/LICENSE,sha256=XKJuERnF3YCXg9ujPMNx1yOhChxe6bBmoHnPZBl7o2I,1068
3
- autosh-0.0.0.dist-info/METADATA,sha256=6bD3KcuY6YsLtrAKPnA6R_i0xBeaynkq-cKR0V5nppo,462
4
- autosh-0.0.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
5
- autosh-0.0.0.dist-info/RECORD,,
File without changes