deepy-cli 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.
Files changed (71) hide show
  1. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/PKG-INFO +2 -2
  2. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/README.md +1 -1
  3. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/pyproject.toml +1 -1
  4. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/__init__.py +1 -1
  5. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/data/tools/shell.md +4 -0
  6. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/tools/builtin.py +43 -4
  7. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/ui/prompt_input.py +56 -0
  8. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/__main__.py +0 -0
  9. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/cli.py +0 -0
  10. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/config/__init__.py +0 -0
  11. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/config/settings.py +0 -0
  12. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/data/__init__.py +0 -0
  13. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/data/tools/AskUserQuestion.md +0 -0
  14. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/data/tools/WebFetch.md +0 -0
  15. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/data/tools/WebSearch.md +0 -0
  16. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/data/tools/__init__.py +0 -0
  17. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/data/tools/edit.md +0 -0
  18. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/data/tools/modify.md +0 -0
  19. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/data/tools/read.md +0 -0
  20. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/data/tools/write.md +0 -0
  21. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/errors.py +0 -0
  22. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/llm/__init__.py +0 -0
  23. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/llm/agent.py +0 -0
  24. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/llm/compaction.py +0 -0
  25. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/llm/context.py +0 -0
  26. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/llm/events.py +0 -0
  27. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/llm/model_capabilities.py +0 -0
  28. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/llm/provider.py +0 -0
  29. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/llm/replay.py +0 -0
  30. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/llm/runner.py +0 -0
  31. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/llm/thinking.py +0 -0
  32. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/prompts/__init__.py +0 -0
  33. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/prompts/compact.py +0 -0
  34. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/prompts/rules.py +0 -0
  35. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/prompts/runtime_context.py +0 -0
  36. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/prompts/system.py +0 -0
  37. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/prompts/tool_docs.py +0 -0
  38. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/sessions/__init__.py +0 -0
  39. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/sessions/jsonl.py +0 -0
  40. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/sessions/manager.py +0 -0
  41. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/skills.py +0 -0
  42. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/status.py +0 -0
  43. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/tools/__init__.py +0 -0
  44. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/tools/agents.py +0 -0
  45. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/tools/file_state.py +0 -0
  46. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/tools/result.py +0 -0
  47. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/tools/shell_utils.py +0 -0
  48. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/ui/__init__.py +0 -0
  49. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/ui/app.py +0 -0
  50. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/ui/ask_user_question.py +0 -0
  51. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/ui/exit_summary.py +0 -0
  52. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/ui/loading_text.py +0 -0
  53. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/ui/markdown.py +0 -0
  54. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/ui/message_view.py +0 -0
  55. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/ui/model_picker.py +0 -0
  56. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/ui/prompt_buffer.py +0 -0
  57. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/ui/session_list.py +0 -0
  58. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/ui/session_picker.py +0 -0
  59. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/ui/slash_commands.py +0 -0
  60. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/ui/styles.py +0 -0
  61. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/ui/terminal.py +0 -0
  62. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/ui/theme_picker.py +0 -0
  63. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/ui/thinking_state.py +0 -0
  64. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/ui/welcome.py +0 -0
  65. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/update_check.py +0 -0
  66. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/usage.py +0 -0
  67. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/utils/__init__.py +0 -0
  68. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/utils/debug_logger.py +0 -0
  69. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/utils/error_logger.py +0 -0
  70. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/utils/json.py +0 -0
  71. {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/utils/notify.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: deepy-cli
3
- Version: 0.1.7
3
+ Version: 0.1.8
4
4
  Summary: Deepy - Vibe coding for DeepSeek models in your terminal
5
5
  Keywords: deepseek,coding-agent,terminal,cli,agents
6
6
  Author: kirineko
@@ -238,5 +238,5 @@ assets live outside the package directory and are not included in the wheel.
238
238
 
239
239
  ## Release Status
240
240
 
241
- Deepy `0.1.7` is released through GitHub and PyPI. Standalone binaries and npm
241
+ Deepy `0.1.8` is released through GitHub and PyPI. Standalone binaries and npm
242
242
  wrappers can be added later, but the primary distribution is the Python CLI.
@@ -210,5 +210,5 @@ assets live outside the package directory and are not included in the wheel.
210
210
 
211
211
  ## Release Status
212
212
 
213
- Deepy `0.1.7` is released through GitHub and PyPI. Standalone binaries and npm
213
+ Deepy `0.1.8` is released through GitHub and PyPI. Standalone binaries and npm
214
214
  wrappers can be added later, but the primary distribution is the Python CLI.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "deepy-cli"
3
- version = "0.1.7"
3
+ version = "0.1.8"
4
4
  description = "Deepy - Vibe coding for DeepSeek models in your terminal"
5
5
  readme = "README.md"
6
6
  authors = [
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.1.7"
3
+ __version__ = "0.1.8"
4
4
 
5
5
 
6
6
  def main() -> None:
@@ -9,5 +9,9 @@ Use the runtime context's command dialect and path style: PowerShell uses
9
9
  PowerShell commands and Windows paths, `cmd` uses cmd syntax, and `posix` uses
10
10
  POSIX shell syntax.
11
11
 
12
+ On Windows PowerShell, Python child processes run with UTF-8 I/O defaults for
13
+ the command invocation; do not ask users to run `chcp` or change their
14
+ PowerShell profile for Unicode output.
15
+
12
16
  Runs in the session cwd, preserves cwd between calls when supported, and returns
13
17
  stdout/stderr JSON with cwd, exit-code, and shell metadata.
@@ -208,6 +208,7 @@ class ShellInvocation:
208
208
  shell_path: str
209
209
  args: list[str]
210
210
  runtime_environment: RuntimeEnvironment
211
+ env: dict[str, str] | None = None
211
212
 
212
213
 
213
214
  def _find_occurrences(text: str, needle: str, scope: tuple[int, int]) -> list[MatchOccurrence]:
@@ -1399,6 +1400,7 @@ class ToolRuntime:
1399
1400
  process = subprocess.Popen(
1400
1401
  [shell_invocation.shell_path, *shell_invocation.args],
1401
1402
  cwd=self.cwd,
1403
+ env=shell_invocation.env,
1402
1404
  text=True,
1403
1405
  stdout=stdout_file,
1404
1406
  stderr=stderr_file,
@@ -1750,8 +1752,7 @@ def _read_text_preserving_newlines(path: Path) -> str:
1750
1752
  def _read_text_metadata(path: Path) -> TextFileMetadata:
1751
1753
  data = path.read_bytes()
1752
1754
  encoding = _detect_text_encoding(data)
1753
- python_encoding = "utf-16" if encoding == "utf16le" else "utf-8"
1754
- text = data.decode(python_encoding, errors="replace")
1755
+ text = data.decode(_python_text_encoding(encoding), errors="replace")
1755
1756
  return TextFileMetadata(
1756
1757
  content=text,
1757
1758
  encoding=encoding,
@@ -1762,12 +1763,32 @@ def _read_text_metadata(path: Path) -> TextFileMetadata:
1762
1763
  def _detect_text_encoding(data: bytes) -> str:
1763
1764
  if len(data) >= 2 and data[0] == 0xFF and data[1] == 0xFE:
1764
1765
  return "utf16le"
1766
+ if data.startswith(b"\xef\xbb\xbf"):
1767
+ return "utf8-sig"
1768
+ try:
1769
+ data.decode("utf-8", errors="strict")
1770
+ return "utf8"
1771
+ except UnicodeDecodeError:
1772
+ pass
1773
+ try:
1774
+ data.decode("gb18030", errors="strict")
1775
+ return "gb18030"
1776
+ except UnicodeDecodeError:
1777
+ return "utf8"
1778
+
1779
+
1780
+ def _python_text_encoding(encoding: str) -> str:
1781
+ if encoding == "utf16le":
1782
+ return "utf-16"
1783
+ if encoding == "utf8-sig":
1784
+ return "utf-8-sig"
1785
+ if encoding == "gb18030":
1786
+ return "gb18030"
1765
1787
  return "utf8"
1766
1788
 
1767
1789
 
1768
1790
  def _write_text_with_encoding(path: Path, content: str, encoding: str) -> None:
1769
- python_encoding = "utf-16" if encoding == "utf16le" else "utf-8"
1770
- path.write_text(content, encoding=python_encoding)
1791
+ path.write_text(content, encoding=_python_text_encoding(encoding))
1771
1792
 
1772
1793
 
1773
1794
  def _coerce_write_content(path: Path, content: object) -> tuple[str, dict[str, object], str | None]:
@@ -2034,25 +2055,41 @@ def _build_shell_command(
2034
2055
  platform_name=platform_name,
2035
2056
  os_name=os_name,
2036
2057
  )
2058
+ process_env = _build_shell_process_env(runtime_environment, env)
2037
2059
  if runtime_environment.command_dialect == "powershell":
2038
2060
  return ShellInvocation(
2039
2061
  shell_path=resolved_shell,
2040
2062
  args=_build_powershell_args(command, marker),
2041
2063
  runtime_environment=runtime_environment,
2064
+ env=process_env,
2042
2065
  )
2043
2066
  if runtime_environment.command_dialect == "cmd":
2044
2067
  return ShellInvocation(
2045
2068
  shell_path=resolved_shell,
2046
2069
  args=_build_cmd_args(command, marker),
2047
2070
  runtime_environment=runtime_environment,
2071
+ env=process_env,
2048
2072
  )
2049
2073
  return ShellInvocation(
2050
2074
  shell_path=resolved_shell,
2051
2075
  args=_build_posix_shell_args(command, marker, resolved_shell),
2052
2076
  runtime_environment=runtime_environment,
2077
+ env=process_env,
2053
2078
  )
2054
2079
 
2055
2080
 
2081
+ def _build_shell_process_env(
2082
+ runtime_environment: RuntimeEnvironment,
2083
+ env: dict[str, str] | None = None,
2084
+ ) -> dict[str, str] | None:
2085
+ if runtime_environment.os_family != "windows":
2086
+ return dict(env) if env is not None else None
2087
+ process_env = dict(os.environ if env is None else env)
2088
+ process_env.setdefault("PYTHONUTF8", "1")
2089
+ process_env.setdefault("PYTHONIOENCODING", "utf-8")
2090
+ return process_env
2091
+
2092
+
2056
2093
  def _build_posix_shell_args(command: str, marker: str, shell_path: str) -> list[str]:
2057
2094
  normalized_command = rewrite_windows_null_redirect(command)
2058
2095
  parts = [
@@ -2073,6 +2110,8 @@ def _build_posix_shell_args(command: str, marker: str, shell_path: str) -> list[
2073
2110
  def _build_powershell_args(command: str, marker: str) -> list[str]:
2074
2111
  script = "\n".join(
2075
2112
  [
2113
+ "$OutputEncoding = [System.Text.UTF8Encoding]::new($false)",
2114
+ "[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false)",
2076
2115
  "$global:LASTEXITCODE = $null",
2077
2116
  "try {",
2078
2117
  command,
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from dataclasses import dataclass
4
4
  from pathlib import Path
5
+ import sys
5
6
  from typing import Callable
6
7
  from unicodedata import normalize
7
8
 
@@ -32,6 +33,7 @@ SHIFT_ENTER_SEQUENCES = (
32
33
  "\x1b[27;2;13~", # xterm modified-key format.
33
34
  "\x1b[13;2u", # Kitty/fixterms CSI-u format, used by modern terminals.
34
35
  )
36
+ _WINDOWS_SHIFT_ENTER_PATCH_ATTR = "_deepy_shift_enter_patched"
35
37
 
36
38
 
37
39
  @dataclass(frozen=True)
@@ -102,6 +104,60 @@ def install_shift_enter_key_sequence_overrides() -> None:
102
104
  prefix_cache = getattr(vt100_parser, "_IS_PREFIX_OF_LONGER_MATCH_CACHE", None)
103
105
  if hasattr(prefix_cache, "clear"):
104
106
  prefix_cache.clear()
107
+ install_windows_shift_enter_key_sequence_override()
108
+
109
+
110
+ def install_windows_shift_enter_key_sequence_override(
111
+ *,
112
+ platform_name: str | None = None,
113
+ console_input_reader_cls: type | None = None,
114
+ ) -> bool:
115
+ resolved_platform = platform_name or sys.platform
116
+ if not resolved_platform.startswith("win"):
117
+ return False
118
+ if console_input_reader_cls is None:
119
+ try:
120
+ from prompt_toolkit.input import win32
121
+ except (AssertionError, ImportError):
122
+ return False
123
+ console_input_reader_cls = win32.ConsoleInputReader
124
+ if getattr(console_input_reader_cls, _WINDOWS_SHIFT_ENTER_PATCH_ATTR, False):
125
+ return True
126
+
127
+ from prompt_toolkit.key_binding.key_processor import KeyPress
128
+
129
+ original_handler = console_input_reader_cls._event_to_key_presses
130
+ shift_pressed = getattr(console_input_reader_cls, "SHIFT_PRESSED", 0x0010)
131
+
132
+ def patched_event_to_key_presses(self, ev):
133
+ key_presses = original_handler(self, ev)
134
+ if _is_windows_shift_enter_key_press(ev, key_presses, shift_pressed=shift_pressed):
135
+ return [KeyPress(Keys.Escape, ""), key_presses[0]]
136
+ return key_presses
137
+
138
+ setattr(
139
+ console_input_reader_cls,
140
+ "_deepy_original_event_to_key_presses",
141
+ original_handler,
142
+ )
143
+ console_input_reader_cls._event_to_key_presses = patched_event_to_key_presses
144
+ setattr(console_input_reader_cls, _WINDOWS_SHIFT_ENTER_PATCH_ATTR, True)
145
+ return True
146
+
147
+
148
+ def _is_windows_shift_enter_key_press(
149
+ ev,
150
+ key_presses: list,
151
+ *,
152
+ shift_pressed: int,
153
+ ) -> bool:
154
+ if not key_presses or len(key_presses) != 1:
155
+ return False
156
+ control_key_state = getattr(ev, "ControlKeyState", 0)
157
+ if not control_key_state & shift_pressed:
158
+ return False
159
+ key = getattr(key_presses[0], "key", None)
160
+ return key in {Keys.ControlM, Keys.ControlJ, Keys.Enter}
105
161
 
106
162
 
107
163
  def prompt_for_input(
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes