ziya 0.1.42__py3-none-any.whl → 0.1.44__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.

Potentially problematic release.


This version of ziya might be problematic. Click here for more details.

app/agents/agent.py CHANGED
@@ -55,16 +55,8 @@ def get_combined_docs_from_files(files) -> str:
55
55
  try:
56
56
  full_file_path = os.path.join(user_codebase_dir, file_path)
57
57
  docs = TextLoader(full_file_path).load()
58
- for doc_index, doc in enumerate(docs):
59
- # Add line numbers to the content
60
- lines = doc.page_content.split('\n')
61
- numbered_lines = [f"{i + 1:4d} | {line}" for i, line in enumerate(lines)]
62
- numbered_content = '\n'.join(numbered_lines)
63
-
64
- # Use the numbered content instead of the original
65
- doc.page_content = numbered_content
58
+ for doc in docs:
66
59
  combined_contents += f"File: {file_path}\n{doc.page_content}\n\n"
67
-
68
60
  except Exception as e:
69
61
  print(f"Skipping file {full_file_path} due to error: {e}")
70
62
 
app/agents/prompts.py CHANGED
@@ -6,10 +6,6 @@ template = """
6
6
 
7
7
  You are an excellent coder. Help the user with their coding tasks. You are given the codebase of the user in your context.
8
8
 
9
- IMPORTANT: The file contents provided to you have line numbers added at the beginning of each line in the format "
10
- 1 | <line content>". These line numbers start at 1, matching Git's conventions. Use these line numbers when generating
11
- diff hunks to ensure accurate line numbering.
12
-
13
9
  IMPORTANT: When recommending code changes, format your response as a standard Git diff format unless the user specifies otherwise.
14
10
  Follow these strict guidelines for diff formatting:
15
11
 
@@ -36,25 +32,23 @@ Follow these strict guidelines for diff formatting:
36
32
  5. End each diff block with ``` on a new line
37
33
 
38
34
  CRITICAL: After generating each hunk diff, carefully review and verify the following:
39
- 1. Ensure all Hunk Headers (e.g., @@ -4,7 +4,2 @@) are accurate. The numbers should correctly reflect the lines being changed, added, or removed.
40
- 2. Verify that the line numbers in the Hunk Headers match the actual content changes in the diff.
41
- 3. Check that the diff can be applied cleanly using `git apply`. This means:
35
+ 1. Check that the diff can be applied cleanly using `git apply`. This means:
42
36
  - The context lines (unchanged lines) in the diff should match the original file content.
43
37
  - The line numbers and content should be consistent throughout the diff.
44
38
  - There should be no conflicts or inconsistencies in the changes.
45
- 4. If you find any errors or inconsistencies, correct them before finalizing the diff.
46
- 5. For each hunk in the diff, please make sure it starts or ends with a line containing content instead of empty line, if possible.
47
- 6. When creating a new file, ensure the line `new file mode 100644` is included to specify file permissions.
39
+ 2. If you find any errors or inconsistencies, correct them before finalizing the diff.
40
+ 3. For each hunk in the diff, please make sure it starts or ends with a line containing content instead of empty line, if possible.
41
+ 4. When creating a new file, ensure the line `new file mode 100644` is included to specify file permissions.
48
42
  5. When deleting a file, include `deleted file mode` to indicate that the file has been removed. Each line in the
49
43
  deleted file should be prefixed with `-` to indicate the content removal.
44
+ 6. Lines ending with a newline (\n) should not be interpreted as an additional line. Treat \n as the end of the current
45
+ line’s content, not as a new line in the file.
50
46
 
51
47
  Do not include any explanatory text within the diff blocks. If you need to provide explanations or comments, do so outside the diff blocks.
52
48
 
53
49
  The codebase is provided at the end of this prompt in a specific format.
54
50
  The code that the user has given to you for context is in the format like below where first line has the File path and then the content follows.
55
51
  Each file starts with "File: <filepath>" followed by its content on subsequent lines.
56
- Remember, each line of the file content now starts with a line number, beginning from 1. Use these numbers to generate
57
- accurate hunk diffs, but do not include the line numbers in the actual diff content.
58
52
 
59
53
  File: <filepath>
60
54
  <Content of the file>.
app/main.py CHANGED
@@ -23,8 +23,6 @@ def parse_arguments():
23
23
  help="Port number to run Ziya frontend on (e.g., --port 8080)")
24
24
  parser.add_argument("--version", action="store_true",
25
25
  help="Prints the version of Ziya")
26
- parser.add_argument("--enable-code-apply", action="store_true",
27
- help="Enable the feature to show the button to apply code diffs (unstable)")
28
26
  parser.add_argument("--max-depth", type=int, default=15,
29
27
  help="Maximum depth for folder structure traversal (e.g., --max-depth 20)")
30
28
  return parser.parse_args()
@@ -40,9 +38,6 @@ def setup_environment(args):
40
38
  os.environ["ZIYA_AWS_PROFILE"] = args.profile
41
39
  if args.model:
42
40
  os.environ["ZIYA_AWS_MODEL"] = args.model
43
- if args.enable_code_apply:
44
- os.environ["ZIYA_ENABLE_CODE_APPLY"] = "true"
45
-
46
41
  os.environ["ZIYA_MAX_DEPTH"] = str(args.max_depth)
47
42
 
48
43
 
app/server.py CHANGED
@@ -14,7 +14,7 @@ from pydantic import BaseModel
14
14
  # import pydevd_pycharm
15
15
  import uvicorn
16
16
 
17
- from app.utils.code_util import us_git_to_apply_code_diff, correct_git_diff
17
+ from app.utils.code_util import use_git_to_apply_code_diff, correct_git_diff
18
18
  from app.utils.directory_util import get_ignored_patterns
19
19
  from app.utils.logging_utils import logger
20
20
  from app.utils.gitignore_parser import parse_gitignore_patterns
@@ -38,12 +38,8 @@ add_routes(app, agent_executor, disabled_endpoints=["playground"], path="/ziya")
38
38
 
39
39
  @app.get("/")
40
40
  async def root(request: Request):
41
- enable_code_apply = os.environ.get("ZIYA_ENABLE_CODE_APPLY", "false")
42
- enable_code_apply_bool = enable_code_apply.lower() == "true"
43
- logger.info(f"enable_code_apply_bool: {enable_code_apply_bool}")
44
41
  return templates.TemplateResponse("index.html", {
45
- "request": request,
46
- "enable_code_apply": str(enable_code_apply_bool).lower()
42
+ "request": request
47
43
  })
48
44
 
49
45
 
@@ -120,8 +116,10 @@ async def apply_changes(request: ApplyChangesRequest):
120
116
  if not user_codebase_dir:
121
117
  raise ValueError("ZIYA_USER_CODEBASE_DIR environment variable is not set")
122
118
 
123
- corrected_diff = correct_git_diff(request.diff)
124
- us_git_to_apply_code_diff(corrected_diff)
119
+ file_path = os.path.join(user_codebase_dir, request.filePath)
120
+ corrected_diff = correct_git_diff(request.diff, file_path)
121
+ logger.info(f"corrected diff content: \n{corrected_diff}")
122
+ use_git_to_apply_code_diff(corrected_diff)
125
123
  return {'message': 'Changes applied successfully'}
126
124
  except Exception as e:
127
125
  logger.error(f"Error applying changes: {str(e)}", exc_info=True)
app/utils/code_util.py CHANGED
@@ -6,7 +6,7 @@ import re
6
6
 
7
7
  HUNK_HEADER_REGEX = re.compile(r'^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@')
8
8
 
9
- def us_git_to_apply_code_diff(git_diff: str):
9
+ def use_git_to_apply_code_diff(git_diff: str):
10
10
  """
