tass 0.1.7__tar.gz → 0.1.8__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tass
3
- Version: 0.1.7
3
+ Version: 0.1.8
4
4
  Summary: A terminal assistant that allows you to ask an LLM to run commands.
5
5
  Project-URL: Homepage, https://github.com/cetincan0/tass
6
6
  Author: Can Cetin
@@ -21,10 +21,18 @@ This tool can run commands including ones that can modify, move, or delete files
21
21
 
22
22
  ## Installation
23
23
 
24
+ ### Using uv
25
+
24
26
  ```
25
27
  uv tool install tass
26
28
  ```
27
29
 
30
+ ### Using pip
31
+
32
+ ```
33
+ pip install tass
34
+ ```
35
+
28
36
  You can run it with
29
37
 
30
38
  ```
@@ -34,3 +42,19 @@ tass
34
42
  tass has only been tested with gpt-oss-120b using llama.cpp so far, but in theory any LLM with tool calling capabilities should work. By default, it will try connecting to http://localhost:8080. If you want to use another host, set the `TASS_HOST` environment variable.
35
43
 
36
44
  Once it's running, you can ask questions or give commands like "Create an empty file called test.txt" and it will propose a command to run after user confirmation.
45
+
46
+ You can enter multiline input by ending lines with a backslash (\\). The continuation prompt will appear until you enter a line without a trailing backslash.
47
+
48
+ ## Upgrade
49
+
50
+ ### Using uv
51
+
52
+ ```
53
+ uv tool upgrade tass
54
+ ```
55
+
56
+ ### Using pip
57
+
58
+ ```
59
+ pip install --upgrade tass
60
+ ```
@@ -8,10 +8,18 @@ This tool can run commands including ones that can modify, move, or delete files
8
8
 
9
9
  ## Installation
10
10
 
11
+ ### Using uv
12
+
11
13
  ```
12
14
  uv tool install tass
13
15
  ```
14
16
 
17
+ ### Using pip
18
+
19
+ ```
20
+ pip install tass
21
+ ```
22
+
15
23
  You can run it with
16
24
 
17
25
  ```
@@ -21,3 +29,19 @@ tass
21
29
  tass has only been tested with gpt-oss-120b using llama.cpp so far, but in theory any LLM with tool calling capabilities should work. By default, it will try connecting to http://localhost:8080. If you want to use another host, set the `TASS_HOST` environment variable.
22
30
 
23
31
  Once it's running, you can ask questions or give commands like "Create an empty file called test.txt" and it will propose a command to run after user confirmation.
32
+
33
+ You can enter multiline input by ending lines with a backslash (\\). The continuation prompt will appear until you enter a line without a trailing backslash.
34
+
35
+ ## Upgrade
36
+
37
+ ### Using uv
38
+
39
+ ```
40
+ uv tool upgrade tass
41
+ ```
42
+
43
+ ### Using pip
44
+
45
+ ```
46
+ pip install --upgrade tass
47
+ ```
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "tass"
3
- version = "0.1.7"
3
+ version = "0.1.8"
4
4
  description = "A terminal assistant that allows you to ask an LLM to run commands."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -15,9 +15,7 @@ from src.constants import (
15
15
  SYSTEM_PROMPT,
16
16
  TOOLS,
17
17
  )
18
- from src.utils import (
19
- is_read_only_command,
20
- )
18
+ from src.utils import is_read_only_command
21
19
 
22
20
  console = Console()
23
21
 
@@ -102,22 +100,34 @@ class TassApp:
102
100
  content = ""
103
101
  reasoning_content = ""
104
102
  tool_calls_map = {}
103
+ timings_str = ""
105
104
 
106
- def generate_layout(reasoning_content: str, content: str):
105
+ def generate_layout():
107
106
  groups = []
108
107
 
109
108
  if reasoning_content:
109
+ last_three_lines = "\n".join(reasoning_content.rstrip().split("\n")[-3:])
110
110
  groups.append(Text(""))
