mini-code-cli 0.1.0.0__tar.gz → 0.1.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.
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/PKG-INFO +16 -1
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/README.md +15 -0
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/mini_code_cli/agent_loop.py +51 -3
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/mini_code_cli/ui.py +55 -0
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/mini_code_cli.egg-info/PKG-INFO +16 -1
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/pyproject.toml +1 -1
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/LICENSE +0 -0
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/mini_code_cli/__init__.py +0 -0
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/mini_code_cli/config.py +0 -0
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/mini_code_cli/permissions.py +0 -0
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/mini_code_cli/persistence.py +0 -0
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/mini_code_cli/plan.py +0 -0
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/mini_code_cli/prompts.py +0 -0
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/mini_code_cli/runner.py +0 -0
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/mini_code_cli/sandbox.py +0 -0
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/mini_code_cli/shell_safety_utils.py +0 -0
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/mini_code_cli/skills.py +0 -0
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/mini_code_cli/subagents/__init__.py +0 -0
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/mini_code_cli/subagents/base.py +0 -0
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/mini_code_cli/subagents/builtin.py +0 -0
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/mini_code_cli/tools.py +0 -0
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/mini_code_cli/utils.py +0 -0
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/mini_code_cli.egg-info/SOURCES.txt +0 -0
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/mini_code_cli.egg-info/dependency_links.txt +0 -0
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/mini_code_cli.egg-info/entry_points.txt +0 -0
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/mini_code_cli.egg-info/requires.txt +0 -0
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/mini_code_cli.egg-info/top_level.txt +0 -0
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/setup.cfg +0 -0
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/tests/test_agent_loop.py +0 -0
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/tests/test_integration.py +0 -0
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/tests/test_plan.py +0 -0
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/tests/test_sandboxing.py +0 -0
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/tests/test_shell_safety.py +0 -0
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/tests/test_skills.py +0 -0
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/tests/test_subagents.py +0 -0
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/tests/test_tools.py +0 -0
- {mini_code_cli-0.1.0.0 → mini_code_cli-0.1.0.1}/tests/test_ui.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mini-code-cli
|
|
3
|
-
Version: 0.1.0.
|
|
3
|
+
Version: 0.1.0.1
|
|
4
4
|
Summary: Mini Coding Agent. Allows you to easily experiment with a small coding agent.
|
|
5
5
|
Author-email: Nikolai Rozanov <nikolai.rozanov@gmail.com>
|
|
6
6
|
License: GNU AFFERO GENERAL PUBLIC LICENSE
|
|
@@ -871,4 +871,19 @@ vllm serve ornith-ai/Ornith-1.5-397B-FP8 \
|
|
|
871
871
|
--trust-remote-code
|
|
872
872
|
```
|
|
873
873
|
|
|
874
|
+
## Citation
|
|
875
|
+
|
|
876
|
+
If you use `mini-code-cli` in your research or writing, please cite it using the BibTeX entry below:
|
|
877
|
+
|
|
878
|
+
```bibtex
|
|
879
|
+
@misc{mini-code-cli,
|
|
880
|
+
author = {Rozanov, Nikolai},
|
|
881
|
+
title = {mini-code-cli: A minimal, dependency-light coding agent},
|
|
882
|
+
year = {2026},
|
|
883
|
+
version = {0.1.0.0},
|
|
884
|
+
howpublished = {\url{https://github.com/ai-nikolai/mini-code-cli}},
|
|
885
|
+
note = {A no-bloat, dependency-free agent CLI for experimenting.}
|
|
886
|
+
}
|
|
887
|
+
```
|
|
888
|
+
|
|
874
889
|
## (C) Nikolai Rozanov, 2026 - Present
|
|
@@ -197,4 +197,19 @@ vllm serve ornith-ai/Ornith-1.5-397B-FP8 \
|
|
|
197
197
|
--trust-remote-code
|
|
198
198
|
```
|
|
199
199
|
|
|
200
|
+
## Citation
|
|
201
|
+
|
|
202
|
+
If you use `mini-code-cli` in your research or writing, please cite it using the BibTeX entry below:
|
|
203
|
+
|
|
204
|
+
```bibtex
|
|
205
|
+
@misc{mini-code-cli,
|
|
206
|
+
author = {Rozanov, Nikolai},
|
|
207
|
+
title = {mini-code-cli: A minimal, dependency-light coding agent},
|
|
208
|
+
year = {2026},
|
|
209
|
+
version = {0.1.0.0},
|
|
210
|
+
howpublished = {\url{https://github.com/ai-nikolai/mini-code-cli}},
|
|
211
|
+
note = {A no-bloat, dependency-free agent CLI for experimenting.}
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
200
215
|
## (C) Nikolai Rozanov, 2026 - Present
|
|
@@ -581,6 +581,10 @@ class AgentSession:
|
|
|
581
581
|
print_welcome(self.allowed_dir, self.server_url, self.args,
|
|
582
582
|
self.unique_id, self.cache_dir, self.model)
|
|
583
583
|
|
|
584
|
+
# Announce the session's unique id as an assistant-styled message so the
|
|
585
|
+
# user can see / copy the id this conversation is being saved under.
|
|
586
|
+
self._print_session_id()
|
|
587
|
+
|
|
584
588
|
# Report the outcome of --load-last-session up front, so the user sees
|
|
585
589
|
# whether we resumed an earlier conversation (under a brand-new id) or
|
|
586
590
|
# started fresh because no previous session was found.
|
|
@@ -649,6 +653,20 @@ class AgentSession:
|
|
|
649
653
|
# Ctrl-C mid-loop just saves and re-prompts rather than crashing.
|
|
650
654
|
self._persist()
|
|
651
655
|
|
|
656
|
+
def _print_session_id(self):
|
|
657
|
+
"""Print the session's unique id as an assistant-styled message.
|
|
658
|
+
|
|
659
|
+
A short, styled announcement (in the assistant accent) so the user can
|
|
660
|
+
see and copy the id the conversation is saved under -- the same id shown
|
|
661
|
+
in the welcome banner, but rendered as a transcript turn so it is easy
|
|
662
|
+
to spot and grep.
|
|
663
|
+
"""
|
|
664
|
+
self.console.divider()
|
|
665
|
+
self.console.turn(
|
|
666
|
+
"Session id",
|
|
667
|
+
f"{self.unique_id} (saved under {self.cache_dir})",
|
|
668
|
+
accent="green")
|
|
669
|
+
|
|
652
670
|
# -- autonomous drive (used by sub-agents) ------------------------------
|
|
653
671
|
|
|
654
672
|
def _drive_auto(self, initial_task, max_steps=None):
|
|
@@ -864,7 +882,7 @@ class AgentSession:
|
|
|
864
882
|
self.unique_id, self.cache_dir, self.model)
|
|
865
883
|
return True
|
|
866
884
|
if cmd in self.CLEAR_COMMANDS:
|
|
867
|
-
self.
|
|
885
|
+
self._clear_and_show_last()
|
|
868
886
|
return True
|
|
869
887
|
self.console.note(f"Unknown command {stripped!r}. Try /help.", "warn")
|
|
870
888
|
return True
|
|
@@ -892,12 +910,42 @@ class AgentSession:
|
|
|
892
910
|
return
|
|
893
911
|
self._reset_history(target["turn"], target)
|
|
894
912
|
|
|
913
|
+
def _clear_and_show_last(self):
|
|
914
|
+
"""Handle /clear: wipe the screen and re-print the last turn.
|
|
915
|
+
|
|
916
|
+
The conversation itself is unchanged; we just redraw the most recent
|
|
917
|
+
exchange so the user re-orients after clearing the view. If there is no
|
|
918
|
+
assistant reply yet, the last user turn is shown instead.
|
|
919
|
+
"""
|
|
920
|
+
self.console.clear_screen()
|
|
921
|
+
last_role = last_text = None
|
|
922
|
+
for m in reversed(self.messages):
|
|
923
|
+
role = m.get("role")
|
|
924
|
+
content = m.get("content")
|
|
925
|
+
if role == "assistant" and not m.get("tool_calls") and content:
|
|
926
|
+
last_role, last_text = "Assistant", content
|
|
927
|
+
break
|
|
928
|
+
if role == "user" and content:
|
|
929
|
+
last_role, last_text = "You", content
|
|
930
|
+
break
|
|
931
|
+
if last_role is not None:
|
|
932
|
+
self.console.divider()
|
|
933
|
+
accent = "green" if last_role == "Assistant" else "cyan"
|
|
934
|
+
self.console.turn(last_role, last_text, accent=accent)
|
|
935
|
+
|
|
895
936
|
# -- tool execution ----------------------------------------------------
|
|
896
937
|
|
|
897
938
|
def _run_tool_calls(self, tool_calls):
|
|
898
939
|
_make_tool_call_note(self.console, len(tool_calls))
|
|
899
|
-
|
|
900
|
-
|
|
940
|
+
# Show a "… calling tool" spinner (in-place, non-scrolling) while the
|
|
941
|
+
# tool(s) execute, mirroring the thinking spinner that covers the LLM
|
|
942
|
+
# call. Always stopped (finally) so it can never leak into the next turn.
|
|
943
|
+
self.console.start_tool_call()
|
|
944
|
+
try:
|
|
945
|
+
for call in tool_calls:
|
|
946
|
+
self._run_one_tool_call(call)
|
|
947
|
+
finally:
|
|
948
|
+
self.console.stop_tool_call()
|
|
901
949
|
|
|
902
950
|
def _run_one_tool_call(self, call):
|
|
903
951
|
call_id = call.get("id", "")
|
|
@@ -99,6 +99,12 @@ class Console:
|
|
|
99
99
|
# "… thinking" spinner state (see start_thinking / stop_thinking).
|
|
100
100
|
self._thinking_thread = None
|
|
101
101
|
self._thinking_stop = None
|
|
102
|
+
# "… calling tool" spinner state (see start_tool_call / stop_tool_call).
|
|
103
|
+
# Mirrors the thinking spinner: a daemon thread that rewrites a single
|
|
104
|
+
# live line in place (via the transient region) so the tool-execution
|
|
105
|
+
# phase looks alive without scrolling the transcript.
|
|
106
|
+
self._tool_call_thread = None
|
|
107
|
+
self._tool_call_stop = None
|
|
102
108
|
# Live "transient" region (non-verbose mode) renders the tool-call area
|
|
103
109
|
# and the usage line without scrolling the screen. We keep a single
|
|
104
110
|
# invariant: whenever ``_transient_lines`` is > 0 a block of that many
|
|
@@ -432,6 +438,55 @@ class Console:
|
|
|
432
438
|
if thread is not None and thread.is_alive():
|
|
433
439
|
thread.join(timeout=1.0)
|
|
434
440
|
|
|
441
|
+
def start_tool_call(self, message="Calling tool"):
|
|
442
|
+
"""Start a background "… calling tool" spinner (non-scrolling).
|
|
443
|
+
|
|
444
|
+
Shown while the agent executes a tool call, mirroring
|
|
445
|
+
:meth:`start_thinking` which covers the LLM request. Runs a short
|
|
446
|
+
animation in a daemon thread that rewrites a single live line in place
|
|
447
|
+
via the transient region, so the wait looks alive without scrolling the
|
|
448
|
+
transcript. On a real colour/utf-8 TTY it animates in place; on piped /
|
|
449
|
+
ASCII output it simply prints one static line and starts no thread.
|
|
450
|
+
Stop it with :meth:`stop_tool_call` before drawing the next turn.
|
|
451
|
+
"""
|
|
452
|
+
self.stop_tool_call() # be defensive: never leak more than one spinner
|
|
453
|
+
if not self._can_clear_cursor():
|
|
454
|
+
self.emit(self.style(f"\u2026 {message}", fg="magenta", dim=True))
|
|
455
|
+
return
|
|
456
|
+
self._tool_call_stop = threading.Event()
|
|
457
|
+
self._tool_call_thread = threading.Thread(
|
|
458
|
+
target=self._spin_tool_call, args=(message,), daemon=True)
|
|
459
|
+
self._tool_call_thread.start()
|
|
460
|
+
|
|
461
|
+
def _spin_tool_call(self, message):
|
|
462
|
+
"""Animation loop for the tool-call spinner (mirror of :meth:`_spin`)."""
|
|
463
|
+
stop = self._tool_call_stop
|
|
464
|
+
i = 0
|
|
465
|
+
while not stop.is_set():
|
|
466
|
+
dots = "\u2026 " * min((i % 3) + 1, 3)
|
|
467
|
+
i += 1
|
|
468
|
+
self.emit_transient(self.style(f"{dots}{message}", fg="magenta", dim=True))
|
|
469
|
+
stop.wait(0.3)
|
|
470
|
+
# Replace the spinner line with a blank so the following real output
|
|
471
|
+
# lands cleanly; the blank stays tracked as the transient block and is
|
|
472
|
+
# cleared by the next :meth:`emit` (e.g. the next assistant turn).
|
|
473
|
+
self.emit_transient(None)
|
|
474
|
+
|
|
475
|
+
def stop_tool_call(self):
|
|
476
|
+
"""Stop the "… calling tool" spinner started by :meth:`start_tool_call`.
|
|
477
|
+
|
|
478
|
+
Signals the animation thread to finish its current frame and exit, then
|
|
479
|
+
joins it, so no writes race with the main thread's subsequent output.
|
|
480
|
+
Safe to call when no spinner is running (a no-op)."""
|
|
481
|
+
stop = self._tool_call_stop
|
|
482
|
+
thread = self._tool_call_thread
|
|
483
|
+
self._tool_call_stop = None
|
|
484
|
+
self._tool_call_thread = None
|
|
485
|
+
if stop is not None:
|
|
486
|
+
stop.set()
|
|
487
|
+
if thread is not None and thread.is_alive():
|
|
488
|
+
thread.join(timeout=1.0)
|
|
489
|
+
|
|
435
490
|
def tool_group(self, name, params=None, result=None, status="ran"):
|
|
436
491
|
"""Render one attempted tool call: its name, parameters and result."""
|
|
437
492
|
self.emit(self.style(f"{self.glyph('gear')} {name}", fg="magenta", bold=True))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mini-code-cli
|
|
3
|
-
Version: 0.1.0.
|
|
3
|
+
Version: 0.1.0.1
|
|
4
4
|
Summary: Mini Coding Agent. Allows you to easily experiment with a small coding agent.
|
|
5
5
|
Author-email: Nikolai Rozanov <nikolai.rozanov@gmail.com>
|
|
6
6
|
License: GNU AFFERO GENERAL PUBLIC LICENSE
|
|
@@ -871,4 +871,19 @@ vllm serve ornith-ai/Ornith-1.5-397B-FP8 \
|
|
|
871
871
|
--trust-remote-code
|
|
872
872
|
```
|
|
873
873
|
|
|
874
|
+
## Citation
|
|
875
|
+
|
|
876
|
+
If you use `mini-code-cli` in your research or writing, please cite it using the BibTeX entry below:
|
|
877
|
+
|
|
878
|
+
```bibtex
|
|
879
|
+
@misc{mini-code-cli,
|
|
880
|
+
author = {Rozanov, Nikolai},
|
|
881
|
+
title = {mini-code-cli: A minimal, dependency-light coding agent},
|
|
882
|
+
year = {2026},
|
|
883
|
+
version = {0.1.0.0},
|
|
884
|
+
howpublished = {\url{https://github.com/ai-nikolai/mini-code-cli}},
|
|
885
|
+
note = {A no-bloat, dependency-free agent CLI for experimenting.}
|
|
886
|
+
}
|
|
887
|
+
```
|
|
888
|
+
|
|
874
889
|
## (C) Nikolai Rozanov, 2026 - Present
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "mini-code-cli"
|
|
3
3
|
# version = { file = "mini_code_cli/__init__.py", attr = "__version__" }
|
|
4
|
-
version = "0.1.0.
|
|
4
|
+
version = "0.1.0.1"
|
|
5
5
|
description = "Mini Coding Agent. Allows you to easily experiment with a small coding agent."
|
|
6
6
|
readme = "README.md"
|
|
7
7
|
requires-python = ">=3.10"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|