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.
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/PKG-INFO +2 -2
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/README.md +1 -1
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/pyproject.toml +1 -1
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/__init__.py +1 -1
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/data/tools/shell.md +4 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/tools/builtin.py +43 -4
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/ui/prompt_input.py +56 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/__main__.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/cli.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/config/__init__.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/config/settings.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/data/__init__.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/data/tools/AskUserQuestion.md +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/data/tools/WebFetch.md +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/data/tools/WebSearch.md +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/data/tools/__init__.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/data/tools/edit.md +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/data/tools/modify.md +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/data/tools/read.md +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/data/tools/write.md +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/errors.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/llm/__init__.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/llm/agent.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/llm/compaction.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/llm/context.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/llm/events.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/llm/model_capabilities.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/llm/provider.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/llm/replay.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/llm/runner.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/llm/thinking.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/prompts/__init__.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/prompts/compact.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/prompts/rules.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/prompts/runtime_context.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/prompts/system.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/prompts/tool_docs.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/sessions/__init__.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/sessions/jsonl.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/sessions/manager.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/skills.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/status.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/tools/__init__.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/tools/agents.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/tools/file_state.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/tools/result.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/tools/shell_utils.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/ui/__init__.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/ui/app.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/ui/ask_user_question.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/ui/exit_summary.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/ui/loading_text.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/ui/markdown.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/ui/message_view.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/ui/model_picker.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/ui/prompt_buffer.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/ui/session_list.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/ui/session_picker.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/ui/slash_commands.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/ui/styles.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/ui/terminal.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/ui/theme_picker.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/ui/thinking_state.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/ui/welcome.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/update_check.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/usage.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/utils/__init__.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/utils/debug_logger.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/utils/error_logger.py +0 -0
- {deepy_cli-0.1.7 → deepy_cli-0.1.8}/src/deepy/utils/json.py +0 -0
- {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.
|
|
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.
|
|
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.
|
|
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.
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|