111
- groups.append(Panel(Text(reasoning_content, style="grey50"), title="Thought process", title_align="left", style="grey50"))
111
+ groups.append(
112
+ Panel(
113
+ Text(
114
+ last_three_lines,
115
+ style="grey50",
116
+ ),
117
+ title="Thought process",
118
+ title_align="left",
119
+ subtitle=timings_str,
120
+ style="grey50",
121
+ )
122
+ )
112
123
 
113
124
  if content:
114
125
  groups.append(Text(""))
115
- groups.append(Markdown(content))
116
- groups.append(Text(""))
126
+ groups.append(Markdown(content.rstrip()))
117
127
 
118
128
  return Group(*groups)
119
129
 
120
- with Live(generate_layout(reasoning_content, content), refresh_per_second=10) as live:
130
+ with Live(generate_layout(), refresh_per_second=10) as live:
121
131
  for line in response.iter_lines():
122
132
  line = line.decode("utf-8")
123
133
  if not line.strip():
@@ -130,12 +140,10 @@ class TassApp:
130
140
  delta = chunk["choices"][0]["delta"]
131
141
  if delta.get("content"):
132
142
  content += delta["content"]
133
- last_three_lines = "\n".join(reasoning_content.rstrip().split("\n")[-3:])
134
- live.update(generate_layout(last_three_lines, content.rstrip()))
143
+ live.update(generate_layout())
135
144
  if delta.get("reasoning_content" ):
136
145
  reasoning_content += delta["reasoning_content"]
137
- last_three_lines = "\n".join(reasoning_content.rstrip().split("\n")[-3:])
138
- live.update(generate_layout(last_three_lines, content.rstrip()))
146
+ live.update(generate_layout())
139
147
 
140
148
  for tool_call_delta in delta.get("tool_calls", []):
141
149
  index = tool_call_delta["index"]
@@ -164,9 +172,15 @@ class TassApp:
164
172
  if function.get("arguments"):
165
173
  tool_call["function"]["arguments"] += function["arguments"]
166
174
 
175
+ if all(k in chunk.get("timings", {}) for k in ["prompt_n", "prompt_per_second", "predicted_n", "predicted_per_second"]):
176
+ timings = chunk["timings"]
177
+ timings_str = (
178
+ f"Input: {timings['prompt_n']:,} tokens, {timings['prompt_per_second']:,.2f} tok/s | "
179
+ f"Output: {timings['predicted_n']:,} tokens, {timings['predicted_per_second']:,.2f} tok/s"
180
+ )
181
+
167
182
  if chunk["choices"][0]["finish_reason"]:
168
- last_three_lines = "\n".join(reasoning_content.rstrip().split("\n")[-3:])
169
- live.update(generate_layout(last_three_lines, content.rstrip()))
183
+ live.update(generate_layout())
170
184
 
171
185
  self.messages.append(
172
186
  {
@@ -362,14 +376,22 @@ class TassApp:
362
376
  def run(self):
363
377
  try:
364
378
  self._check_llm_host()
365
- console.print()
366
379
  except KeyboardInterrupt:
367
380
  console.print("\nBye!")
368
381
  return
369
382
 
370
383
  while True:
384
+ console.print()
371
385
  try:
372
- user_input = console.input("> ").strip()
386
+ input_lines = []
387
+ while True:
388
+ input_line = console.input("> ")
389
+ if not input_line or input_line[-1] != "\\":
390
+ input_lines.append(input_line)
391
+ break
392
+ input_lines.append(input_line[:-1])
393
+
394
+ user_input = "\n".join(input_lines)
373
395
  except KeyboardInterrupt:
374
396
  console.print("\nBye!")
375
397
  break
@@ -261,7 +261,7 @@ wheels = [
261
261
 
262
262
  [[package]]
263
263
  name = "tass"
264
- version = "0.1.7"
264
+ version = "0.1.8"
265
265
  source = { editable = "." }
266
266
  dependencies = [
267
267
  { name = "requests" },
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes