nanocode-cli 0.2.4__tar.gz → 0.2.6__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: nanocode-cli
3
- Version: 0.2.4
3
+ Version: 0.2.6
4
4
  Summary: A lightweight terminal-based AI coding assistant
5
5
  Author-email: hit9 <hit9@icloud.com>
6
6
  License-Expression: BSD-3-Clause
@@ -41,7 +41,7 @@ from prompt_toolkit.patch_stdout import patch_stdout
41
41
 
42
42
  JsonValue: TypeAlias = Any
43
43
  Json: TypeAlias = dict[str, JsonValue]
44
- __version__ = "0.2.4"
44
+ __version__ = "0.2.6"
45
45
 
46
46
 
47
47
  class Error(Exception): ...
@@ -820,6 +820,7 @@ class SearchTool(Tool):
820
820
  return [
821
821
  "Search files or directories before Read; default is fixed text.",
822
822
  "Prefix pattern with re: for regex search.",
823
+ "Search is line-oriented; regex patterns must not contain newlines.",
823
824
  "Use A|B|C for literal OR search in fixed mode.",
824
825
  "Optional context=N or N sets nearby context lines.",
825
826
  "Optional glob matches file basename or path relative to cwd.",
@@ -827,7 +828,7 @@ class SearchTool(Tool):
827
828
 
828
829
  @classmethod
829
830
  def signature(cls) -> str:
830
- return "Search(pattern, path[, glob_pattern][, context=N|N]) -> SearchToolResult<matches>"
831
+ return "Search(pattern, path[, option...]) -> SearchToolResult<matches>; option is context=N|N or glob_pattern"
831
832
 
832
833
  @classmethod
833
834
  def example(cls) -> list[str]:
@@ -850,6 +851,8 @@ class SearchTool(Tool):
850
851
  pattern = raw_pattern[3:] if regex else raw_pattern
851
852
  if not pattern:
852
853
  raise ToolCallError("pattern cannot be empty")
854
+ if regex and "\n" in pattern:
855
+ raise ToolCallError("multiline regex is not supported; Search is line-oriented. Search each line separately or Read a nearby range.")
853
856
  glob_pattern = ""
854
857
  context_lines = cls.CONTEXT_LINES
855
858
  for raw_option in args[2:]:
@@ -1734,8 +1737,10 @@ Input:
1734
1737
  - Latest_User_Input: latest user message
1735
1738
  - Tools: available tool specs
1736
1739
 
1737
- Output strict JSON only. No markdown. No comments. No extra text.
1738
- Never answer outside JSON, including help/status/explanation requests; put user-facing text only in message_to_user.
1740
+ Output MUST be exactly one JSON object.
1741
+ No markdown, prose, code fences, XML tags, native tool calls, or text outside JSON.
1742
+ Put normal replies in message_to_user.
1743
+ Put tool calls only in JSON tool_calls.
1739
1744
 
1740
1745
  Schema:
1741
1746
  {
@@ -1966,6 +1971,7 @@ class ModelClient:
1966
1971
  "model": self.session.model,
1967
1972
  "messages": messages,
1968
1973
  "temperature": self.session.temperature,
1974
+ "response_format": {"type": "json_object"},
1969
1975
  }
1970
1976
  extra_params = self._reasoning_params()
1971
1977
  payload.update(extra_params)
@@ -2675,7 +2681,6 @@ class ConversationCompactor:
2675
2681
  @final
2676
2682
  class Agent:
2677
2683
  MAX_CONSECUTIVE_FORMAT_ERRORS: ClassVar[int] = 3
2678
- MAX_CONSECUTIVE_SUMMARY_GATES: ClassVar[int] = 1
2679
2684
 
2680
2685
  def __init__(self, session: Session):
2681
2686
  self.session = session
@@ -2725,7 +2730,6 @@ class Agent:
2725
2730
  self.maybe_auto_compact()
2726
2731
  self.session.append_conversation(UserMessage(content=user_input))
2727
2732
  consecutive_format_errors = 0
2728
- consecutive_summary_gates = 0
2729
2733
 
2730
2734
  for _ in range(self.session.max_agent_steps):
2731
2735
  response = self.step()
@@ -2758,25 +2762,6 @@ class Agent:
2758
2762
  continue
2759
2763
  consecutive_format_errors = 0
2760
2764
  tool_calls = _json_list(response.get("tool_calls"))
2761
- summary_gate = self._format_tool_summary_gate(tool_calls)
2762
- if summary_gate:
2763
- consecutive_summary_gates += 1
2764
- if consecutive_summary_gates <= self.MAX_CONSECUTIVE_SUMMARY_GATES:
2765
- self.state_updater.latest_report = ""
2766
- self.latest_agent_feedback = summary_gate
2767
- self._report_gate(
2768
- on_message,
2769
- "Retrying: model needs to summarize the latest tool results.",
2770
- self._compact_gate_report(summary_gate),
2771
- )
2772
- continue
2773
- self._report_gate(
2774
- on_message,
2775
- "Continuing: model did not summarize tool results after one retry.",
2776
- "Tool_Summary_Gate: allowing continuation after one missing-summary retry.",
2777
- )
2778
- else:
2779
- consecutive_summary_gates = 0
2780
2765
  self.apply_response(response)
2781
2766
  if on_message is not None and self.state_updater.latest_report:
2782
2767
  on_message(self.state_updater.latest_report)
@@ -2828,7 +2813,11 @@ class Agent:
2828
2813
  return headline
2829
2814
 
2830
2815
  def step(self) -> Json:
2831
- response = self.request(self.build_system_prompt(), self.build_user_prompt(), activity="main")
2816
+ response = self.request(self.build_system_prompt(), self.build_user_prompt(consume_latest_tool_results=False), activity="main")
2817
+ if _json_str(response.get("_format_error")):
2818
+ return response
2819
+ self.latest_tool_call_results = ""
2820
+ self.latest_agent_feedback = ""
2832
2821
  self.state_updater.apply_tool_call_summaries(response)
2833
2822
  return response
2834
2823
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nanocode-cli
3
- Version: 0.2.4
3
+ Version: 0.2.6
4
4
  Summary: A lightweight terminal-based AI coding assistant
5
5
  Author-email: hit9 <hit9@icloud.com>
6
6
  License-Expression: BSD-3-Clause
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "nanocode-cli"
7
- version = "0.2.4"
7
+ version = "0.2.6"
8
8
  description = "A lightweight terminal-based AI coding assistant"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
File without changes
File without changes
File without changes
File without changes