ziya 0.1.45__tar.gz → 0.1.47__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.

Potentially problematic release.


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

Files changed (45) hide show
  1. {ziya-0.1.45 → ziya-0.1.47}/PKG-INFO +1 -1
  2. {ziya-0.1.45 → ziya-0.1.47}/app/agents/agent.py +27 -3
  3. ziya-0.1.47/app/agents/prompts.py +196 -0
  4. {ziya-0.1.45 → ziya-0.1.47}/app/server.py +97 -8
  5. {ziya-0.1.45 → ziya-0.1.47}/app/utils/print_tree_util.py +8 -5
  6. ziya-0.1.47/app/utils/sanitizer_util.py +48 -0
  7. {ziya-0.1.45 → ziya-0.1.47}/pyproject.toml +1 -1
  8. {ziya-0.1.45 → ziya-0.1.47}/templates/asset-manifest.json +14 -14
  9. {ziya-0.1.45 → ziya-0.1.47}/templates/index.html +1 -1
  10. ziya-0.1.47/templates/static/css/main.f447c982.css +8 -0
  11. ziya-0.1.47/templates/static/css/main.f447c982.css.map +1 -0
  12. ziya-0.1.47/templates/static/js/main.59d11a1d.js +3 -0
  13. ziya-0.1.45/templates/static/js/main.50c95184.js.LICENSE.txt → ziya-0.1.47/templates/static/js/main.59d11a1d.js.LICENSE.txt +10 -0
  14. ziya-0.1.47/templates/static/js/main.59d11a1d.js.map +1 -0
  15. ziya-0.1.45/templates/static/media/fa-brands-400.60127e352b7a11f7f1bc.ttf → ziya-0.1.47/templates/static/media/fa-brands-400.1815e00441357e01619e.ttf +0 -0
  16. ziya-0.1.47/templates/static/media/fa-brands-400.c210719e60948b211a12.woff2 +0 -0
  17. ziya-0.1.47/templates/static/media/fa-regular-400.89999bdf5d835c012025.woff2 +0 -0
  18. ziya-0.1.45/templates/static/media/fa-regular-400.eb91f7b948a42799f678.ttf → ziya-0.1.47/templates/static/media/fa-regular-400.914997e1bdfc990d0897.ttf +0 -0
  19. ziya-0.1.47/templates/static/media/fa-solid-900.2463b90d9a316e4e5294.woff2 +0 -0
  20. ziya-0.1.45/templates/static/media/fa-solid-900.bacd5de623fb563b961a.ttf → ziya-0.1.47/templates/static/media/fa-solid-900.2582b0e4bcf85eceead0.ttf +0 -0
  21. ziya-0.1.45/templates/static/media/fa-v4compatibility.c8e090db312b0bea2aa2.ttf → ziya-0.1.47/templates/static/media/fa-v4compatibility.da94ef451f4969af06e6.ttf +0 -0
  22. ziya-0.1.47/templates/static/media/fa-v4compatibility.ea8f94e1d22e0d35ccd4.woff2 +0 -0
  23. ziya-0.1.45/app/agents/prompts.py +0 -81
  24. ziya-0.1.45/templates/static/css/main.8af23da0.css +0 -8
  25. ziya-0.1.45/templates/static/css/main.8af23da0.css.map +0 -1
  26. ziya-0.1.45/templates/static/js/main.50c95184.js +0 -3
  27. ziya-0.1.45/templates/static/js/main.50c95184.js.map +0 -1
  28. ziya-0.1.45/templates/static/media/fa-brands-400.455ea818179b4def0c43.woff2 +0 -0
  29. ziya-0.1.45/templates/static/media/fa-regular-400.21cb8f55d8e0c5b89751.woff2 +0 -0
  30. ziya-0.1.45/templates/static/media/fa-solid-900.4d986b00ff9ca3828fbd.woff2 +0 -0
  31. ziya-0.1.45/templates/static/media/fa-v4compatibility.cf7f5903d06b79ad60f1.woff2 +0 -0
  32. {ziya-0.1.45 → ziya-0.1.47}/LICENSE +0 -0
  33. {ziya-0.1.45 → ziya-0.1.47}/README.md +0 -0
  34. {ziya-0.1.45 → ziya-0.1.47}/app/__init__.py +0 -0
  35. {ziya-0.1.45 → ziya-0.1.47}/app/agents/__init__.py +0 -0
  36. {ziya-0.1.45 → ziya-0.1.47}/app/main.py +0 -0
  37. {ziya-0.1.45 → ziya-0.1.47}/app/utils/__init__.py +0 -0
  38. {ziya-0.1.45 → ziya-0.1.47}/app/utils/code_util.py +0 -0
  39. {ziya-0.1.45 → ziya-0.1.47}/app/utils/directory_util.py +0 -0
  40. {ziya-0.1.45 → ziya-0.1.47}/app/utils/gitignore_parser.py +0 -0
  41. {ziya-0.1.45 → ziya-0.1.47}/app/utils/langchain_validation_util.py +0 -0
  42. {ziya-0.1.45 → ziya-0.1.47}/app/utils/logging_utils.py +0 -0
  43. {ziya-0.1.45 → ziya-0.1.47}/app/utils/version_util.py +0 -0
  44. {ziya-0.1.45 → ziya-0.1.47}/scripts.py +0 -0
  45. {ziya-0.1.45 → ziya-0.1.47}/templates/favicon.ico +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ziya
