foliko 1.1.56 → 1.1.59

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.
@@ -291,10 +291,11 @@ class ChatUI {
291
291
  sendMessage(message){
292
292
  const self=this;
293
293
  queue.add(function(){
294
- self.agent.sendMessage(message, { sessionId:self.sessionId }).then().then(this.next)
294
+ self.agent.sendMessage(message, { sessionId:self.sessionId }).then(this.next).catch(self.clear_message_done.bind(self));
295
295
  })
296
296
  this.loader.show();
297
- return
297
+ this.tui.setFocus(this.editor);
298
+ return
298
299
  }
299
300
 
300
301
  async handleOnSubmit(value){
@@ -338,7 +339,8 @@ class ChatUI {
338
339
  setTimeout(this.sendMessage.bind(this,message),10)
339
340
 
340
341
  }catch(err){
341
- console.log(err)
342
+ //console.log(err)
343
+ this.create_message(err.message,colored('● ', RED))
342
344
  //this.tui.stop();
343
345
  }
344
346
  }
@@ -447,7 +449,7 @@ class ChatUI {
447
449
  }
448
450
  setTimeout(() => {
449
451
  this.tooler.hide();
450
- this.create_message(`${colored('[提示]', CYAN)} 上下文已压缩\n`,colored('● ', RED))
452
+ this.create_message(`${colored('[提示]', CYAN)} 上下文已压缩`,chalk.dim('● '))
451
453
  this.tui.requestRender();
452
454
  }, 2000);
453
455
  }).catch(err => {
@@ -484,11 +486,11 @@ class ChatUI {
484
486
  }
485
487
  } else if (chunk.type === 'tool-call') {
486
488
  const args = chunk.input ? JSON.stringify(chunk.input).slice(0, 50) : '';
487
- this.tooler.show(`${chalk.yellow('[Tool]')} ${chalk.blue(chunk.toolName)} ${chalk.gray(args+'...')}`)
489
+ this.tooler.show(`${chalk.yellow('[Tool]')} ${folikoGold(chunk.toolName)} ${chalk.gray(args+'...')}`)
488
490
  } else if(chunk.type==='tool-result'){
489
491
  const result = chunk.result;
490
492
  const shortResult = typeof result === 'string' ? result.slice(0, 30) : JSON.stringify(result).slice(0, 30);
491
- this.tooler.show(`${chalk.green('[Tool]')} ${chalk.blue(chunk.toolName)} ${chalk.gray(shortResult+'...')}`)
493
+ this.tooler.show(`${chalk.green('[Tool]')} ${folikoGold(chunk.toolName)} ${chalk.gray(shortResult+'...')}`)
492
494
  // setTimeout(() => this.tooler.hide(), 3000);
493
495
  }else if (chunk.type === 'error') {
494
496
  this.tooler.show(chalk.red(`[Error] ${chunk.error}`))
@@ -503,8 +505,7 @@ class ChatUI {
503
505
  this.sessionScope.on('queue:completed', this.clear_message_done.bind(this))
504
506
 
505
507
  this.sessionScope.on('queue:failed', ({ error }) => {
506
- //console.error(`\n${colored('[错误]', RED)} ${error}`);
507
- this._currentBotMessage.setText(chalk.red(`[错误] ${error.message}`))
508
+ this.create_message(chalk.red(`[错误] ${error}`),colored('● ', RED))
508
509
  this.clear_message_done()
509
510
  });
510
511
  }
@@ -94,29 +94,40 @@ function renderInline(text) {
94
94
  return result;
95
95
  }
96
96
 
97
- function renderThink(line, state = { inThink: false },thinking) {
97
+ function renderThink(line, state = { inThink: false }, thinking) {
98
+ // 处理只有开始标签的情况(line = "<think>" 这样单独一行)
99
+ // 这种情况在流式输出时很常见
100
+ if (line === '<think>' || line === '<think>\n') {
101
+ state.inThink = true;
102
+ return STYLES.think.prefix + line;
103
+ }
104
+
98
105
  let result = line;
99
106
 
100
107
  // 匹配 <think>...</think> 以及可能的跨行情况
101
108
  result = result.replace(/<think>([\s\S]*?)<\/think>/g, (match, content) => {
102
- const prefix=result.indexOf('<think>')>0?'\n':""
103
- return prefix+STYLES.think.prefix + match + STYLES.think.suffix;
109
+ const prefix = result.indexOf('<think>') > 0 ? '\n' : "";
110
+ return prefix + STYLES.think.prefix + match + STYLES.think.suffix;
104
111
  });
105
112
 
106
113
  // 处理未闭合的 think 标签 - 更新状态
107
- if (result.includes('<think>')) {
114
+ if (result.includes('<think>') && !result.includes('</think>')) {
108
115
  state.inThink = true;
109
116
  }
110
117
  if (result.includes('</think>')) {
111
118
  state.inThink = false;
119
+ // 如果只有 </think> 标签(没有开始标签)
120
+ if (!result.includes('<think>')) {
121
+ return STYLES.think.prefix + line + STYLES.think.suffix;
122
+ }
112
123
  }
113
124
 
114
125
  // 处理未闭合的 think 标签(开始但没结束)
115
126
  if (state.inThink && !result.includes('<think>')) {
116
- result = STYLES.think.prefix + result;
127
+ result = STYLES.think.prefix + result + STYLES.think.suffix;
117
128
  }
118
129
 
119
- return thinking?result:renderInline(result);
130
+ return thinking ? result : renderInline(result);
120
131
  }
121
132
 
122
133
  /**
@@ -157,6 +168,11 @@ function renderLine(line, state = { inThink: false, inCodeBlock: false },thinkin
157
168
  return result;
158
169
  }
159
170
 
171
+ // 如果是 continuation 行(在思考块中但没有思考标签)
172
+ if (state.inThink && !line.includes('<think>') && !line.includes('</think>')) {
173
+ return STYLES.think.prefix + leadingNL + renderThink(line, state, thinking) + trailingNL + STYLES.think.suffix;
174
+ }
175
+
160
176
  // 标题
161
177
  if (line.startsWith('### ')) {
162
178
  return `${STYLES.h3.prefix}${renderInline(line.substring(4))}${STYLES.h3.suffix}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "foliko",
3
- "version": "1.1.56",
3
+ "version": "1.1.59",
4
4
  "description": "简约的插件化 Agent 框架",
5
5
  "main": "src/index.js",
6
6
  "type": "commonjs",