mrmd-ai 0.1.0__py3-none-any.whl → 0.1.2__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.
- mrmd_ai/custom_programs.py +215 -0
- mrmd_ai/juice.py +403 -61
- mrmd_ai/modules/__init__.py +11 -0
- mrmd_ai/modules/edit.py +102 -0
- mrmd_ai/server.py +275 -23
- mrmd_ai/signatures/__init__.py +15 -0
- mrmd_ai/signatures/edit.py +173 -0
- {mrmd_ai-0.1.0.dist-info → mrmd_ai-0.1.2.dist-info}/METADATA +2 -1
- {mrmd_ai-0.1.0.dist-info → mrmd_ai-0.1.2.dist-info}/RECORD +12 -8
- mrmd_ai-0.1.2.dist-info/licenses/LICENSE +21 -0
- {mrmd_ai-0.1.0.dist-info → mrmd_ai-0.1.2.dist-info}/WHEEL +0 -0
- {mrmd_ai-0.1.0.dist-info → mrmd_ai-0.1.2.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"""Signature definitions for cursor-based editing and comment processing."""
|
|
2
|
+
|
|
3
|
+
import dspy
|
|
4
|
+
from pydantic import BaseModel, Field
|
|
5
|
+
from typing import List, Optional
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Edit(BaseModel):
|
|
9
|
+
"""A single find/replace edit operation.
|
|
10
|
+
|
|
11
|
+
For insertions at cursor, use find="" and the text will be inserted
|
|
12
|
+
at the cursor position.
|
|
13
|
+
"""
|
|
14
|
+
find: str = Field(
|
|
15
|
+
description="Exact text to find in document. Use empty string for insertion at cursor."
|
|
16
|
+
)
|
|
17
|
+
replace: str = Field(
|
|
18
|
+
description="Text to replace the found text with, or text to insert if find is empty."
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class CommentInfo(BaseModel):
|
|
23
|
+
"""Information about a comment in the document."""
|
|
24
|
+
text: str = Field(description="The comment text content")
|
|
25
|
+
context_before: str = Field(description="Text immediately before the comment")
|
|
26
|
+
context_after: str = Field(description="Text immediately after the comment")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class EditAtCursorSignature(dspy.Signature):
|
|
30
|
+
"""
|
|
31
|
+
Execute a user instruction by generating precise find/replace edits.
|
|
32
|
+
|
|
33
|
+
You are given the cursor context and a natural language instruction.
|
|
34
|
+
Generate a list of edits that implement the instruction.
|
|
35
|
+
|
|
36
|
+
CRITICAL RULES:
|
|
37
|
+
1. Each edit has `find` (exact text to locate) and `replace` (replacement text)
|
|
38
|
+
2. For INSERTIONS at cursor: use find="" - the replace text will be inserted at cursor
|
|
39
|
+
3. For MODIFICATIONS: find must match the EXACT text in the document (character-for-character)
|
|
40
|
+
4. find strings must be UNIQUE enough to match only the intended location
|
|
41
|
+
5. Include surrounding context in find to ensure uniqueness (e.g., "def process_data(items)" not just "process_data")
|
|
42
|
+
6. Edits are applied in order - earlier edits may shift positions of later ones
|
|
43
|
+
|
|
44
|
+
Examples:
|
|
45
|
+
- Instruction: "add a docstring" → find the function definition, replace with definition + docstring
|
|
46
|
+
- Instruction: "rename x to count" → find=" x " (with spaces), replace=" count "
|
|
47
|
+
- Instruction: "insert a comment here" → find="", replace="# comment\\n"
|
|
48
|
+
- Instruction: "delete this line" → find="the line content\\n", replace=""
|
|
49
|
+
|
|
50
|
+
When the user has selected text, that text is provided in `selection`.
|
|
51
|
+
Prefer to operate on the selection when it's relevant to the instruction.
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
text_before: str = dspy.InputField(
|
|
55
|
+
desc="Text immediately before the cursor (up to 500 characters for context)"
|
|
56
|
+
)
|
|
57
|
+
text_after: str = dspy.InputField(
|
|
58
|
+
desc="Text immediately after the cursor (up to 500 characters for context)"
|
|
59
|
+
)
|
|
60
|
+
selection: str = dspy.InputField(
|
|
61
|
+
desc="Currently selected text, or empty string if no selection"
|
|
62
|
+
)
|
|
63
|
+
full_document: str = dspy.InputField(
|
|
64
|
+
desc="The complete document content for full context"
|
|
65
|
+
)
|
|
66
|
+
instruction: str = dspy.InputField(
|
|
67
|
+
desc="User's natural language instruction for what to do"
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
edits: List[Edit] = dspy.OutputField(
|
|
71
|
+
desc="List of find/replace edits to apply. Order matters - applied sequentially."
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class AddressCommentSignature(dspy.Signature):
|
|
76
|
+
"""
|
|
77
|
+
Address a single comment/instruction embedded in the document.
|
|
78
|
+
|
|
79
|
+
Comments are marked with <!--! comment text !--> syntax.
|
|
80
|
+
The comment contains instructions or notes that should be addressed.
|
|
81
|
+
Generate edits that fulfill the comment's request.
|
|
82
|
+
|
|
83
|
+
After addressing, you may optionally remove the comment marker itself.
|
|
84
|
+
|
|
85
|
+
Guidelines:
|
|
86
|
+
- Read the comment carefully to understand what's requested
|
|
87
|
+
- Look at the surrounding context to understand where changes should go
|
|
88
|
+
- Generate precise edits that address the comment
|
|
89
|
+
- If the comment asks for something that's already done, return empty edits
|
|
90
|
+
- Consider removing the comment after addressing it (include that as an edit)
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
full_document: str = dspy.InputField(
|
|
94
|
+
desc="The complete document content"
|
|
95
|
+
)
|
|
96
|
+
comment_text: str = dspy.InputField(
|
|
97
|
+
desc="The text content of the comment (without the <!--! !--> markers)"
|
|
98
|
+
)
|
|
99
|
+
comment_context_before: str = dspy.InputField(
|
|
100
|
+
desc="Text immediately before the comment marker"
|
|
101
|
+
)
|
|
102
|
+
comment_context_after: str = dspy.InputField(
|
|
103
|
+
desc="Text immediately after the comment marker"
|
|
104
|
+
)
|
|
105
|
+
comment_raw: str = dspy.InputField(
|
|
106
|
+
desc="The full raw comment including markers (e.g., '<!--! add error handling !-->')"
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
edits: List[Edit] = dspy.OutputField(
|
|
110
|
+
desc="List of find/replace edits to address the comment"
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
class AddressAllCommentsSignature(dspy.Signature):
|
|
115
|
+
"""
|
|
116
|
+
Address ALL comments/instructions in a document.
|
|
117
|
+
|
|
118
|
+
Scan the document for all <!--! ... !--> comment markers and generate
|
|
119
|
+
edits that address each one.
|
|
120
|
+
|
|
121
|
+
Guidelines:
|
|
122
|
+
- Process comments in document order (top to bottom)
|
|
123
|
+
- Each comment should be addressed appropriately
|
|
124
|
+
- Comments that conflict should be resolved sensibly
|
|
125
|
+
- After addressing, remove the comment markers
|
|
126
|
+
- Return all edits as a single list (they'll be applied in order)
|
|
127
|
+
"""
|
|
128
|
+
|
|
129
|
+
full_document: str = dspy.InputField(
|
|
130
|
+
desc="The complete document content with embedded comments"
|
|
131
|
+
)
|
|
132
|
+
comments: List[CommentInfo] = dspy.InputField(
|
|
133
|
+
desc="List of all comments found in the document with their context"
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
edits: List[Edit] = dspy.OutputField(
|
|
137
|
+
desc="List of all find/replace edits to address all comments"
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
class AddressNearbyCommentSignature(dspy.Signature):
|
|
142
|
+
"""
|
|
143
|
+
Address the comment nearest to the cursor position.
|
|
144
|
+
|
|
145
|
+
Find the comment that's closest to where the user's cursor is and
|
|
146
|
+
generate edits to address that specific comment.
|
|
147
|
+
|
|
148
|
+
Guidelines:
|
|
149
|
+
- Focus only on the comment nearest to the cursor
|
|
150
|
+
- Use the cursor context to identify which comment is relevant
|
|
151
|
+
- Generate edits that address that comment
|
|
152
|
+
- Optionally remove the comment marker after addressing
|
|
153
|
+
"""
|
|
154
|
+
|
|
155
|
+
full_document: str = dspy.InputField(
|
|
156
|
+
desc="The complete document content"
|
|
157
|
+
)
|
|
158
|
+
cursor_context_before: str = dspy.InputField(
|
|
159
|
+
desc="Text before the cursor position"
|
|
160
|
+
)
|
|
161
|
+
cursor_context_after: str = dspy.InputField(
|
|
162
|
+
desc="Text after the cursor position"
|
|
163
|
+
)
|
|
164
|
+
nearby_comment: CommentInfo = dspy.InputField(
|
|
165
|
+
desc="The comment closest to the cursor"
|
|
166
|
+
)
|
|
167
|
+
nearby_comment_raw: str = dspy.InputField(
|
|
168
|
+
desc="The full raw comment including markers"
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
edits: List[Edit] = dspy.OutputField(
|
|
172
|
+
desc="List of find/replace edits to address the nearby comment"
|
|
173
|
+
)
|
|
@@ -1,26 +1,30 @@
|
|
|
1
1
|
mrmd_ai/__init__.py,sha256=RocuoOEEJCUNinxqsXWjm_bIimCu8aDCDha-G5pU4fU,105
|
|
2
|
-
mrmd_ai/
|
|
3
|
-
mrmd_ai/
|
|
2
|
+
mrmd_ai/custom_programs.py,sha256=owdMbWzHNDAoF2LbOpWZnri9xnFIq2BocFtiQLtoDXU,6826
|
|
3
|
+
mrmd_ai/juice.py,sha256=SJjJailZ3o84RbG8XvBIyKAh0ZqDcbKmbekCj6UJa4Q,28544
|
|
4
|
+
mrmd_ai/server.py,sha256=RPZhnp9Gl3tt5x8q2MjlzVrjSvuE-r8yA536JIPQbm8,23515
|
|
4
5
|
mrmd_ai/metrics/__init__.py,sha256=6BngKqh0a09phOzUdYeWjhsUXznCIx5jEjrEt7DIDu4,62
|
|
5
|
-
mrmd_ai/modules/__init__.py,sha256=
|
|
6
|
+
mrmd_ai/modules/__init__.py,sha256=OO-5alsFmR1bLtsvxAJ2wNO5nOtHRmWChTexEI6Y9xU,2097
|
|
6
7
|
mrmd_ai/modules/code.py,sha256=8cK6LF0ZTrSp2srt1ltvUnmYjPlt5NZTj1yWctpJ7j0,4099
|
|
7
8
|
mrmd_ai/modules/correct.py,sha256=TWnE1HD_Ip7xZ5yQwJi1n01tNXgBtYNvkTK--kAknak,1478
|
|
8
9
|
mrmd_ai/modules/document.py,sha256=o6iLR2amscn-DHZ95JFQuEwhaj8cLs4bBISf7G9cT9Y,1106
|
|
10
|
+
mrmd_ai/modules/edit.py,sha256=lGa0tNB7d9tRG4rtdQ6uNIi3lzSbC588c3r86ccPXZc,2736
|
|
9
11
|
mrmd_ai/modules/finish.py,sha256=VtyE-45-8iM6iWjNg57wRWL0Ln3mSF0RcZq8CO5CoSk,2638
|
|
10
12
|
mrmd_ai/modules/fix.py,sha256=fb4flKWyyyelheigeb1sI0dixd2scL9HZX-0_M_Uh-o,1506
|
|
11
13
|
mrmd_ai/modules/notebook.py,sha256=w8Dg-NKVL6_kPOKkvb84kGrwgv5zHxvFNWBtXHLHww8,477
|
|
12
14
|
mrmd_ai/modules/text.py,sha256=9MCO__EDalwi-iFf__sd8t7orsUy7WiBBf6Lp4bxxGE,2010
|
|
13
15
|
mrmd_ai/optimizers/__init__.py,sha256=Ay6ZrQu8fLQaG7-dl6hTMruQY5AdGOT_YnlRhhZGgag,60
|
|
14
|
-
mrmd_ai/signatures/__init__.py,sha256=
|
|
16
|
+
mrmd_ai/signatures/__init__.py,sha256=UoIplXOXxPidkaXi9u-7l2LziDJX2MN4PmwtXVsC04U,1013
|
|
15
17
|
mrmd_ai/signatures/code.py,sha256=zBM_Nl2NImfOw49fVWCGlXcE_sm8xgWCN1ksDbEa6e8,11245
|
|
16
18
|
mrmd_ai/signatures/correct.py,sha256=tIhYCONgGhuTV0eJCiLSXcGZSAEi06XY35ommtTTsRE,2920
|
|
17
19
|
mrmd_ai/signatures/document.py,sha256=4Y-9SeXJGCq098Vy-PIbb_rexS2dYDlkU-kxnKAPVSU,1828
|
|
20
|
+
mrmd_ai/signatures/edit.py,sha256=OBAYsh88Qg_EIoEJHHa28QRuSh2xbGM3OSGWtPJ8u_A,6524
|
|
18
21
|
mrmd_ai/signatures/finish.py,sha256=x-ZB0U8GQJdNoGGO80FBOxHXjYsCmTFq9fnkXlHDeUY,5294
|
|
19
22
|
mrmd_ai/signatures/fix.py,sha256=LJNvu9_XjPl90Wtt3xn6s-jGXA9GB5rdIL0MeFyRGtE,3042
|
|
20
23
|
mrmd_ai/signatures/notebook.py,sha256=ZBioHA9ZTkLUD_UovdfiRYiDaUKuKOCDhiZP1NDFY8o,1226
|
|
21
24
|
mrmd_ai/signatures/text.py,sha256=GhmFtEZqwivbevPI_NSBzh6AlH6JKLt2rA_LaYGK2lQ,5223
|
|
22
25
|
mrmd_ai/utils/__init__.py,sha256=T4e9jmFWDSj1HOyz5_Qv-JQSC08GwT_9CACcAn37vWg,46
|
|
23
|
-
mrmd_ai-0.1.
|
|
24
|
-
mrmd_ai-0.1.
|
|
25
|
-
mrmd_ai-0.1.
|
|
26
|
-
mrmd_ai-0.1.
|
|
26
|
+
mrmd_ai-0.1.2.dist-info/METADATA,sha256=XP2KXado_UWlhsbveBajtLEdAl9Cjeq3e3XGovqK1sg,1189
|
|
27
|
+
mrmd_ai-0.1.2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
28
|
+
mrmd_ai-0.1.2.dist-info/entry_points.txt,sha256=Bq6nXiXxhNSPEgYWBgrrgJH1DeGjKM6hfCijcWClApw,55
|
|
29
|
+
mrmd_ai-0.1.2.dist-info/licenses/LICENSE,sha256=7WBExfg4gC1NdkdBtnOFRbt_bOD3gKPmEc-7hHMIcXQ,1070
|
|
30
|
+
mrmd_ai-0.1.2.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Maxime Rivest
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
File without changes
|
|
File without changes
|