kopipasta 0.38.0__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 kopipasta might be problematic. Click here for more details.

kopipasta/prompt.py ADDED
@@ -0,0 +1,174 @@
1
+ import os
2
+ from kopipasta.file import FileTuple, read_file_contents, is_ignored
3
+
4
+
5
+ from typing import Dict, List, Tuple
6
+
7
+
8
+ def get_file_snippet(file_path, max_lines=50, max_bytes=4096):
9
+ snippet = ""
10
+ byte_count = 0
11
+ with open(file_path, "r") as file:
12
+ for i, line in enumerate(file):
13
+ if i >= max_lines or byte_count >= max_bytes:
14
+ break
15
+ snippet += line
16
+ byte_count += len(line.encode("utf-8"))
17
+ return snippet
18
+
19
+
20
+ def get_language_for_file(file_path):
21
+ extension = os.path.splitext(file_path)[1].lower()
22
+ language_map = {
23
+ ".py": "python",
24
+ ".js": "javascript",
25
+ ".jsx": "jsx",
26
+ ".ts": "typescript",
27
+ ".tsx": "tsx",
28
+ ".html": "html",
29
+ ".htm": "html",
30
+ ".css": "css",
31
+ ".json": "json",
32
+ ".md": "markdown",
33
+ ".sql": "sql",
34
+ ".sh": "bash",
35
+ ".yml": "yaml",
36
+ ".yaml": "yaml",
37
+ ".go": "go",
38
+ ".toml": "toml",
39
+ ".c": "c",
40
+ ".cpp": "cpp",
41
+ ".cc": "cpp",
42
+ ".h": "cpp",
43
+ ".hpp": "cpp",
44
+ }
45
+ return language_map.get(extension, "")
46
+
47
+
48
+ def get_project_structure(ignore_patterns):
49
+ tree = []
50
+ for root, dirs, files in os.walk("."):
51
+ dirs[:] = [
52
+ d for d in dirs if not is_ignored(os.path.join(root, d), ignore_patterns)
53
+ ]
54
+ files = [
55
+ f for f in files if not is_ignored(os.path.join(root, f), ignore_patterns)
56
+ ]
57
+ level = root.replace(".", "").count(os.sep)
58
+ indent = " " * 4 * level + "|-- "
59
+ tree.append(f"{indent}{os.path.basename(root)}/")
60
+ subindent = " " * 4 * (level + 1) + "|-- "
61
+ for f in files:
62
+ tree.append(f"{subindent}{f}")
63
+ return "\n".join(tree)
64
+
65
+
66
+ def handle_env_variables(content, env_vars):
67
+ detected_vars = []
68
+ for key, value in env_vars.items():
69
+ if value in content:
70
+ detected_vars.append((key, value))
71
+ if not detected_vars:
72
+ return content
73
+
74
+ print("Detected environment variables:")
75
+ for key, value in detected_vars:
76
+ print(f"- {key}={value}")
77
+
78
+ for key, value in detected_vars:
79
+ while True:
80
+ choice = input(
81
+ f"How would you like to handle {key}? (m)ask / (s)kip / (k)eep: "
82
+ ).lower()
83
+ if choice in ["m", "s", "k"]:
84
+ break
85
+ print("Invalid choice. Please enter 'm', 's', or 'k'.")
86
+
87
+ if choice == "m":
88
+ content = content.replace(value, "*" * len(value))
89
+ elif choice == "s":
90
+ content = content.replace(value, "[REDACTED]")
91
+ # If 'k', we don't modify the content
92
+
93
+ return content
94
+
95
+
96
+ def generate_prompt_template(
97
+ files_to_include: List[FileTuple],
98
+ ignore_patterns: List[str],
99
+ web_contents: Dict[str, Tuple[FileTuple, str]],
100
+ env_vars: Dict[str, str],
101
+ ) -> Tuple[str, int]:
102
+ prompt = "# Project Overview\n\n"
103
+ prompt += "## Project Structure\n\n"
104
+ prompt += "```\n"
105
+ prompt += get_project_structure(ignore_patterns)
106
+ prompt += "\n```\n\n"
107
+ prompt += "## File Contents\n\n"
108
+ for file, use_snippet, chunks, content_type in files_to_include:
109
+ relative_path = os.path.relpath(file)
110
+ language = content_type if content_type else get_language_for_file(file)
111
+
112
+ if chunks is not None:
113
+ prompt += f"### {relative_path} (selected patches)\n\n```{language}\n"
114
+ for chunk in chunks:
115
+ prompt += f"{chunk}\n"
116
+ prompt += "```\n\n"
117
+ elif use_snippet:
118
+ file_content = get_file_snippet(file)
119
+ prompt += f"### {relative_path} (snippet)\n\n```{language}\n{file_content}\n```\n\n"
120
+ else:
121
+ file_content = read_file_contents(file)
122
+ file_content = handle_env_variables(file_content, env_vars)
123
+ prompt += f"### {relative_path}\n\n```{language}\n{file_content}\n```\n\n"
124
+
125
+ if web_contents:
126
+ prompt += "## Web Content\n\n"
127
+ for url, (file_tuple, content) in web_contents.items():
128
+ _, is_snippet, _, content_type = file_tuple
129
+ content = handle_env_variables(content, env_vars)
130
+ language = content_type if content_type in ["json", "csv"] else ""
131
+ prompt += f"### {url}{' (snippet)' if is_snippet else ''}\n\n```{language}\n{content}\n```\n\n"
132
+
133
+ prompt += "## Task Instructions\n\n"
134
+ cursor_position = len(prompt)
135
+ prompt += "\n\n"
136
+ prompt += "## Instructions for Achieving the Task\n\n"
137
+ analysis_text = (
138
+ "### Partnership Principles\n\n"
139
+ "We work as collaborative partners. You provide technical expertise and critical thinking. "
140
+ "I have exclusive access to my codebase, real environment, external services, and actual users. "
141
+ "Never assume project file contents - always ask to see them.\n\n"
142
+ "**Critical Thinking**: Challenge poor approaches, identify risks, suggest better alternatives. Don't be a yes-man.\n\n"
143
+ "**Anti-Hallucination**: Never write placeholder code for files in ## Project Structure. Use [STOP - NEED FILE: filename] and wait.\n\n"
144
+ "**Hard Stops**: End with [AWAITING USER RESPONSE] when you need input. Don't continue with assumptions.\n\n"
145
+ "### Development Workflow\n\n"
146
+ "We work in two modes:\n"
147
+ "- **Iterative Mode**: Build incrementally, show only changes\n"
148
+ "- **Consolidation Mode**: When I request, provide clean final version\n\n"
149
+ "1. **Understand & Analyze**:\n"
150
+ " - Rephrase task, identify issues, list needed files\n"
151
+ " - Challenge problematic aspects\n"
152
+ " - End: 'I need: [files]. Is this correct?' [AWAITING USER RESPONSE]\n\n"
153
+ "2. **Plan**:\n"
154
+ " - Present 2-3 approaches with pros/cons\n"
155
+ " - Recommend best approach\n"
156
+ " - End: 'Which approach?' [AWAITING USER RESPONSE]\n\n"
157
+ "3. **Implement Iteratively**:\n"
158
+ " - Small, testable increments\n"
159
+ " - Track failed attempts: `Attempt 1: [FAILED] X→Y (learned: Z)`\n"
160
+ " - After 3 failures, request diagnostics\n\n"
161
+ "4. **Code Presentation**:\n"
162
+ " - Always: `// FILE: path/to/file.ext`\n"
163
+ " - Iterative: Show only changes with context\n"
164
+ " - Consolidation: Smart choice - minimal changes = show patches, extensive = full file\n\n"
165
+ "5. **Test & Validate**:\n"
166
+ " - 'Test with: [command]. Share any errors.' [AWAITING USER RESPONSE]\n"
167
+ " - Include debug outputs\n"
168
+ " - May return to implementation based on results\n\n"
169
+ "### Permissions & Restrictions\n\n"
170
+ "**You MAY**: Request project files, ask me to test code/services, challenge my approach, refuse without info\n\n"
171
+ "**You MUST NOT**: Assume project file contents, continue past [AWAITING USER RESPONSE], be agreeable when you see problems\n"
172
+ )
173
+ prompt += analysis_text
174
+ return prompt, cursor_position