linco-connect 1.1.0 → 1.1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "linco-connect",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "自研 IM 桥接多 Agent 服务",
5
5
  "main": "server.js",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  const { spawn } = require('child_process');
2
2
  const { isDangerousCommand } = require('../danger');
3
- const { send, sendError, sendSystem } = require('../protocol');
3
+ const { send, sendError, sendSystem, sendTurnEnd } = require('../protocol');
4
4
  const { persistAgentSessionId, stopAgentProcess: stopSessionProcess, updateAgentSessionHistory } = require('../session');
5
5
  const { getOutboxDir } = require('../outgoingAttachmentHandler');
6
6
  const { createTextStreamBuffer, appendTextStream, flushTextStream, resetTextStream } = require('../streamBuffer');
@@ -603,6 +603,7 @@ function handleAppServerMessage(message, session) {
603
603
  } else {
604
604
  sendSystem(ws, 'Codex 本次执行没有输出。');
605
605
  }
606
+ sendTurnEnd(ws, session, 'timeout');
606
607
  const cfg = session._lastConfig;
607
608
  if (cfg) drainQueue(ws, session, cfg);
608
609
  }
@@ -622,6 +623,7 @@ function handleAppServerMessage(message, session) {
622
623
  } else {
623
624
  sendSystem(ws, 'Codex 本次执行没有输出。');
624
625
  }
626
+ sendTurnEnd(ws, session);
625
627
  const cfg = session._lastConfig;
