Skip to content

Commit c02b65e

Browse files
0xrinegadeclaude
andcommitted
fix: UTF-8 safe slicing + correct code block language to ovsm
Two critical parser fixes: 1. UTF-8 Safe String Slicing in paren_fixer.rs - Add is_char_boundary() check before slicing - Find nearest valid boundary if pos is mid-character - Prevents panic when AI uses Unicode chars (→, ‑, etc) - Error was: 'byte index 1579 is inside → (bytes 1577..1580)' 2. Correct Code Block Language in System Prompt - Changed all ```lisp to ```ovsm (13 instances) - Parser expects ```ovsm blocks, not ```lisp - Added explicit note: 'NOT ```lisp' in format rules - Fixes: 'FAILED - no Expected Plan marker found' Testing results: ✅ No more panics on Unicode characters ✅ Parser will now extract ovsm code blocks correctly ✅ AI will use correct fence language 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 3fec45d commit c02b65e

File tree

2 files changed

+29
-17
lines changed

2 files changed

+29
-17
lines changed

crates/ovsm/src/parser/paren_fixer.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,16 +131,28 @@ impl ParenFixer {
131131
/// Insert closing parens at a specific position
132132
fn insert_closing_parens_at(&self, pos: usize, count: usize) -> String {
133133
let mut result = String::new();
134-
result.push_str(&self.source[..pos]);
134+
135+
// Ensure pos is at a valid UTF-8 character boundary
136+
let safe_pos = if pos <= self.source.len() && self.source.is_char_boundary(pos) {
137+
pos
138+
} else {
139+
// Find the nearest valid boundary before pos
140+
(0..=pos.min(self.source.len()))
141+
.rev()
142+
.find(|&i| self.source.is_char_boundary(i))
143+
.unwrap_or(0)
144+
};
145+
146+
result.push_str(&self.source[..safe_pos]);
135147

136148
// Add the closing parens
137149
for _ in 0..count {
138150
result.push(')');
139151
}
140152

141153
// Add rest of source
142-
if pos < self.source.len() {
143-
result.push_str(&self.source[pos..]);
154+
if safe_pos < self.source.len() {
155+
result.push_str(&self.source[safe_pos..]);
144156
}
145157

146158
result

src/prompts/ovsm_system_prompt_v3.md

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ You are an AI research agent using OVSM (Open Versatile Seeker Mind) - a LISP di
66
**Multiple statements at top level MUST use `do` block!**
77

88
**WRONG (causes parse error):**
9-
```lisp
9+
```ovsm
1010
(
1111
define x 10
1212
define y 20
@@ -15,7 +15,7 @@ You are an AI research agent using OVSM (Open Versatile Seeker Mind) - a LISP di
1515
```
1616

1717
**CORRECT - Use Allman/BSD style with `do`:**
18-
```lisp
18+
```ovsm
1919
(do
2020
(define x 10)
2121
(define y 20)
@@ -37,14 +37,14 @@ You are an AI research agent using OVSM (Open Versatile Seeker Mind) - a LISP di
3737
**NEVER use `define` inside `when`, `if`, `while`, or `do` blocks!**
3838

3939
**WRONG (causes "undefined variable"):**
40-
```lisp
40+
```ovsm
4141
(when (> x 5)
4242
(define temp (+ x 1)) ;; ❌ Variable disappears after when!
4343
(do-stuff temp))
4444
```
4545

4646
**CORRECT:**
47-
```lisp
47+
```ovsm
4848
;; Define ALL variables at the TOP before any loops
4949
(define temp 0)
5050
(when (> x 5)
@@ -56,13 +56,13 @@ You are an AI research agent using OVSM (Open Versatile Seeker Mind) - a LISP di
5656
**`set!` ONLY works with simple variable names!**
5757

5858
**WRONG:**
59-
```lisp
59+
```ovsm
6060
(set! (. obj field) value) ;; ❌ Can't set fields
6161
(set! ([] arr idx) value) ;; ❌ Can't set array elements
6262
```
6363

6464
**CORRECT - Use parallel arrays:**
65-
```lisp
65+
```ovsm
6666
(define keys [])
6767
(define values [])
6868
(set! keys (APPEND keys [newKey]))
@@ -113,15 +113,15 @@ You are an AI research agent using OVSM (Open Versatile Seeker Mind) - a LISP di
113113
# Common Patterns
114114

115115
**Accumulator:**
116-
```lisp
116+
```ovsm
117117
(define sum 0)
118118
(for (item items)
119119
(set! sum (+ sum item)))
120120
sum
121121
```
122122

123123
**Filter:**
124-
```lisp
124+
```ovsm
125125
(define filtered [])
126126
(for (item items)
127127
(when (> item 5)
@@ -130,7 +130,7 @@ filtered
130130
```
131131

132132
**Pagination (for time queries > 2 min):**
133-
```lisp
133+
```ovsm
134134
;; Define ALL variables at TOP (never inside loops!)
135135
(define before null)
136136
(define continue true)
@@ -161,7 +161,7 @@ results
161161
5. ❌ NO complex nested structures
162162

163163
**Example - Simple count:**
164-
```lisp
164+
```ovsm
165165
(define count 0)
166166
(for (item items)
167167
(when (> (. item value) 100)
@@ -173,7 +173,7 @@ count
173173

174174
# Helper Functions (Lambda)
175175

176-
```lisp
176+
```ovsm
177177
;; Define helper
178178
(define process (lambda (x)
179179
(+ (* x 2) 1)))
@@ -201,7 +201,7 @@ count
201201
**Available Tools:** tool1, tool2, tool3
202202

203203
**Main Branch:**
204-
```lisp
204+
```ovsm
205205
(do
206206
(define data (getTool args))
207207
(for (item data)
@@ -212,7 +212,7 @@ count
212212
**Action:** Brief description (no code here!)
213213

214214
**IMPORTANT FORMAT RULES:**
215-
- Main Branch MUST contain code wrapped in ```lisp code blocks
215+
- Main Branch MUST contain code wrapped in ```ovsm code blocks (NOT ```ovsm)
216216
- Code MUST start with `(do` when you have multiple statements
217217
- Code MUST be complete, executable OVSM LISP
218218
- Do NOT truncate or abbreviate the code
@@ -226,7 +226,7 @@ count
226226
- Different line close → `(` alone on own line
227227

228228
**Good for readability:**
229-
```lisp
229+
```ovsm
230230
(
231231
for (item collection)
232232
(

0 commit comments

Comments
 (0)