linco-connect 1.1.5 → 1.1.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/agents/codex.js +37 -32
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "linco-connect",
3
- "version": "1.1.5",
3
+ "version": "1.1.6",
4
4
  "description": "自研 IM 桥接多 Agent 服务",
5
5
  "main": "server.js",
6
6
  "bin": {
@@ -12,6 +12,8 @@ const {
12
12
  setPendingPermission,
13
13
  } = require('../permissionState');
14
14
 
15
+ const CODEX_TURN_COMPLETION_FALLBACK_MS = 1000;
16
+
15
17
  function execute(input, ws, session, config) {
16
18
  const textForCheck = stringifyInput(input);
17
19
  if (isDangerousCommand(textForCheck) && session.autoApprove !== true) {
@@ -286,6 +288,35 @@ function clearTurnState(session) {
286
288
  }
287
289
  }
288
290
 
291
+ function finishCodexTurn(ws, session, config, reason = 'completed', payload = {}) {
292
+ if (!session.isTurnActive) return;
293
+
294
+ if (reason === 'completed') {
295
+ updateCodexSessionStats(session, payload);
296
+ }
297
+
298
+ clearTurnState(session);
299
+ if (session.sawPartialAssistantText) {
300
+ sendCodexAssistantEnd(ws, session);
301
+ } else {
302
+ sendSystem(ws, 'Codex 本次执行没有输出。');
303
+ }
304
+ sendTurnEnd(ws, session, reason, payload);
305
+ if (config) drainQueue(ws, session, config);
306
+ }
307
+
308
+ function isFinalCodexAssistantItem(params) {
309
+ const item = params.item || {};
310
+ return isCodexAssistantMessageType(item.type) && item.phase === 'final_answer';
311
+ }
312
+
313
+ function armCodexTurnCompletionFallback(ws, session, config) {
314
+ if (session.turnCompletedTimerId) clearTimeout(session.turnCompletedTimerId);
315
+ session.turnCompletedTimerId = setTimeout(() => {
316
+ finishCodexTurn(ws, session, config, 'completed');
317
+ }, CODEX_TURN_COMPLETION_FALLBACK_MS);
318
+ }
319
+
289
320
  function ensureCodexStreamState(session) {
290
321
  if (!session.codexStreamState) {
291
322
  session.codexStreamState = createTextStreamBuffer();
@@ -597,42 +628,16 @@ function handleAppServerMessage(message, session) {
597
628
  appendCodexAssistantText(text, ws, session, () => send(ws, 'assistant_start', {}));
598
629
  markCodexAgentMessageEmitted(session, agentMessageId);
599
630
  }
600
- // Safety fallback: if turn/completed never arrives, clear isTurnActive so the next message doesn't get stuck.
601
- if (session.turnCompletedTimerId) clearTimeout(session.turnCompletedTimerId);
602
- session.turnCompletedTimerId = setTimeout(() => {
603
- if (session.isTurnActive) {
604
- session.isTurnActive = false;
605
- session.currentInputForNoOutput = null;
606
- if (session.sawPartialAssistantText) {
607
- sendCodexAssistantEnd(ws, session);
608
- } else {
609
- sendSystem(ws, 'Codex 本次执行没有输出。');
610
- }
611
- sendTurnEnd(ws, session, 'timeout');
612
- const cfg = session._lastConfig;
613
- if (cfg) drainQueue(ws, session, cfg);
614
- }
615
- }, 10000);
631
+ // Safety fallback: some app-server builds emit task completion without a turn/completed notification.
632
+ // Arm it only after the final assistant message, not after user/tool/reasoning items.
633
+ if (isFinalCodexAssistantItem(params)) {
634
+ armCodexTurnCompletionFallback(ws, session, session._lastConfig);
635
+ }
616
636
  return;
617
637
  }
618
638
 
619
639
  if (method === 'turn/completed' || method === 'turn.completed') {
620
- if (session.turnCompletedTimerId) {
621
- clearTimeout(session.turnCompletedTimerId);
622
- session.turnCompletedTimerId = null;
623
- }
624
- updateCodexSessionStats(session, params);
625
- clearTurnState(session);
626
- if (session.sawPartialAssistantText) {
627
- sendCodexAssistantEnd(ws, session);
628
- } else {
629
- sendSystem(ws, 'Codex 本次执行没有输出。');
630
- }
631
- sendTurnEnd(ws, session);
632
- const cfg = session._lastConfig;
633
- if (cfg) {
634
- drainQueue(ws, session, cfg);
635
- }
640
+ finishCodexTurn(ws, session, session._lastConfig, 'completed', params);
636
641
  return;
637
642
  }
638
643