fix(edit): warned on hashline separator padding
Tightened the hashline prompt to forbid readability spaces after the payload separator. Preserved parsed payload text verbatim and surfaced a warning when a payload block looks like separator padding was added across every line. Fixes #1166
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
## [Unreleased]
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed hashline edit payloads that use a readability space after `~` by warning on separator-padding-shaped payload blocks and tightening the model prompt. ([#1166](https://github.com/can1357/oh-my-pi/issues/1166))
|
||||
- Fixed ACP command and custom tool-call notifications to carry the original tool arguments in replayed and final updates, so command text is preserved and raw input is no longer wrapped
|
||||
- Fixed ACP async-job draining to be scoped by session owner so `getAsyncJobSnapshot` and `drainAsyncJobDeliveriesForAcp` no longer consume or expose jobs from other sessions
|
||||
- Fixed async job status reporting to include in-flight completions so queued/delivering indicators remain accurate while callbacks are still running
|
||||
|
||||
@@ -74,19 +74,29 @@ export function cloneCursor(cursor: HashlineCursor): HashlineCursor {
|
||||
if (cursor.kind === "after_anchor") return { kind: "after_anchor", anchor: { ...cursor.anchor } };
|
||||
return cursor;
|
||||
}
|
||||
/** Returns true when every non-empty payload line starts with `${sep} ` (sep + one space). */
|
||||
function hasUniformSeparatorPadding(payload: string[]): boolean {
|
||||
let any = false;
|
||||
for (const text of payload) {
|
||||
if (text.length === 0) continue;
|
||||
if (!text.startsWith(" ")) return false;
|
||||
any = true;
|
||||
}
|
||||
return any;
|
||||
}
|
||||
|
||||
function collectPayload(
|
||||
lines: string[],
|
||||
startIndex: number,
|
||||
opLineNum: number,
|
||||
requirePayload: boolean,
|
||||
): { payload: string[]; nextIndex: number } {
|
||||
): { payload: string[]; nextIndex: number; paddingWarning?: string } {
|
||||
const payload: string[] = [];
|
||||
let index = startIndex;
|
||||
while (index < lines.length) {
|
||||
const line = lines[index];
|
||||
if (line.startsWith(HL_EDIT_SEP)) {
|
||||
payload.push(line.slice(1).trimEnd());
|
||||
payload.push(line.slice(HL_EDIT_SEP.length).trimEnd());
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
@@ -115,7 +125,11 @@ function collectPayload(
|
||||
if (payload.length === 0 && requirePayload) {
|
||||
throw new Error(`line ${opLineNum}: + and < operations require at least one ${HL_EDIT_SEP}TEXT payload line.`);
|
||||
}
|
||||
return { payload, nextIndex: index };
|
||||
const paddingWarning = hasUniformSeparatorPadding(payload)
|
||||
? `line ${opLineNum}: all payload lines start with "${HL_EDIT_SEP} " (separator + space). ` +
|
||||
`The space becomes file content. Remove it unless the target file requires leading spaces.`
|
||||
: undefined;
|
||||
return { payload, nextIndex: index, paddingWarning };
|
||||
}
|
||||
|
||||
export function parseHashline(diff: string): HashlineEdit[] {
|
||||
@@ -158,7 +172,8 @@ export function parseHashlineWithWarnings(diff: string): { edits: HashlineEdit[]
|
||||
const insertBeforeMatch = INSERT_BEFORE_OP_RE.exec(line);
|
||||
if (insertBeforeMatch) {
|
||||
const cursor = parseInsertTarget(insertBeforeMatch[1], lineNum, "before");
|
||||
const { payload, nextIndex } = collectPayload(lines, i + 1, lineNum, true);
|
||||
const { payload, nextIndex, paddingWarning } = collectPayload(lines, i + 1, lineNum, true);
|
||||
if (paddingWarning) warnings.push(paddingWarning);
|
||||
for (const text of payload) pushInsert(cursor, text, lineNum);
|
||||
i = nextIndex;
|
||||
continue;
|
||||
@@ -167,7 +182,8 @@ export function parseHashlineWithWarnings(diff: string): { edits: HashlineEdit[]
|
||||
const insertAfterMatch = INSERT_AFTER_OP_RE.exec(line);
|
||||
if (insertAfterMatch) {
|
||||
const cursor = parseInsertTarget(insertAfterMatch[1], lineNum, "after");
|
||||
const { payload, nextIndex } = collectPayload(lines, i + 1, lineNum, true);
|
||||
const { payload, nextIndex, paddingWarning } = collectPayload(lines, i + 1, lineNum, true);
|
||||
if (paddingWarning) warnings.push(paddingWarning);
|
||||
for (const text of payload) pushInsert(cursor, text, lineNum);
|
||||
i = nextIndex;
|
||||
continue;
|
||||
@@ -185,7 +201,8 @@ export function parseHashlineWithWarnings(diff: string): { edits: HashlineEdit[]
|
||||
const replaceMatch = REPLACE_OP_RE.exec(line);
|
||||
if (replaceMatch) {
|
||||
const range = parseRange(replaceMatch[1], lineNum);
|
||||
const { payload, nextIndex } = collectPayload(lines, i + 1, lineNum, false);
|
||||
const { payload, nextIndex, paddingWarning } = collectPayload(lines, i + 1, lineNum, false);
|
||||
if (paddingWarning) warnings.push(paddingWarning);
|
||||
// `= A..B` with no payload blanks the range to a single empty line.
|
||||
const replacement = payload.length === 0 ? [""] : payload;
|
||||
for (const text of replacement) {
|
||||
|
||||
@@ -19,8 +19,9 @@ Each op line is ONE of:
|
||||
Op lines carry no content — payload goes on the next line.
|
||||
|
||||
WRONG: + 5pg| some code
|
||||
WRONG: {{hsep}} some code
|
||||
RIGHT: + 5pg
|
||||
{{hsep}} some code
|
||||
{{hsep}}some code
|
||||
|
||||
A single `+`/`<`/`=` op accepts MANY `{{hsep}}` payload lines. To insert N consecutive lines, write ONE op followed by N payload lines — NEVER N ops with one payload each.
|
||||
|
||||
@@ -37,8 +38,9 @@ RIGHT (one op, many payload lines):
|
||||
</format-reminder>
|
||||
|
||||
<rules>
|
||||
- Every payload line MUST start with `{{hsep}}`.
|
||||
- Payload is verbatim — NEVER escape unicode.
|
||||
- Every payload line MUST start with `{{hsep}}` immediately followed by payload text. Do NOT add a readability space after `{{hsep}}`.
|
||||
- Every character after `{{hsep}}` is file content. If the target line intentionally starts with one space, write exactly one space after `{{hsep}}`; otherwise write none.
|
||||
- Payload text is verbatim — NEVER escape unicode.
|
||||
- **Payload is only what's NEW relative to your range:**
|
||||
- `=` replaces inside; NEVER include lines outside.
|
||||
- `+`/`<` adds at the anchor; NEVER repeat line A or neighbors.
|
||||
|
||||
Reference in New Issue
Block a user