11
11
  Apply a git diff to the user's codebase.
12
12
 
@@ -53,7 +53,7 @@ def us_git_to_apply_code_diff(git_diff: str):
53
53
  finally:
54
54
  os.remove(temp_file)
55
55
 
56
- def correct_git_diff(git_diff: str) -> str:
56
+ def correct_git_diff(git_diff: str, original_file_path: str) -> str:
57
57
  """
58
58
  Corrects the hunk headers in a git diff string by recalculating the line counts and
59
59
  adjusting the starting line numbers in the new file, considering the cumulative effect of
@@ -64,6 +64,7 @@ def correct_git_diff(git_diff: str) -> str:
64
64
 
65
65
  Parameters:
66
66
  git_diff (str): The git diff string to be corrected. It may contain multiple hunks
67
+ original_file_path (str): Path to the original file to calculate correct start_line_old
67
68
  and incorrect hunk headers.
68
69
 
69
70
  Returns:
@@ -83,6 +84,20 @@ def correct_git_diff(git_diff: str) -> str:
83
84
  # Split the diff into lines
84
85
  lines = git_diff.split('\n')
85
86
 
87
+ # Check if this is a new file creation by looking for "new file mode" in the diff
88
+ is_new_file = any('new file mode 100644' in line for line in lines[:5])
89
+ original_content = []
90
+
91
+ if not is_new_file:
92
+ try:
93
+ with open(original_file_path, 'r') as f:
94
+ original_content = f.read().splitlines()
95
+ except FileNotFoundError:
96
+ error_msg = (
97
+ f"File {original_file_path} not found and diff does not indicate new file creation. "
98
+ )
99
+ raise FileNotFoundError(error_msg)
100
+
86
101
  corrected_lines = []
87
102
  line_index = 0
88
103
 
@@ -96,8 +111,8 @@ def correct_git_diff(git_diff: str) -> str:
96
111
 
97
112
  if hunk_match:
98
113
  # Process the hunk
99
- corrected_hunk_header, hunk_lines, line_index, line_offset = _process_hunk(
100
- lines, line_index, cumulative_line_offset
114
+ corrected_hunk_header, hunk_lines, line_index, line_offset = _process_hunk_with_original_content(
115
+ lines, line_index, cumulative_line_offset, original_content
101
116
  )
102
117
 
103
118
  # Update cumulative_line_offset
@@ -115,7 +130,74 @@ def correct_git_diff(git_diff: str) -> str:
115
130
  corrected_diff = '\n'.join(corrected_lines)
116
131
  return corrected_diff
117
132
 
118
- def _process_hunk(lines: list, start_index: int, cumulative_line_offset: int):
133
+ def _find_correct_old_start_line(original_content: list, hunk_lines: list) -> int:
134
+ """
135
+ Finds the correct starting line number in the original file by matching context and deleted lines.
136
+
137
+ Parameters:
138
+ original_content (list): List of lines from the original file
139
+ hunk_lines (list): List of lines in the current hunk
140
+
141
+ Returns:
142
+ int: The correct 1-based line number where the hunk should start in the original file
143
+
144
+ The function works by:
145
+ 1. Extracting context and deleted lines from the hunk (ignoring added lines)
146
+ 2. Creating a pattern from these lines
147
+ 3. Finding where this pattern matches in the original file
148
+ 4. Converting the matching position to a 1-based line number
149
+ """
150
+ # Extract context and deleted lines from the hunk
151
+ if not original_content:
152
+ # Creating a new file, should start with @@ -0,0 +1,N @@
153
+ return 0
154
+
155
+ if len(hunk_lines) < 3:
156
+ error_msg = (
157
+ f"Invalid git diff format: Expected at least 2 lines in the hunk, but got {len(hunk_lines)} lines.\n"
158
+ + "Hunk content:\n{}".format('\n'.join(hunk_lines)))
159
+ logger.error(error_msg)
160
+ raise RuntimeError("Invalid git diff format.")
161
+
162
+ context_and_deleted = []
163
+ for line in hunk_lines:
164
+ if line.startswith(' ') or line.startswith('-'):
165
+ # Remove the prefix character
166
+ context_and_deleted.append(line[1:])
167
+
168
+ if not context_and_deleted:
169
+ error_msg = (
170
+ "Invalid git diff format: No context or deleted lines found in the hunk.\n"
171
+ "Each hunk must contain at least one context line (starting with space) "
172
+ "or deleted line (starting with '-').\n"
173
+ "Hunk content:\n{}".format('\n'.join(hunk_lines)))
174
+ raise RuntimeError(error_msg)
175
+
176
+ # Search for the pattern in the original file
177
+ pattern_length = len(context_and_deleted)
178
+ for i in range(len(original_content) - pattern_length + 1):
179
+ matches = True
180
+ for j in range(pattern_length):
181
+ if j >= len(context_and_deleted):
182
+ break
183
+ if i + j >= len(original_content) or original_content[i + j] != context_and_deleted[j]:
184
+ matches = False
185
+ break
186
+ if matches:
187
+ # Found the correct position git diff start with 1.
188
+ return i + 1
189
+
190
+ joined_context_and_deleted = '\n'.join(context_and_deleted)
191
+ error_msg = (
192
+ "Failed to locate the hunk position in the original file.\n"
193
+ "This usually happens when the context lines in the diff don't match the original file content.\n"
194
+ f"Context and deleted lines being searched:\n{joined_context_and_deleted}\n"
195
+ "Please ensure the diff is generated against the correct version of the file."
196
+ )
197
+ logger.error(error_msg)
198
+ raise RuntimeError(error_msg)
199
+
200
+ def _process_hunk_with_original_content(lines: list, start_index: int, cumulative_line_offset: int, original_content: list):
119
201
  """
