deepy-cli 0.2.1__tar.gz → 0.2.2__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.2.1 → deepy_cli-0.2.2}/PKG-INFO +1 -1
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/pyproject.toml +1 -1
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/__init__.py +1 -1
- deepy_cli-0.2.2/src/deepy/data/tools/modify.md +26 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/prompts/system.py +1 -1
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/tools/agents.py +2 -1
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/tools/builtin.py +19 -1
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/tools/file_state.py +16 -0
- deepy_cli-0.2.1/src/deepy/data/tools/modify.md +0 -22
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/README.md +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/__main__.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/cli.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/config/__init__.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/config/settings.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/data/__init__.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/data/skills/skill-creator/SKILL.md +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/data/skills/skill-installer/SKILL.md +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/data/tools/AskUserQuestion.md +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/data/tools/WebFetch.md +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/data/tools/WebSearch.md +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/data/tools/__init__.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/data/tools/edit.md +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/data/tools/read.md +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/data/tools/shell.md +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/data/tools/write.md +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/errors.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/llm/__init__.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/llm/agent.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/llm/compaction.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/llm/context.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/llm/events.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/llm/model_capabilities.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/llm/provider.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/llm/replay.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/llm/runner.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/llm/thinking.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/mcp.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/prompts/__init__.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/prompts/compact.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/prompts/init_agents.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/prompts/rules.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/prompts/runtime_context.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/prompts/tool_docs.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/sessions/__init__.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/sessions/jsonl.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/sessions/manager.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/skill_market.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/skills.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/status.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/tools/__init__.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/tools/result.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/tools/shell_output.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/tools/shell_utils.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/types/__init__.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/types/sdk.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/types/tool_payloads.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/ui/__init__.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/ui/app.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/ui/ask_user_question.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/ui/exit_summary.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/ui/file_mentions.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/ui/loading_text.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/ui/local_command.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/ui/markdown.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/ui/message_view.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/ui/model_picker.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/ui/prompt_buffer.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/ui/prompt_input.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/ui/session_list.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/ui/session_picker.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/ui/skill_picker.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/ui/slash_commands.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/ui/styles.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/ui/terminal.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/ui/theme_picker.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/ui/thinking_state.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/ui/welcome.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/update_check.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/usage.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/utils/__init__.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/utils/debug_logger.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/utils/error_logger.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/utils/json.py +0 -0
- {deepy_cli-0.2.1 → deepy_cli-0.2.2}/src/deepy/utils/notify.py +0 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
## modify
|
|
2
|
+
|
|
3
|
+
Create new files or edit existing files.
|
|
4
|
+
|
|
5
|
+
Use `content` only when the target file does not exist. For existing files, use
|
|
6
|
+
`old_string` and `new_string` for the smallest reliable replacement. You may
|
|
7
|
+
attempt an exact replacement directly when you already know the current text;
|
|
8
|
+
Deepy records the required file snapshot internally when no prior snapshot
|
|
9
|
+
exists. Read first when you need to inspect context. Do not rewrite an existing
|
|
10
|
+
scaffolded file with full content; replace the specific generated block instead.
|
|
11
|
+
|
|
12
|
+
Args for new files: `file_path`, `content`.
|
|
13
|
+
|
|
14
|
+
Args for existing files: `file_path`, `old_string`, `new_string`, optional
|
|
15
|
+
`replace_all`, optional `snippet_id`.
|
|
16
|
+
|
|
17
|
+
Existing-file edits must have a managed snapshot before Deepy commits changes;
|
|
18
|
+
`modify` can create that snapshot internally for direct exact replacements. Stale
|
|
19
|
+
edits are rejected. Repeated matches are rejected unless `replace_all` is true;
|
|
20
|
+
candidate snippets can be reused with `snippet_id`. Success includes diff
|
|
21
|
+
metadata.
|
|
22
|
+
|
|
23
|
+
If several `old_string` attempts fail and you know the complete desired file content,
|
|
24
|
+
re-read the file and use the managed whole-file replacement path. Do not delete the file
|
|
25
|
+
and recreate it with shell commands or here-strings; that bypasses Deepy's encoding,
|
|
26
|
+
newline, and stale-write protections, especially on Windows.
|
|
@@ -45,7 +45,7 @@ def build_system_prompt(
|
|
|
45
45
|
Core rules:
|
|
46
46
|
- Work in the repo with tools: inspect, modify, test, verify.
|
|
47
47
|
- Preserve user changes. Prefer small, verifiable edits.
|
|
48
|
-
- Read
|
|
48
|
+
- Read existing files when you need context; exact `modify` edits can establish the managed snapshot internally.
|
|
49
49
|
- Use `modify` for file changes: `content` only creates new files; existing files use `old_string`/`new_string`.
|
|
50
50
|
- After project generators create scaffold files, read and edit the generated block instead of replacing the file.
|
|
51
51
|
- Run shell commands using the Runtime context's command dialect and path style: `powershell` -> PowerShell with Windows paths; `cmd` -> cmd; `posix` -> POSIX shell.
|
|
@@ -107,7 +107,8 @@ def build_function_tools(
|
|
|
107
107
|
name="modify",
|
|
108
108
|
description=(
|
|
109
109
|
"Create new files or edit existing files. Use content only for files that do not "
|
|
110
|
-
"exist. For existing files, read first
|
|
110
|
+
"exist. For existing files, use old_string/new_string; read first when you need "
|
|
111
|
+
"to inspect context."
|
|
111
112
|
),
|
|
112
113
|
params_json_schema=MODIFY_SCHEMA,
|
|
113
114
|
on_invoke_tool=invoke_modify,
|
|
@@ -1302,7 +1302,14 @@ class ToolRuntime:
|
|
|
1302
1302
|
"modify",
|
|
1303
1303
|
"Provide content for a new file, or both old_string and new_string for an existing file.",
|
|
1304
1304
|
).to_json()
|
|
1305
|
-
return self.edit(
|
|
1305
|
+
return self.edit(
|
|
1306
|
+
path,
|
|
1307
|
+
old,
|
|
1308
|
+
new,
|
|
1309
|
+
replace_all=replace_all,
|
|
1310
|
+
snippet_id=snippet_id,
|
|
1311
|
+
auto_read_if_missing_snapshot=True,
|
|
1312
|
+
)
|
|
1306
1313
|
|
|
1307
1314
|
def write(self, path: str, content: object) -> str:
|
|
1308
1315
|
name = "write"
|
|
@@ -1351,6 +1358,7 @@ class ToolRuntime:
|
|
|
1351
1358
|
new: str,
|
|
1352
1359
|
replace_all: bool = False,
|
|
1353
1360
|
snippet_id: str | None = None,
|
|
1361
|
+
auto_read_if_missing_snapshot: bool = False,
|
|
1354
1362
|
) -> str:
|
|
1355
1363
|
name = "edit"
|
|
1356
1364
|
if not old:
|
|
@@ -1377,6 +1385,14 @@ class ToolRuntime:
|
|
|
1377
1385
|
target = _resolve_in_cwd(self.cwd, path)
|
|
1378
1386
|
if not target.exists():
|
|
1379
1387
|
return ToolResult.error_result(name, f"File does not exist: {target}").to_json()
|
|
1388
|
+
auto_read_before_modify = False
|
|
1389
|
+
if (
|
|
1390
|
+
auto_read_if_missing_snapshot
|
|
1391
|
+
and snippet is None
|
|
1392
|
+
and self.file_state.snapshot_status(target) == "missing"
|
|
1393
|
+
):
|
|
1394
|
+
self.file_state.mark_read(target)
|
|
1395
|
+
auto_read_before_modify = True
|
|
1380
1396
|
ok, error = self.file_state.check_writable(
|
|
1381
1397
|
target,
|
|
1382
1398
|
require_read=True,
|
|
@@ -1465,6 +1481,8 @@ class ToolRuntime:
|
|
|
1465
1481
|
"diff": diff,
|
|
1466
1482
|
"diff_preview": diff,
|
|
1467
1483
|
}
|
|
1484
|
+
if auto_read_before_modify:
|
|
1485
|
+
metadata["autoReadBeforeModify"] = True
|
|
1468
1486
|
if snippet is not None:
|
|
1469
1487
|
metadata["scope"] = _format_scope_metadata(target, snippet, scope, text)
|
|
1470
1488
|
return ToolResult.ok_result(name, f"Edited {target}", metadata=metadata).to_json()
|
|
@@ -2,6 +2,10 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from dataclasses import dataclass, field
|
|
4
4
|
from pathlib import Path
|
|
5
|
+
from typing import Literal
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
SnapshotStatus = Literal["missing", "full", "partial", "deleted", "stale"]
|
|
5
9
|
|
|
6
10
|
|
|
7
11
|
@dataclass
|
|
@@ -58,6 +62,18 @@ class FileState:
|
|
|
58
62
|
return False, "File changed since it was read; read it again before editing."
|
|
59
63
|
return True, None
|
|
60
64
|
|
|
65
|
+
def snapshot_status(self, path: Path) -> SnapshotStatus:
|
|
66
|
+
resolved = path.resolve()
|
|
67
|
+
snapshot = self._snapshots.get(resolved)
|
|
68
|
+
if snapshot is None:
|
|
69
|
+
return "missing"
|
|
70
|
+
if not resolved.exists():
|
|
71
|
+
return "deleted"
|
|
72
|
+
stat = resolved.stat()
|
|
73
|
+
if stat.st_mtime_ns != snapshot.mtime_ns or stat.st_size != snapshot.size:
|
|
74
|
+
return "stale"
|
|
75
|
+
return "full" if snapshot.full_read else "partial"
|
|
76
|
+
|
|
61
77
|
def mark_written(self, path: Path) -> None:
|
|
62
78
|
if path.exists():
|
|
63
79
|
self.mark_read(path)
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
## modify
|
|
2
|
-
|
|
3
|
-
Create new files or edit existing files.
|
|
4
|
-
|
|
5
|
-
Use `content` only when the target file does not exist. For existing files, read the
|
|
6
|
-
file first, then use `old_string` and `new_string` for the smallest reliable
|
|
7
|
-
replacement. Do not rewrite an existing scaffolded file with full content; replace the
|
|
8
|
-
specific generated block instead.
|
|
9
|
-
|
|
10
|
-
Args for new files: `file_path`, `content`.
|
|
11
|
-
|
|
12
|
-
Args for existing files: `file_path`, `old_string`, `new_string`, optional
|
|
13
|
-
`replace_all`, optional `snippet_id`.
|
|
14
|
-
|
|
15
|
-
Existing files must be read before editing. Stale edits are rejected. Repeated matches
|
|
16
|
-
are rejected unless `replace_all` is true; candidate snippets can be reused with
|
|
17
|
-
`snippet_id`. Success includes diff metadata.
|
|
18
|
-
|
|
19
|
-
If several `old_string` attempts fail and you know the complete desired file content,
|
|
20
|
-
re-read the file and use the managed whole-file replacement path. Do not delete the file
|
|
21
|
-
and recreate it with shell commands or here-strings; that bypasses Deepy's encoding,
|
|
22
|
-
newline, and stale-write protections, especially on Windows.
|
|
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
|
|
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
|