prior-cli 1.2.4 → 1.2.6
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.
- package/bin/prior.js +3 -5
- package/lib/agent.js +29 -3
- package/package.json +1 -1
package/bin/prior.js
CHANGED
|
@@ -670,14 +670,12 @@ async function startChat(opts = {}) {
|
|
|
670
670
|
clearSuggestions();
|
|
671
671
|
if (!matches.length) return;
|
|
672
672
|
_suggCount = matches.length;
|
|
673
|
-
process.stdout.write('\x1b[s');
|
|
674
|
-
// Print newlines to scroll terminal and guarantee room below the prompt
|
|
675
|
-
process.stdout.write('\n'.repeat(matches.length));
|
|
676
|
-
process.stdout.write(`\x1b[${matches.length}A`); // move cursor back up to prompt line
|
|
673
|
+
process.stdout.write('\x1b[s'); // save cursor at end of typed input
|
|
677
674
|
for (const { cmd, desc } of matches) {
|
|
675
|
+
// \x1b[B = cursor down 1 (no scroll), \r = col 0, \x1b[2K = clear line
|
|
678
676
|
process.stdout.write(`\x1b[B\r\x1b[2K${c.brand(' ' + cmd.padEnd(14))}${c.dim(desc)}`);
|
|
679
677
|
}
|
|
680
|
-
process.stdout.write('\x1b[u');
|
|
678
|
+
process.stdout.write('\x1b[u'); // restore cursor to end of typed input
|
|
681
679
|
}
|
|
682
680
|
|
|
683
681
|
process.stdin.on('keypress', (ch, key) => {
|
package/lib/agent.js
CHANGED
|
@@ -77,7 +77,7 @@ function parseToolCalls(text) {
|
|
|
77
77
|
} catch { /* skip */ }
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
// Fallback: <tool_name>{...}</tool_name>
|
|
80
|
+
// Fallback 1: <tool_name>{...}</tool_name>
|
|
81
81
|
for (const name of TOOL_NAMES) {
|
|
82
82
|
const fbRe = new RegExp(`<${name}>([\\s\\S]*?)<\\/${name}>`, 'g');
|
|
83
83
|
let fm;
|
|
@@ -93,6 +93,22 @@ function parseToolCalls(text) {
|
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
// Fallback 2: <tool_name {"key":"val"}>...</tool_name> (JSON in opening tag)
|
|
97
|
+
for (const name of TOOL_NAMES) {
|
|
98
|
+
const fbRe = new RegExp(`<${name}\\s*({[\\s\\S]*?})\\s*>[\\s\\S]*?<\\/${name}>`, 'g');
|
|
99
|
+
let fm;
|
|
100
|
+
while ((fm = fbRe.exec(text)) !== null) {
|
|
101
|
+
const alreadyCaptured = calls.some(c => fm.index >= c.offset && fm.index < c.offset + c.raw.length);
|
|
102
|
+
if (alreadyCaptured) continue;
|
|
103
|
+
try {
|
|
104
|
+
const fixed = fixJsonLiterals(fm[1].trim());
|
|
105
|
+
const parsed = JSON.parse(fixed);
|
|
106
|
+
const { args, ...rest } = parsed || {};
|
|
107
|
+
calls.push({ raw: fm[0], offset: fm.index, name, args: args || (parsed && Object.keys(rest).length > 0 ? rest : {}) });
|
|
108
|
+
} catch { /* skip */ }
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
96
112
|
return calls;
|
|
97
113
|
}
|
|
98
114
|
|
|
@@ -121,6 +137,16 @@ function stripThink(text) {
|
|
|
121
137
|
return text.replace(/<think>[\s\S]*?<\/think>/gi, '').trim();
|
|
122
138
|
}
|
|
123
139
|
|
|
140
|
+
// Strip any residual tool-call tags the model echoes in its text output
|
|
141
|
+
function stripToolTags(text) {
|
|
142
|
+
// <tool>...</tool>
|
|
143
|
+
let out = text.replace(/<tool>[\s\S]*?<\/tool>/gi, '');
|
|
144
|
+
// <tool_name {...}>...</tool_name> AND <tool_name>...</tool_name>
|
|
145
|
+
const namesPattern = TOOL_NAMES.join('|');
|
|
146
|
+
out = out.replace(new RegExp(`<(?:${namesPattern})[^>]*>[\\s\\S]*?<\\/(?:${namesPattern})>`, 'gi'), '');
|
|
147
|
+
return out.trim();
|
|
148
|
+
}
|
|
149
|
+
|
|
124
150
|
// ── Main agent loop ───────────────────────────────────────────
|
|
125
151
|
|
|
126
152
|
const CONFIRM_TOOLS = new Set(['run_command', 'file_delete', 'file_write']);
|
|
@@ -168,13 +194,13 @@ async function runAgent({ messages, model, uncensored, cwd, projectContext, send
|
|
|
168
194
|
// ── No tool calls → final answer ──────────────────────────
|
|
169
195
|
if (calls.length === 0) {
|
|
170
196
|
await trackTokenUsage(token, totalPromptTokens, totalCompletionTokens);
|
|
171
|
-
send({ type: 'text', content: cleaned });
|
|
197
|
+
send({ type: 'text', content: stripToolTags(cleaned) });
|
|
172
198
|
send({ type: 'done' });
|
|
173
199
|
return;
|
|
174
200
|
}
|
|
175
201
|
|
|
176
202
|
// ── Text before first tool call ───────────────────────────
|
|
177
|
-
const textBefore = cleaned.slice(0, calls[0].offset).trim();
|
|
203
|
+
const textBefore = stripToolTags(cleaned.slice(0, calls[0].offset)).trim();
|
|
178
204
|
if (textBefore) send({ type: 'text', content: textBefore });
|
|
179
205
|
|
|
180
206
|
history.push({ role: 'assistant', content: raw });
|