prior-cli 1.2.9 → 1.3.1

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 CHANGED
@@ -606,8 +606,9 @@ async function startChat(opts = {}) {
606
606
 
607
607
  // Conversation history (for agent mode, keeps full multi-turn context)
608
608
  const chatHistory = [];
609
- let currentModel = opts.model || null;
610
- let uncensored = opts.uncensored || false;
609
+ let currentModel = opts.model || null;
610
+ let uncensored = opts.uncensored || false;
611
+ let _currentAbortController = null;
611
612
 
612
613
  // ── Live slash-command suggestions ──────────────────────────
613
614
  let clearSuggestions = () => {};
@@ -657,6 +658,11 @@ async function startChat(opts = {}) {
657
658
 
658
659
  if (_suggTimer) { clearTimeout(_suggTimer); _suggTimer = null; }
659
660
 
661
+ if (key.name === 'escape' && _currentAbortController) {
662
+ _currentAbortController.abort();
663
+ return;
664
+ }
665
+
660
666
  if (key.name === 'return' || key.name === 'enter' || (key.ctrl && key.name === 'c')) {
661
667
  clearSuggestions();
662
668
  return;
@@ -989,6 +995,7 @@ Keep it under 350 words. Write prior.md now.`;
989
995
  return approved;
990
996
  };
991
997
 
998
+ _currentAbortController = new AbortController();
992
999
  await runAgent({
993
1000
  messages: [...chatHistory, { role: 'user', content: input }],
994
1001
  model: currentModel,
@@ -996,6 +1003,7 @@ Keep it under 350 words. Write prior.md now.`;
996
1003
  cwd: process.cwd(),
997
1004
  projectContext,
998
1005
  confirm,
1006
+ signal: _currentAbortController.signal,
999
1007
  send: ev => {
1000
1008
  switch (ev.type) {
1001
1009
 
@@ -1003,6 +1011,12 @@ Keep it under 350 words. Write prior.md now.`;
1003
1011
  spinStart('thinking…');
1004
1012
  break;
1005
1013
 
1014
+ case 'cancelled':
1015
+ spinStop();
1016
+ process.stdout.write('\n');
1017
+ console.log(c.muted(' ✗ Cancelled'));
1018
+ break;
1019
+
1006
1020
  case 'tool_start':
1007
1021
  spinStop();
1008
1022
  _progressStarted = false;
@@ -1042,6 +1056,7 @@ Keep it under 350 words. Write prior.md now.`;
1042
1056
 
1043
1057
  case 'text': {
1044
1058
  spinStop();
1059
+ if (!ev.content) break;
1045
1060
  const rendered = renderMarkdown(ev.content);
1046
1061
  const thinkTime = elapsed(Date.now() - _thinkStart);
1047
1062
  console.log(c.brand(' Prior ') + c.muted(`· ${timeNow()} · ${thinkTime}`));
@@ -1065,7 +1080,11 @@ Keep it under 350 words. Write prior.md now.`;
1065
1080
  });
1066
1081
  } catch (err) {
1067
1082
  spinStop();
1068
- console.error(c.err(` ✗ ${err.message}`));
1083
+ if (err.name !== 'AbortError') {
1084
+ console.error(c.err(` ✗ ${err.message}`));
1085
+ }
1086
+ } finally {
1087
+ _currentAbortController = null;
1069
1088
  }
1070
1089
 
1071
1090
  chatHistory.push({ role: 'user', content: input });
package/lib/agent.js CHANGED
@@ -10,12 +10,13 @@ const MAX_ITER = 14;
10
10
 
11
11
  // ── Single inference call (server just runs Ollama + returns) ─
12
12
 
13
- async function infer(messages, model, token, { cwd, uncensored, projectContext } = {}) {
13
+ async function infer(messages, model, token, { cwd, uncensored, projectContext } = {}, signal) {
14
14
  const res = await fetch(`${CLI_BASE}/api/infer`, {
15
15
  method: 'POST',
16
16
  headers: { 'Content-Type': 'application/json' },
17
17
  body: JSON.stringify({ messages, model, token, cwd, uncensored, projectContext }),
18
18
  timeout: 120000,
19
+ signal,
19
20
  });
20
21
  if (!res.ok) {
21
22
  const err = await res.json().catch(() => ({}));
@@ -150,7 +151,7 @@ function stripToolTags(text) {
150
151
 
151
152
  const CONFIRM_TOOLS = new Set(['run_command', 'file_delete', 'file_write']);
152
153
 
153
- async function runAgent({ messages, model, uncensored, cwd, projectContext, send, confirm }) {
154
+ async function runAgent({ messages, model, uncensored, cwd, projectContext, send, confirm, signal }) {
154
155
  const token = getToken();
155
156
  const history = [...messages];
156
157
 
@@ -159,13 +160,24 @@ async function runAgent({ messages, model, uncensored, cwd, projectContext, send
159
160
 
160
161
  for (let iter = 0; iter < MAX_ITER; iter++) {
161
162
 
163
+ if (signal?.aborted) {
164
+ send({ type: 'cancelled' });
165
+ send({ type: 'done' });
166
+ return;
167
+ }
168
+
162
169
  send({ type: 'thinking' });
163
170
 
164
171
  let result;
165
172
  try {
166
- result = await infer(history, model || 'qwen3.5:4b', token, { cwd, uncensored, projectContext });
173
+ result = await infer(history, model || 'qwen3.5:4b', token, { cwd, uncensored, projectContext }, signal);
167
174
  } catch (err) {
168
175
  await trackTokenUsage(token, totalPromptTokens, totalCompletionTokens);
176
+ if (err.name === 'AbortError' || signal?.aborted) {
177
+ send({ type: 'cancelled' });
178
+ send({ type: 'done' });
179
+ return;
180
+ }
169
181
  send({ type: 'error', message: err.message });
170
182
  send({ type: 'done' });
171
183
  return;
@@ -186,8 +198,15 @@ async function runAgent({ messages, model, uncensored, cwd, projectContext, send
186
198
 
187
199
  // ── No tool calls → final answer ──────────────────────────
188
200
  if (calls.length === 0) {
201
+ const finalText = stripToolTags(cleaned);
202
+ if (!finalText && iter < MAX_ITER - 1) {
203
+ // Model returned blank (all think tags, no actual output) — nudge once
204
+ history.push({ role: 'assistant', content: raw });
205
+ history.push({ role: 'user', content: '(Your response was empty. Please write your reply.)' });
206
+ continue;
207
+ }
189
208
  await trackTokenUsage(token, totalPromptTokens, totalCompletionTokens);
190
- send({ type: 'text', content: stripToolTags(cleaned) });
209
+ send({ type: 'text', content: finalText });
191
210
  send({ type: 'done' });
192
211
  return;
193
212
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prior-cli",
3
- "version": "1.2.9",
3
+ "version": "1.3.1",
4
4
  "description": "Prior Network AI — command-line interface",
5
5
  "bin": {
6
6
  "prior": "bin/prior.js"