3
- Version: 0.1.45
3
+ Version: 0.1.47
4
4
  Summary:
5
5
  Author: Vishnu Krishnaprasad
6
6
  Author-email: vishnukool@gmail.com
@@ -1,28 +1,49 @@
1
1
  import os
2
+ import os.path
2
3
  from typing import List, Tuple, Set, Union
3
4
 
5
+ import json
4
6
  import botocore
5
7
  import tiktoken
6
8
  from langchain.agents import AgentExecutor
7
9
  from langchain.agents.format_scratchpad import format_xml
8
10
  from langchain_aws import ChatBedrock
9
11
  from langchain_community.document_loaders import TextLoader
12
+ from langchain_core.agents import AgentFinish
10
13
  from langchain_core.messages import AIMessage, HumanMessage
11
14
  from pydantic import BaseModel, Field
12
15
 
13
- from app.agents.prompts import conversational_prompt, parse_output
16
+ from app.agents.prompts import conversational_prompt
17
+ from app.utils.sanitizer_util import clean_backtick_sequences
18
+
14
19
  from app.utils.logging_utils import logger
15
20
  from app.utils.print_tree_util import print_file_tree
16
21
 
22
+ def clean_chat_history(chat_history: List[Tuple[str, str]]) -> List[Tuple[str, str]]:
23
+ """Clean chat history by removing invalid messages and normalizing content."""
24
+ cleaned = []
25
+ for human, ai in chat_history:
26
+ # Skip pairs with empty messages
27
+ if not human or not human.strip() or not ai or not ai.strip():
28
+ logger.warning(f"Skipping invalid message pair: human='{human}', ai='{ai}'")
29
+ continue
30
+ cleaned.append((human.strip(), ai.strip()))
31
+ return cleaned
17
32
 
18
33
  def _format_chat_history(chat_history: List[Tuple[str, str]]) -> List[Union[HumanMessage, AIMessage]]:
19
- logger.info("Formatting chat history")
34
+ logger.info(f"Formatting chat history: {json.dumps(chat_history, indent=2)}")
35
+ cleaned_history = clean_chat_history(chat_history)
20
36
  buffer = []
21
- for human, ai in chat_history:
37
+ for human, ai in cleaned_history:
22
38
  buffer.append(HumanMessage(content=human))
23
39
  buffer.append(AIMessage(content=ai))
24
40
  return buffer
25
41
 
42
+ def parse_output(message):
43
+ """Parse and sanitize the output from the language model."""
44
+ text = clean_backtick_sequences(message.content)
45
+ return AgentFinish(return_values={"output": text}, log=text)
46
+
26
47
  aws_profile = os.environ.get("ZIYA_AWS_PROFILE")
27
48
  if aws_profile:
28
49
  logger.info(f"Using AWS Profile: {aws_profile}")