120
202
  Processes a single hunk starting at start_index in lines, recalculates the line counts,
121
203
  and returns the corrected hunk header, hunk lines, and the updated index after the hunk.
@@ -124,6 +206,7 @@ def _process_hunk(lines: list, start_index: int, cumulative_line_offset: int):
124
206
  lines (list): The list of lines from the diff.
125
207
  start_index (int): The index in lines where the hunk header is located.
126
208
  cumulative_line_offset (int): The cumulative line offset from previous hunks.
209
+ original_content (list): List of lines from the original file.
127
210
 
128
211
  Returns:
129
212
  tuple:
@@ -137,11 +220,6 @@ def _process_hunk(lines: list, start_index: int, cumulative_line_offset: int):
137
220
  """
138
221
 
139
222
  line_index = start_index
140
- hunk_header_line = lines[line_index]
141
- hunk_match = HUNK_HEADER_REGEX.match(hunk_header_line)
142
-
143
- # Extract the starting line numbers from the hunk header
144
- start_line_old = int(hunk_match.group(1))
145
223
 
146
224
  # Initialize counts for recalculation
147
225
  actual_count_old = 0
@@ -161,7 +239,10 @@ def _process_hunk(lines: list, start_index: int, cumulative_line_offset: int):
161
239
  hunk_lines.append(hunk_line)
162
240
  line_index += 1
163
241
 
164
- # Now process hunk_lines to calculate counts
242
+ # Find the correct start_line_old by matching context and deleted lines
243
+ start_line_old = _find_correct_old_start_line(original_content, hunk_lines)
244
+
245
+ # Calculate counts for the hunk lines
165
246
  for hunk_line in hunk_lines:
166
247
  if hunk_line.startswith('+') and not hunk_line.startswith('+++'):
167
248
  actual_count_new += 1
@@ -172,8 +253,15 @@ def _process_hunk(lines: list, start_index: int, cumulative_line_offset: int):
172
253
  actual_count_old += 1
173
254
  actual_count_new += 1
174
255
 
175
- # Adjust start_line_new considering previous line offsets
176
- corrected_start_line_new = start_line_old + cumulative_line_offset
256
+ # Special handling for new file creation
257
+ if start_line_old == 0:
258
+ # For new files:
259
+ # count_old should be 0
260
+ actual_count_old = 0
261
+ corrected_start_line_new = 1
262
+ else:
263
+ # For existing files, adjust start_line_new considering previous line offsets
264
+ corrected_start_line_new = start_line_old + cumulative_line_offset
177
265
 
178
266
  # Calculate line offset for subsequent hunks
179
267
  line_offset = actual_count_new - actual_count_old
@@ -211,24 +299,3 @@ def _format_hunk_header(start_old: int, count_old: int, start_new: int, count_ne
211
299
  if count_new != 1:
212
300
  new_part += f',{count_new}'
213
301
  return f'@@ {old_part} {new_part} @@'
214
-
215
-
216
-
217
- if __name__ == '__main__':
218
- # TODO: Create unit test and move these code to unit test
219
- diff = """\
220
- diff --git a/file.txt b/file.txt
221
- index e69de29..4b825dc 100644
222
- --- a/file.txt
223
- +++ b/file.txt
224
- @@ -1,5 +1,5 @@
225
- Line one
226
- +Line two
227
- Line three
228
- Line four
229
- Line five
230
- @@ -10,2 +10,2 @@
231
- Line ten
232
- -Line eleven
233
- +Line eleven modified"""
234
- print(correct_git_diff(diff))
pyproject.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "ziya"
3
- version = "0.1.42"
3
+ version = "0.1.44"
4
4
  description = ""
5
5
  authors = ["Vishnu Krishnaprasad <vishnukool@gmail.com>"]
6
6
  readme = "README.md"
@@ -25,6 +25,9 @@ langchain-cli = ">=0.0.15"
25
25
  pydevd-pycharm = "^243.18137.19"
26
26
  langchain-community = "^0.3.1"
27
27
 
28
+ [tool.poetry.group.dev.dependencies]
29
+ pytest = "^8.3.3"
30
+
28
31
  [build-system]
29
32
  requires = ["poetry-core"]
30
33
  build-backend = "poetry.core.masonry.api"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "files": {
3
3
  "main.css": "/static/css/main.8af23da0.css",
4
- "main.js": "/static/js/main.fee8aad7.js",
4
+ "main.js": "/static/js/main.50c95184.js",
5
5
  "static/media/fa-solid-900.ttf": "/static/media/fa-solid-900.bacd5de623fb563b961a.ttf",
6
6
  "static/media/fa-brands-400.ttf": "/static/media/fa-brands-400.60127e352b7a11f7f1bc.ttf",
7
7
  "static/media/fa-solid-900.woff2": "/static/media/fa-solid-900.4d986b00ff9ca3828fbd.woff2",
@@ -12,10 +12,10 @@
12
12
  "static/media/fa-v4compatibility.woff2": "/static/media/fa-v4compatibility.cf7f5903d06b79ad60f1.woff2",
13
13
  "index.html": "/index.html",
14
14
  "main.8af23da0.css.map": "/static/css/main.8af23da0.css.map",
15
- "main.fee8aad7.js.map": "/static/js/main.fee8aad7.js.map"
15
+ "main.50c95184.js.map": "/static/js/main.50c95184.js.map"
16
16
  },
17
17
  "entrypoints": [
18
18
  "static/css/main.8af23da0.css",
19
- "static/js/main.fee8aad7.js"
19
+ "static/js/main.50c95184.js"
20
20
  ]
21
21
  }
templates/index.html CHANGED
@@ -1 +1 @@
1
- <!doctype html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Ziya - Code Assistant</title><link rel="icon" href="/favicon.ico" type="image/x-icon"><script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script><script>window.enableCodeApply="{{ enable_code_apply | lower }}"</script><script defer="defer" src="/static/js/main.fee8aad7.js"></script><link href="/static/css/main.8af23da0.css" rel="stylesheet"></head><body><div id="root"></div></body></html>
1
+ <!doctype html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Ziya - Code Assistant</title><link rel="icon" href="/favicon.ico" type="image/x-icon"><script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script><script>window.enableCodeApply="true"</script><script defer="defer" src="/static/js/main.50c95184.js"></script><link href="/static/css/main.8af23da0.css" rel="stylesheet"></head><body><div id="root"></div></body></html>