626
628
  if (cfg) {
627
629
  drainQueue(ws, session, cfg);
@@ -631,6 +633,7 @@ function handleAppServerMessage(message, session) {
631
633
 
632
634
  if (method === 'error' || method.includes('error')) {
633
635
  sendError(ws, params.message || JSON.stringify(params));
636
+ sendTurnEnd(ws, session, 'error', { error: params.message || JSON.stringify(params) });
634
637
  clearTurnState(session);
635
638
  return;
636
639
  }
@@ -861,6 +864,7 @@ function runExecTurn(input, ws, session, config) {
861
864
  if (code === 0) {
862
865
  updateCodexSessionStats(session);
863
866
  }
867
+ sendTurnEnd(ws, session, code === 0 ? 'completed' : 'error', code === 0 ? {} : { error: stderr.trim() || `Codex 退出,状态码: ${code}` });
864
868
  drainQueue(ws, session, config);
865
869
  });
866
870
 
@@ -1,5 +1,5 @@
1
1
  const { isDangerousCommand } = require('../danger');
2
- const { send, sendError, sendSystem } = require('../protocol');
2
+ const { send, sendError, sendSystem, sendTurnEnd } = require('../protocol');
3
3
  const { persistAgentSessionId, stopAgentProcess: stopSessionProcess, updateAgentSessionHistory, createAgentSessionEntry, saveSessionMetadata } = require('../session');
4
4
  const { getOutboxDir } = require('../outgoingAttachmentHandler');
5
5
  const { createTextStreamBuffer, appendTextStream, flushTextStream, resetTextStream } = require('../streamBuffer');
@@ -177,10 +177,12 @@ function handleHermesEvent(event, ws, session, config) {
177
177
  return;
178
178
  case 'run.failed':
179
179
  sendError(ws, event.error || 'Hermes run 执行失败');
180
+ sendTurnEnd(ws, session, 'error', { error: event.error || 'Hermes run 执行失败' });
180
181
  finishTurn(ws, session, config);
181
182
  return;
182
183
  case 'run.cancelled':
183
184
  sendSystem(ws, 'Hermes run 已停止。');
185
+ sendTurnEnd(ws, session, 'cancelled');
184
186
  finishTurn(ws, session, config);
185
187
  return;
186
188
  default:
@@ -240,6 +242,7 @@ function completeRun(event, ws, session, config) {
240
242
  sendSystem(ws, 'Hermes 本次执行没有输出。');
241
243
  }
242
244
  updateHermesSessionStats(session, event.usage);
245
+ sendTurnEnd(ws, session);
243
246
  finishTurn(ws, session, config);
244
247
  }
245
248
 
@@ -1,7 +1,7 @@
1
1
  const crypto = require('crypto');
2
2
  const path = require('path');
3
3
  const { isDangerousCommand } = require('../danger');
4
- const { send, sendError, sendSystem } = require('../protocol');
4
+ const { send, sendError, sendSystem, sendTurnEnd } = require('../protocol');
5
5
  const {
6
6
  createAgentSessionEntry,
7
7
  persistAgentSessionId,
@@ -211,12 +211,14 @@ function handleChatEvent(payload, ws, session, config) {
211
211
  flushOpenClawAssistantText(ws, session);
212
212
  if (session.streamState?.assistantStarted) send(ws, 'assistant_end', {});
213
213
  sendSystem(ws, 'OpenClaw run stopped.');
214
+ sendTurnEnd(ws, session, 'cancelled');
214
215
  finishTurn(ws, session, config, { drain: false });
215
216
  return;
216
217
  }
217
218
 
218
219
  if (payload.state === 'error') {
219
220
  sendError(ws, payload.errorMessage || 'OpenClaw run failed.');
221
+ sendTurnEnd(ws, session, 'error', { error: payload.errorMessage || 'OpenClaw run failed.' });
220
222
  finishTurn(ws, session, config);
221
223
  }
222
224
  }
@@ -227,6 +229,7 @@ function completeRun(payload, ws, session, config) {
227
229
  if (hadOutput) send(ws, 'assistant_end', {});
228
230
  else sendSystem(ws, 'OpenClaw returned no output.');
229
231
  updateOpenClawSessionStats(session, payload.usage);
232
+ sendTurnEnd(ws, session);
230
233
  finishTurn(ws, session, config);
231
234
  }
232
235
 
@@ -3,7 +3,7 @@ const fs = require('fs');
3
3
  const path = require('path');
4
4
  const { isDangerousCommand } = require('./danger');
5
5
  const { buildOutboxSystemPrompt, getOutboxDir } = require('./outgoingAttachmentHandler');
6
- const { send, sendError, sendSystem } = require('./protocol');
6
+ const { send, sendError, sendSystem, sendTurnEnd } = require('./protocol');
7
7
  const { appendTextStream, flushTextStream, resetTextStream } = require('./streamBuffer');
8
8
  const { persistClaudeSessionId, stopAgentProcess, updateAgentSessionHistory } = require('./session');
9
9
  const {
@@ -328,6 +328,7 @@ function handleClaudeMessage(parsed, ws, session, config) {
328
328
  usage: session.usage,
329
329
  messageCount: session.messageCount,
330
330
  });
331
+ sendTurnEnd(ws, session);
331
332
  session.isTurnActive = false;
332
333
  session.currentInputForNoOutput = null;
333
334
  drainMessageQueue(ws, session, config);
@@ -132,6 +132,17 @@ function mapLocalEventToLinco(event, session, config, linco) {
132
132
  };
133
133
  case 'outgoing_attachment':
134
134
  return mapOutgoingAttachment(event, base, session);
135
+ case 'turn_end':
136
+ return {
137
+ ...base,
138
+ ...event,
139
+ type: 'turn_end',
140
+ requestId: event.requestId || event.request_id || base.messageId,
141
+ streamId: event.streamId || event.stream_id || linco.streamId || base.streamId,
142
+ sessionKey: event.sessionKey || event.session_key || session.id,
143
+ reason: event.reason || 'completed',
144
+ ts: event.ts || Date.now(),
145
+ };
135
146
  default:
136
147
  return {
137
148
  ...base,
package/src/protocol.js CHANGED
@@ -10,8 +10,26 @@ function sendError(ws, text) {
10
10
  send(ws, 'error', { text });
11
11
  }
12
12
 
13
+ function buildTurnEndPayload(session, reason = 'completed', payload = {}) {
14
+ const linco = session?.linco || {};
15
+ return {
16
+ requestId: payload.requestId || payload.request_id || linco.messageId,
17
+ streamId: payload.streamId || payload.stream_id || linco.streamId,
18
+ sessionKey: payload.sessionKey || payload.session_key || session?.id,
19
+ reason,
20
+ ts: Date.now(),
21
+ ...payload,
22
+ };
23
+ }
24
+
25
+ function sendTurnEnd(ws, session, reason = 'completed', payload = {}) {
26
+ send(ws, 'turn_end', buildTurnEndPayload(session, reason, payload));
27
+ }
28
+
13
29
  module.exports = {
14
30
  send,
15
31
  sendError,
16
32
  sendSystem,
33
+ sendTurnEnd,
34
+ buildTurnEndPayload,
17
35
  };