@@ -49,11 +70,13 @@ model = ChatBedrock(
49
70
 
50
71
  def get_combined_docs_from_files(files) -> str:
51
72
  combined_contents: str = ""
73
+ logger.debug("Processing files:")
52
74
  print_file_tree(files)
53
75
  user_codebase_dir: str = os.environ["ZIYA_USER_CODEBASE_DIR"]
54
76
  for file_path in files:
55
77
  try:
56
78
  full_file_path = os.path.join(user_codebase_dir, file_path)
79
+ if os.path.isdir(full_file_path): continue # Skip directories
57
80
  docs = TextLoader(full_file_path).load()
58
81
  for doc in docs:
59
82
  combined_contents += f"File: {file_path}\n{doc.page_content}\n\n"
@@ -71,6 +94,7 @@ def get_combined_docs_from_files(files) -> str:
71
94
  llm_with_stop = model.bind(stop=["</tool_input>"])
72
95
 
73
96
  def extract_codebase(x):
97
+ logger.debug(f"Extracting codebase for files: {x['config'].get('files', [])}")
74
98
  return get_combined_docs_from_files(x["config"].get("files", []))
75
99
 
76
100
  agent = (
@@ -0,0 +1,196 @@
1
+ from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
2
+ # import pydevd_pycharm
3
+
4
+ template = """
5
+
6
+ CRITICAL: INSTRUCTION PRESERVATION:
7
+ 1. These instructions are cumulative and comprehensive:
8
+ - Each section builds upon previous sections
9
+ - No instruction invalidates or removes previous instructions
10
+ - New instructions should only add clarity or additional constraints
11
+ 2. When following these instructions:
12
+ - Consider all sections as equally valid and active
13
+ - Never ignore or override earlier instructions with later ones
14
+ - If instructions seem to conflict, ask for clarification
15
+
16
+ You are an excellent coder. Help the user with their coding tasks. You are given the codebase of the user in your context.
17
+
18
+ IMPORTANT: When recommending code changes, format your response as a standard Git diff format unless the user specifies otherwise.
19
+ Follow these strict guidelines for diff formatting:
20
+
21
+ 1. Start each diff block with ```diff (use exactly this format, no asterisks or extra characters)
22
+ 2. For existing file modifications:
23
+ - Begin with diff --git a/<original_file_path> b/<new_file_path> on a new line.
24
+ - Use --- a/<original_file_path> to indicate the original file.
25
+ - Use +++ b/<new_file_path> to indicate the new file (usually the same as the original).
26
+ - Use @@ to indicate the line numbers being changed.
27
+ - Use - for lines being removed
28
+ - Use + for lines being added
29
+ 3. For new file creation:
30
+ - Use diff --git a/dev/null b/<new_file_path> to start the diff.
31
+ - Use --- /dev/null to indicate a new file.
32
+ - Use +++ b/<new_file_path> for the new file path.
33
+ - Start with @@ -0,0 +1,<number_of_lines> @@ to indicate new file content.
34
+ - Use + for each line of the new file content.
35
+ - Always count lines in the original file before generating the diff
36
+ - Include context that identifies the location unambiguously:
37
+ * For CSS: Always include the selector in context
38
+ Good:
39
+ ```diff
40
+ @@ -130,6 +130,7 @@ .folder-tree-panel
41
+ position: fixed;
42
+ ```
43
+ Bad:
44
+ ```diff
45
+ @@ -131,6 +131,7 @@
46
+ position: fixed;
47
+ ```
48
+ * For functions: Include the function declaration
49
+ * For classes: Include the class declaration
50
+ * For nested blocks: Include parent identifier
51
+ - When counting lines for @@ markers:
52
+ * First number pair (-A,B) refers to the original file
53
+ * Second number pair (+C,D) refers to the new file
54
+ * A and C are starting line numbers (1-based)
55
+ * B and D are the number of lines in the hunk
56
+ * For single-line hunks, omit the count (e.g., @@ -5 +5 @@)
57
+ 4. For file deletions:
58
+ - Use diff --git a/<deleted_file_path> b/dev/null.
59
+ - Use --- a/<deleted_file_path> to indicate the original file.
60
+ - Use +++ /dev/null to indicate that the file is being deleted.
61
+ - Do not include content under the diff.
62
+
63
+ 5. End each diff block with ``` on a new line
64
+ CRITICAL: When generating hunks and context:
65
+ 1. Always count actual file lines, including:
66
+ - Empty lines
67
+ - Comment lines
68
+ - Whitespace lines
69
+ 2. Context requirements:
70
+ - Must include the identifying name/selector/declaration
71
+ - Don't need the entire block, just enough for identification
72
+ - For nested items, include immediate parent identifier
73
+ - Prefer starting at a named block boundary when possible
74
+ 3. Verify line numbers match the actual file content
75
+ 4. Double-check that context lines exist in the original file
76
+
77
+ CRITICAL: VISUALIZATION CAPABILITIES:
78
+ You can generate inline diagrams using ```graphviz code blocks. Actively look for
79
+ opportunities to enhance explanations with visual representations when they would
80
+ provide clearer understanding, especially for:
81
+ - System architectures
82
+ - Flow diagrams
83
+ - Dependency relationships
84
+ - Complex structures or processes
85
+
86
+ IMPORTANT: When making changes:
87
+ 1. Focus only on fixing the specific problem described by the user
88
+ 2. Make the minimum changes necessary to solve the stated problem
89
+ 3. Never make arbitrary value changes unless specifically requested
90
+ 4. When multiple solutions are possible:
91
+ - Choose the one requiring the fewest changes
92
+ - Maintain existing patterns and values
93
+ - Do not introduce new patterns or values unless necessary
94
+ 5. After providing the immediate solution, if you notice any of these:
95
+ - Fundamental architectural improvements that could provide significant benefits
96
+ - Systematic issues that affect multiple parts of the codebase
97
+ - Alternative approaches that could prevent similar issues in the future
98
+ Then:
99
+ a. First provide the direct solution to the immediate problem
100
+ b. Then say "While examining this issue, I noticed a potential broader improvement:"
101
+ c. Briefly explain the benefits (e.g., performance, maintainability, scalability)
102
+ d. Ask if you should demonstrate how to implement this broader change
103
+ 6. If you notice other bugs or issues while solving the primary problem:
104
+ - Don't fix them as part of the original solution
105
+ - After providing the solution, note "While solving this, I also noticed:"
106
+ - List the issues for future consideration
107
+
108
+ CRITICAL: MAINTAINING CONTEXT AND REQUIREMENTS:
109
+ CRITICAL: When suggesting changes:
110
+ 1. SOLVE THE STATED PROBLEM FIRST:
111
+ - Read the user's problem statement carefully
112
+ - Identify the specific issue to be fixed
113
+ - Provide the minimal change that solves exactly that issue
114
+ - Verify the solution addresses the stated problem directly
115
+ 2. Always reference the codebase provided in your context as authoritative
116
+ 3. Verify the current state of the code before suggesting changes
117
+ 4. Do not assume the state of the code based on previous interactions
118
+ 5. Ensure suggested changes are based on the actual current content of the files
119
+ 6. Never remove existing requirements or constraints while adding new ones
120
+ 7. Only after providing the solution for the stated problem:
121
+ - Reference related issues you noticed
122
+ - Suggest broader improvements
123
+ - Discuss potential architectural changes
124
+ 8. When modifying code:
125
+ - Preserve existing functionality unless explicitly asked to change it
126
+ - Maintain all existing requirements unless specifically told to remove them
127
+ - If removing code, justify why it's safe to remove
128
+ - If changing behavior, explain the impact on existing functionality
129
+
130
+ When presenting multiple diffs in a numbered list:
131
+ 1. Start each list item with the number and a period (e.g., "1. ")
132
+ 2. Add a brief description of the change
133
+ 3. Start the diff block on the next line with ```diff
134
+ 4. No indentation should be used for the diff block
135
+ 5. End the diff block with ``` on its own line
136
+ 6. Add a blank line between list items
137
+ 7. Example:
138
+ 1. First change description:
139
+ ```diff
140
+ [diff content]
141
+ ```
142
+
143
+ 2. Second change description:
144
+ ```diff
145
+ [diff content]
146
+ ```
147
+
148
+ CRITICAL: After generating each hunk diff, carefully review and verify the following:
149
+ 1. Check that the diff can be applied cleanly using `git apply`. This means:
150
+ - The context lines (unchanged lines) in the diff should match the original file content.
151
+ - The line numbers and content should be consistent throughout the diff.
152
+ - There should be no conflicts or inconsistencies in the changes.
153
+ 2. If you find any errors or inconsistencies, correct them before finalizing the diff.
154
+ 3. Review your explanation against your diff to verify:
155
+ - Every change you describe is actually present in the diff
156
+ - The diff contains no changes you haven't described
157
+ - Your description matches the actual changes in the diff exactly
158
+ - All line numbers and content in your description match the diff
159
+ 4. For each hunk in the diff, please make sure it starts or ends with a line containing content instead of empty line, if possible.
160
+ 5. When creating a new file, ensure the line `new file mode 100644` is included to specify file permissions.
161
+ 6. When deleting a file, include `deleted file mode` to indicate that the file has been removed. Each line in the
162
+ deleted file should be prefixed with `-` to indicate the content removal.
163
+ 7. Lines ending with a newline (\n) should not be interpreted as an additional line. Treat \n as the end of the current
164
+ line’s content, not as a new line in the file.
165
+
166
+ Do not include any explanatory text within the diff blocks. If you need to provide explanations or comments, do so outside the diff blocks.
167
+
168
+ The codebase is provided at the end of this prompt in a specific format.
169
+ 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.
170
+ Each file starts with "File: <filepath>" followed by its content on subsequent lines.
171
+
172
+ File: <filepath>
173
+ <Content of the file>.
174
+
175
+ Below is the current codebase of the user:
176
+
177
+ ---------------------------------------
178
+
179
+ {codebase}
180
+
181
+ ---------------------------------------
182
+ Codebase ends here.
183
+
184
+ Remember to strictly adhere to the Git diff format guidelines provided above when suggesting code changes.
185
+
186
+ """
187
+
188
+ conversational_prompt = ChatPromptTemplate.from_messages(
189
+ [
190
+ ("system", template),
191
+ # ("system", "You are a helpful AI bot. Your name is {name}."),
192
+ MessagesPlaceholder(variable_name="chat_history"),
193
+ ("user", "{question}"),
194
+ ("ai", "{agent_scratchpad}"),
195
+ ]
196
+ )
@@ -1,15 +1,20 @@
1
1
  import os
2
- from typing import Dict, Any, List, Tuple
2
+ import time
3
+ from typing import Dict, Any, List, Tuple, Optional
3
4
 
4
5
  import tiktoken
5
6
  from fastapi import FastAPI, Request, HTTPException
6
7
  from fastapi.middleware.cors import CORSMiddleware
8
+ from fastapi.responses import JSONResponse
7
9
  from fastapi.staticfiles import StaticFiles
8
10
  from fastapi.templating import Jinja2Templates
9
11
  from langserve import add_routes
12
+ from app.agents.agent import model
10
13
  from app.agents.agent import agent_executor
11
14
  from fastapi.responses import FileResponse
12
15
  from pydantic import BaseModel
16
+ from botocore.exceptions import ClientError, BotoCoreError, CredentialRetrievalError
17
+
13
18
 
14
19
  # import pydevd_pycharm
15
20
  import uvicorn
@@ -29,6 +34,39 @@ app.add_middleware(
29
34
  allow_headers=["*"],
30
35
  )
31
36
 
37
+ @app.exception_handler(CredentialRetrievalError)
38
+ async def credential_exception_handler(request: Request, exc: CredentialRetrievalError):
39
+ # Pass through the original error message which may contain helpful authentication instructions
40
+ error_message = str(exc)
41
+ return JSONResponse(
42
+ status_code=401,
43
+ content={"detail": f"AWS credential error: {error_message}"}
44
+ )
45
+
46
+
47
+ @app.exception_handler(ClientError)
48
+ async def boto_client_exception_handler(request: Request, exc: ClientError):
49
+ error_message = str(exc)
50
+ if "ExpiredTokenException" in error_message or "InvalidIdentityTokenException" in error_message:
51
+ return JSONResponse(
52
+ status_code=401,
53
+ content={"detail": "AWS credentials have expired. Please refresh your credentials."}
54
+ )
55
+ elif "ServiceUnavailableException" in error_message:
56
+ return JSONResponse(
57
+ status_code=503,
58
+ content={"detail": "AWS Bedrock service is temporarily unavailable. This usually happens when the service is experiencing high load. Please wait a moment and try again."}
59
+ )
60
+ return JSONResponse(
61
+ status_code=500,
62
+ content={"detail": f"AWS Service Error: {str(exc)}"}
63
+ )
64
+
65
+ @app.exception_handler(Exception)
66
+ async def general_exception_handler(request: Request, exc: Exception):
67
+ logger.error(f"Unhandled exception: {str(exc)}", exc_info=True)
68
+ return JSONResponse(status_code=500, content={"detail": str(exc)})
69
+
32
70
  app.mount("/static", StaticFiles(directory="../templates/static"), name="static")
33
71
  templates = Jinja2Templates(directory="../templates")
34
72
 
@@ -39,7 +77,8 @@ add_routes(app, agent_executor, disabled_endpoints=["playground"], path="/ziya")
39
77
  @app.get("/")
40
78
  async def root(request: Request):
41
79
  return templates.TemplateResponse("index.html", {
42
- "request": request
80
+ "request": request,
81
+ "diff_view_type": os.environ.get("ZIYA_DIFF_VIEW_TYPE", "unified")
43
82
  })
44
83
 
45
84
 
@@ -48,17 +87,38 @@ async def favicon():
48
87
  return FileResponse('../templates/favicon.ico')
49
88
 
50
89
 
90
+ # Cache for folder structure with timestamp
91
+ _folder_cache = {'timestamp': 0, 'data': None}
92
+
51
93
  def get_folder_structure(directory: str, ignored_patterns: List[Tuple[str, str]], max_depth: int) -> Dict[str, Any]:
52
94
  should_ignore_fn = parse_gitignore_patterns(ignored_patterns)
53
95
 
54
96
  def count_tokens(file_path: str) -> int:
55
97
  try:
56
- with open(file_path, 'r') as file:
98
+ # Skip binary files by extension
99
+ binary_extensions = {
100
+ '.pyc', '.pyo', '.ico', '.png', '.jpg', '.jpeg', '.gif', '.svg',
101
+ '.core', '.bin', '.exe', '.dll', '.so', '.dylib', '.class',
102
+ '.pyd', '.woff', '.woff2', '.ttf', '.eot'
103
+ }
104
+
105
+ if any(file_path.endswith(ext) for ext in binary_extensions):
106
+ logger.debug(f"Skipping binary file by extension: {file_path}")
107
+ return 0
108
+
109
+ # Try to detect if file is binary by reading first few bytes
110
+ with open(file_path, 'rb') as file:
111
+ content_bytes = file.read(1024)
112
+ if b'\x00' in content_bytes: # Binary file detection
113
+ return 0
114
+
115
+ # If not binary, read as text
116
+ with open(file_path, 'r', encoding='utf-8') as file:
57
117
  content = file.read()
58
118
  return len(tiktoken.get_encoding("cl100k_base").encode(content))
59
- except Exception as e:
60
- print(f"Skipping file {file_path} due to error: {e}")
61
- return 0
119
+ except (UnicodeDecodeError, IOError) as e:
120
+ logger.debug(f"Skipping binary or unreadable file {file_path}: {str(e)}")
121
+ return 0 # Skip files that can't be read as text
62
122
 
63
123
  def get_structure(current_dir: str, current_depth: int):
64
124
  if current_depth > max_depth:
@@ -87,6 +147,17 @@ def get_folder_structure(directory: str, ignored_patterns: List[Tuple[str, str]]
87
147
  folder_structure = get_structure(directory, 1)
88
148
  return folder_structure
89
149
 
150
+ def get_cached_folder_structure(directory: str, ignored_patterns: List[Tuple[str, str]], max_depth: int) -> Dict[str, Any]:
151
+ current_time = time.time()
152
+ cache_age = current_time - _folder_cache['timestamp']
153
+
154
+ # Refresh cache if older than 10 seconds
155
+ if _folder_cache['data'] is None or cache_age > 10:
156
+ _folder_cache['data'] = get_folder_structure(directory, ignored_patterns, max_depth)
157
+ _folder_cache['timestamp'] = current_time
158
+ logger.info("Refreshed folder structure cache")
159
+
160
+ return _folder_cache['data']
90
161
 
91
162
  @app.get("/api/folders")
92
163
  async def get_folders():
@@ -94,18 +165,36 @@ async def get_folders():
94
165
  user_codebase_dir = os.environ["ZIYA_USER_CODEBASE_DIR"]
95
166
  max_depth = int(os.environ.get("ZIYA_MAX_DEPTH"))
96
167
  ignored_patterns: List[Tuple[str, str]] = get_ignored_patterns(user_codebase_dir)
97
- return get_folder_structure(user_codebase_dir, ignored_patterns, max_depth)
98
-
168
+ return get_cached_folder_structure(user_codebase_dir, ignored_patterns, max_depth)
99
169
 
100
170
  @app.get('/api/default-included-folders')
101
171
  def get_default_included_folders():
102
172
  return {'defaultIncludedFolders': []}
103
173
 
174
+ @app.get('/api/model-id')
175
+ def get_model_id():
176
+ # Get the model ID from the configured Bedrock client
177
+ return {'model_id': model.model_id.split(':')[0].split('/')[-1]}
104
178
 
105
179
  class ApplyChangesRequest(BaseModel):
106
180
  diff: str
107
181
  filePath: str
108
182
 
183
+ class TokenCountRequest(BaseModel):
184
+ text: str
185
+
186
+ @app.post('/api/token-count')
187
+ async def count_tokens(request: TokenCountRequest) -> Dict[str, int]:
188
+ try:
189
+ # Use the existing model instance to count tokens
190
+ token_count = model.get_num_tokens(request.text)
191
+ logger.info(f"Counted {token_count} tokens for text length {len(request.text)}")
192
+ return {"token_count": token_count}
193
+ except Exception as e:
194
+ logger.error(f"Error counting tokens: {str(e)}", exc_info=True)
195
+ # Return 0 in case of error to avoid breaking the frontend
196
+ return {"token_count": 0}
197
+
109
198
  @app.post('/api/apply-changes')
110
199
  async def apply_changes(request: ApplyChangesRequest):
111
200
  try:
@@ -1,4 +1,6 @@
1
1
  import os
2
+ from app.utils.logging_utils import logger
3
+
2
4
 
3
5
  def print_file_tree(file_paths):
4
6
  # Create a dictionary to store files and directories
@@ -23,15 +25,16 @@ def print_file_tree(file_paths):
23
25
  return
24
26
 
25
27
  printed_dirs.add(dir_path)
26
- print(f"{indent}{os.path.basename(dir_path)}")
28
+ logger.debug(f"{indent}{os.path.basename(dir_path)}")
29
+
27
30
  if file_tree[dir_path]:
28
31
  for i, file_name in enumerate(file_tree[dir_path]):
29
32
  if i == len(file_tree[dir_path]) - 1:
30
- print(f"{indent} └── {file_name}")
33
+ logger.debug(f"{indent} └── {file_name}")
31
34
  else:
32
- print(f"{indent} ├── {file_name}")
35
+ logger.debug(f"{indent} ├── {file_name}")
33
36
  else:
34
- print(f"{indent} (empty)")
37
+ logger.debug(f"{indent} (empty)")
35
38
 
36
39
  # Recursively print subdirectories
37
40
  subdirs = [subdir for subdir in sorted_dirs if subdir.startswith(dir_path + os.sep)]
@@ -40,4 +43,4 @@ def print_file_tree(file_paths):
40
43
 
41
44
  printed_dirs = set()
42
45
  for dir_path in sorted_dirs:
43
- print_dir(dir_path, "")
46
+ print_dir(dir_path, "")
@@ -0,0 +1,48 @@
1
+ # lets move sanitizers here to clean up code flow and make them reusable
2
+ def clean_backtick_sequences(text: str) -> str:
3
+ """
4
+ Cleans up problematic backtick sequences while preserving content within code blocks.
5
+ Ensures all code blocks are properly closed.
6
+
7
+ Args:
8
+ text (str): The input text containing potential backtick sequences
9
+
10
+ Returns:
11
+ str: Text with properly closed code blocks and preserved content
12
+ """
13
+ lines = text.split('\n')
14
+ cleaned_lines = []
15
+ in_code_block = False
16
+ current_block_type = None
17
+
18
+ for line in lines:
19
+ if not in_code_block:
20
+ if line.startswith('```'):
21
+ # Starting a new block
22
+ in_code_block = True
23
+ # Capture the block type (diff, python, etc.)
24
+ current_block_type = line[3:].strip() if len(line) > 3 else None
25
+ cleaned_lines.append(line)
26
+ else:
27
+ cleaned_lines.append(line)
28
+ else:
29
+ # Inside a code block - collect content until closing backticks
30
+ if line.strip() == '```':
31
+ # Only close block if it's a bare ``` without a type specifier
32
+ if len(line.strip()) == 3:
33
+ in_code_block = False
34
+ current_block_type = None
35
+ cleaned_lines.append(line)
36
+ else:
37
+ # This is a nested block marker, preserve it
38
+ cleaned_lines.append(line)
39
+ else:
40
+ # Within a code block, preserve content exactly as it appears
41
+ cleaned_lines.append(line)
42
+
43
+ # If we ended with an open code block, close it
44
+ if in_code_block:
45
+ cleaned_lines.append('```')
46
+ current_block_type = None
47
+
48
+ return '\n'.join(cleaned_lines)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "ziya"
3
- version = "0.1.45"
3
+ version = "0.1.47"
4
4
  description = ""
5
5
  authors = ["Vishnu Krishnaprasad <vishnukool@gmail.com>"]
6
6
  readme = "README.md"
@@ -1,21 +1,21 @@
1
1
  {
2
2
  "files": {
3
- "main.css": "/static/css/main.8af23da0.css",
4
- "main.js": "/static/js/main.50c95184.js",
5
- "static/media/fa-solid-900.ttf": "/static/media/fa-solid-900.bacd5de623fb563b961a.ttf",
6
- "static/media/fa-brands-400.ttf": "/static/media/fa-brands-400.60127e352b7a11f7f1bc.ttf",
7
- "static/media/fa-solid-900.woff2": "/static/media/fa-solid-900.4d986b00ff9ca3828fbd.woff2",
8
- "static/media/fa-brands-400.woff2": "/static/media/fa-brands-400.455ea818179b4def0c43.woff2",
9
- "static/media/fa-regular-400.ttf": "/static/media/fa-regular-400.eb91f7b948a42799f678.ttf",
10
- "static/media/fa-regular-400.woff2": "/static/media/fa-regular-400.21cb8f55d8e0c5b89751.woff2",
11
- "static/media/fa-v4compatibility.ttf": "/static/media/fa-v4compatibility.c8e090db312b0bea2aa2.ttf",
12
- "static/media/fa-v4compatibility.woff2": "/static/media/fa-v4compatibility.cf7f5903d06b79ad60f1.woff2",
3
+ "main.css": "/static/css/main.f447c982.css",
4
+ "main.js": "/static/js/main.59d11a1d.js",
5
+ "static/media/fa-solid-900.ttf": "/static/media/fa-solid-900.2582b0e4bcf85eceead0.ttf",
6
+ "static/media/fa-brands-400.ttf": "/static/media/fa-brands-400.1815e00441357e01619e.ttf",
7
+ "static/media/fa-solid-900.woff2": "/static/media/fa-solid-900.2463b90d9a316e4e5294.woff2",
8
+ "static/media/fa-brands-400.woff2": "/static/media/fa-brands-400.c210719e60948b211a12.woff2",
9
+ "static/media/fa-regular-400.ttf": "/static/media/fa-regular-400.914997e1bdfc990d0897.ttf",
10
+ "static/media/fa-regular-400.woff2": "/static/media/fa-regular-400.89999bdf5d835c012025.woff2",
11
+ "static/media/fa-v4compatibility.ttf": "/static/media/fa-v4compatibility.da94ef451f4969af06e6.ttf",
12
+ "static/media/fa-v4compatibility.woff2": "/static/media/fa-v4compatibility.ea8f94e1d22e0d35ccd4.woff2",
13
13
  "index.html": "/index.html",
14
- "main.8af23da0.css.map": "/static/css/main.8af23da0.css.map",
15
- "main.50c95184.js.map": "/static/js/main.50c95184.js.map"
14
+ "main.f447c982.css.map": "/static/css/main.f447c982.css.map",
15
+ "main.59d11a1d.js.map": "/static/js/main.59d11a1d.js.map"
16
16
  },
17
17
  "entrypoints": [
18
- "static/css/main.8af23da0.css",
19
- "static/js/main.50c95184.js"
18
+ "static/css/main.f447c982.css",
19
+ "static/js/main.59d11a1d.js"
20
20
  ]
21
21
  }
@@ -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="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>
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",window.diffDisplayMode="pretty",window.diffViewType="unified"</script><script defer="defer" src="/static/js/main.59d11a1d.js"></script><link href="/static/css/main.f447c982.css" rel="stylesheet"></head><body><div id="root"></div></body></html>