mini-code-cli 0.1.0.0__py3-none-any.whl → 0.1.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.
@@ -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.console.clear_screen()
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
- for call in tool_calls:
900
- self._run_one_tool_call(call)
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", "")
mini_code_cli/ui.py CHANGED
@@ -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.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,5 +1,5 @@
1
1
  mini_code_cli/__init__.py,sha256=iNgHmKSHOuH99obGjnUMoS2JP4Gw4AOrIfu68EYaZQM,77
2
- mini_code_cli/agent_loop.py,sha256=DnoHKv9hsB7a9ibdvbt3HxfsdASpw8N1Gw2dTLZFI9g,55999
2
+ mini_code_cli/agent_loop.py,sha256=jQEzWknHid0rKA8-vzES1RONg4tVJ8l4ImBleBC_RDE,58124
3
3
  mini_code_cli/config.py,sha256=AvzDZAKynQbuj5lcTtL-DcUwhyLa99QmNrLK6fYpdOA,814
4
4
  mini_code_cli/permissions.py,sha256=uQpQlUtQyVICpjUqdh9QQ_mgl51hZrGLHJzQR9vG124,2017
5
5
  mini_code_cli/persistence.py,sha256=L47NhXs6R54KETd8R17oGGxCXNEf7bjmvlwAJqtspLI,9944
@@ -10,14 +10,14 @@ mini_code_cli/sandbox.py,sha256=t7xS_AIpE8fbo5kj9zbUFbfEaAnq6iUE7plQcn6-uAk,2128
10
10
  mini_code_cli/shell_safety_utils.py,sha256=5E126vGnG7iIuTZe_R5JrxB_zxZpMKGe_pilz_Z2r4w,5551
11
11
  mini_code_cli/skills.py,sha256=baaz0RkPQ-OgWWwH5sHsKBmJdR430yT4HK3VLX0_88Y,13704
12
12
  mini_code_cli/tools.py,sha256=bW1zYyIj6OFp5TIcg5DCwheN-4xI1LQmDOQaHIfRV7M,10998
13
- mini_code_cli/ui.py,sha256=AUwn0OFt3yFx397-V8kYuidseCBxFHgO1KWDKrlLCOU,29371
13
+ mini_code_cli/ui.py,sha256=sNfjwxLWtRF3C3VpSBP9L0uncVgFhZmGquw8u9O956U,32127
14
14
  mini_code_cli/utils.py,sha256=ffUAIisO8_h7VvlwAOLhdoNSAIdssGdtQHXm-i8bcLE,4620
15
15
  mini_code_cli/subagents/__init__.py,sha256=3fgcwY0pNq5iW29OxLPtSA3H5IKXhl2LUhwbBjLUDuU,1884
16
16
  mini_code_cli/subagents/base.py,sha256=bhZEENoTVjebfqaEKS7uPWeU0SwQWFN3BD40EtziPbg,12660
17
17
  mini_code_cli/subagents/builtin.py,sha256=ENzuooXIylzfZZ8uYkZmdxgCrCQ4pdbfrOONkBdGSPg,7598
18
- mini_code_cli-0.1.0.0.dist-info/licenses/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
19
- mini_code_cli-0.1.0.0.dist-info/METADATA,sha256=iUqH7NzuQqmIetQQjA5Re6-sADvq7JD_iGQDKehWqpQ,52292
20
- mini_code_cli-0.1.0.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
21
- mini_code_cli-0.1.0.0.dist-info/entry_points.txt,sha256=MwDp5UbXpI7wodSmOSYL8_nKutnBiyp96ZDDtaX7x14,60
22
- mini_code_cli-0.1.0.0.dist-info/top_level.txt,sha256=3Hb6PpNkJYXvzDKXuuFJRvzCdsTRh0TuRWz-ScJ6qV0,14
23
- mini_code_cli-0.1.0.0.dist-info/RECORD,,
18
+ mini_code_cli-0.1.0.1.dist-info/licenses/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
19
+ mini_code_cli-0.1.0.1.dist-info/METADATA,sha256=Er_McRLgRQ41CpufVZSHZeN1ZjBTGpf_s-odKMijoCE,52757
20
+ mini_code_cli-0.1.0.1.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
21
+ mini_code_cli-0.1.0.1.dist-info/entry_points.txt,sha256=MwDp5UbXpI7wodSmOSYL8_nKutnBiyp96ZDDtaX7x14,60
22
+ mini_code_cli-0.1.0.1.dist-info/top_level.txt,sha256=3Hb6PpNkJYXvzDKXuuFJRvzCdsTRh0TuRWz-ScJ6qV0,14
23
+ mini_code_cli-0.1.0.1.dist-info/RECORD,,