linco-connect 1.1.1 → 1.1.2
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 +1 -1
- package/src/attachmentHandler.js +2 -1
- package/src/claudeRunner.js +6 -2
- package/src/protocol.js +14 -1
- package/src/slashCommands.js +21 -16
package/package.json
CHANGED
package/src/attachmentHandler.js
CHANGED
|
@@ -2,7 +2,7 @@ const crypto = require('crypto');
|
|
|
2
2
|
const fs = require('fs');
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const { ensureDir } = require('./config');
|
|
5
|
-
const { sendError, sendSystem } = require('./protocol');
|
|
5
|
+
const { sendError, sendSystem, sendTurnEnd } = require('./protocol');
|
|
6
6
|
|
|
7
7
|
const RESERVED_WINDOWS_NAMES = new Set(['CON', 'PRN', 'AUX', 'NUL', 'COM1', 'COM2', 'COM3', 'COM4', 'COM5', 'COM6', 'COM7', 'COM8', 'COM9', 'LPT1', 'LPT2', 'LPT3', 'LPT4', 'LPT5', 'LPT6', 'LPT7', 'LPT8', 'LPT9']);
|
|
8
8
|
const SUPPORTED_IMAGE_MEDIA_TYPES = new Set(['image/png', 'image/jpeg', 'image/gif', 'image/webp']);
|
|
@@ -25,6 +25,7 @@ function handleMessageWithAttachments(msg, ws, session, config, executeAgentQuer
|
|
|
25
25
|
savedAttachments = saveAttachments(session, attachments, config);
|
|
26
26
|
} catch (err) {
|
|
27
27
|
sendError(ws, `❌ 附件处理失败: ${err.message}`);
|
|
28
|
+
sendTurnEnd(ws, session, 'error', { error: err.message });
|
|
28
29
|
return;
|
|
29
30
|
}
|
|
30
31
|
|
package/src/claudeRunner.js
CHANGED
|
@@ -193,7 +193,9 @@ function ensureClaudeProcess(ws, session, config) {
|
|
|
193
193
|
if (session.isTurnActive) {
|
|
194
194
|
session.isTurnActive = false;
|
|
195
195
|
session.currentInputForNoOutput = null;
|
|
196
|
-
|
|
196
|
+
const message = code === 0 || code === null ? '⚠️ Claude 会话已结束。' : `❌ Claude 进程退出,退出码: ${code}`;
|
|
197
|
+
sendError(ws, message);
|
|
198
|
+
sendTurnEnd(ws, session, 'error', { error: message });
|
|
197
199
|
drainMessageQueue(ws, session, config);
|
|
198
200
|
}
|
|
199
201
|
});
|
|
@@ -205,7 +207,9 @@ function ensureClaudeProcess(ws, session, config) {
|
|
|
205
207
|
session.isTurnActive = false;
|
|
206
208
|
session.currentInputForNoOutput = null;
|
|
207
209
|
flushAssistantText(ws, session);
|
|
208
|
-
|
|
210
|
+
const message = `❌ 无法启动 Claude: ${err.message}\n请确认已安装 Claude Code 并设置好 API 密钥。`;
|
|
211
|
+
sendError(ws, message);
|
|
212
|
+
sendTurnEnd(ws, session, 'error', { error: message });
|
|
209
213
|
});
|
|
210
214
|
|
|
211
215
|
return child;
|
package/src/protocol.js
CHANGED
|
@@ -22,8 +22,21 @@ function buildTurnEndPayload(session, reason = 'completed', payload = {}) {
|
|
|
22
22
|
};
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
function turnEndKey(payload) {
|
|
26
|
+
return [
|
|
27
|
+
payload.requestId || '',
|
|
28
|
+
payload.streamId || '',
|
|
29
|
+
payload.sessionKey || '',
|
|
30
|
+
].join('|');
|
|
31
|
+
}
|
|
32
|
+
|
|
25
33
|
function sendTurnEnd(ws, session, reason = 'completed', payload = {}) {
|
|
26
|
-
|
|
34
|
+
const turnEndPayload = buildTurnEndPayload(session, reason, payload);
|
|
35
|
+
const key = turnEndKey(turnEndPayload);
|
|
36
|
+
if (session && session.lastTurnEndKey === key) return false;
|
|
37
|
+
if (session) session.lastTurnEndKey = key;
|
|
38
|
+
send(ws, 'turn_end', turnEndPayload);
|
|
39
|
+
return true;
|
|
27
40
|
}
|
|
28
41
|
|
|
29
42
|
module.exports = {
|
package/src/slashCommands.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const { resetOutgoingAttachments, startOutboxWatcher, stopOutboxWatcher } = require('./outgoingAttachmentHandler');
|
|
4
|
-
const { sendError, sendSystem } = require('./protocol');
|
|
4
|
+
const { sendError, sendSystem, sendTurnEnd } = require('./protocol');
|
|
5
5
|
const { removeAgentSessionFromHistory, saveSessionMetadata } = require('./session');
|
|
6
6
|
const { resolvePendingDanger, resolvePendingPermission, stopAgentProcess } = require('./agentRunner');
|
|
7
7
|
const { clearPendingPermissions, pendingPermissionIds } = require('./permissionState');
|
|
@@ -35,7 +35,7 @@ function handleSlashCommand(text, ws, session, config) {
|
|
|
35
35
|
📎 支持附件:默认允许普通文件(如 csv、xlsx、sql、txt、md、pdf、docx 等),高风险可执行/脚本文件默认拦截
|
|
36
36
|
📤 Agent 生成文件后可放入当前会话 outbox 目录自动发送到对话框
|
|
37
37
|
🔁 其他 /xxx 命令会透传给当前 Agent,优先使用当前 Agent 原生斜杠命令能力`);
|
|
38
|
-
return
|
|
38
|
+
return completeLocalCommand(ws, session);
|
|
39
39
|
|
|
40
40
|
case '/commands':
|
|
41
41
|
sendSystem(ws, `${localCommandsHelp()}
|
|
@@ -44,38 +44,38 @@ function handleSlashCommand(text, ws, session, config) {
|
|
|
44
44
|
除上述本地命令外,其他 /xxx 会直接发送给当前 Agent,例如 /model、/status、/memory、/compact 等。
|
|
45
45
|
|
|
46
46
|
⚠️ 注意:部分 Agent 原生命令只在交互式 CLI/TUI 中更新界面;在 Linco 的 stream-json 模式下可能返回“无输出”或提示当前环境不可用。遇到这种情况不是连接失败,而是该命令不适合当前桥接模式。`);
|
|
47
|
-
return
|
|
47
|
+
return completeLocalCommand(ws, session);
|
|
48
48
|
|
|
49
49
|
case '/status':
|
|
50
50
|
sendStatus(ws, session);
|
|
51
|
-
return
|
|
51
|
+
return completeLocalCommand(ws, session);
|
|
52
52
|
|
|
53
53
|
case '/pwd':
|
|
54
54
|
if (isHermesSession(session)) {
|
|
55
55
|
sendHermesWorkspaceNotice(ws);
|
|
56
|
-
return
|
|
56
|
+
return completeLocalCommand(ws, session);
|
|
57
57
|
}
|
|
58
58
|
sendSystem(ws, `📂 ${session.workspace}`);
|
|
59
|
-
return
|
|
59
|
+
return completeLocalCommand(ws, session);
|
|
60
60
|
|
|
61
61
|
case '/cd':
|
|
62
62
|
if (isHermesSession(session)) {
|
|
63
63
|
sendHermesWorkspaceNotice(ws);
|
|
64
|
-
return
|
|
64
|
+
return completeLocalCommand(ws, session);
|
|
65
65
|
}
|
|
66
66
|
handleCd(parts[1], ws, session, config);
|
|
67
|
-
return
|
|
67
|
+
return completeLocalCommand(ws, session);
|
|
68
68
|
|
|
69
69
|
case '/new':
|
|
70
70
|
stopAgentProcess(session, { clearAgentSession: true });
|
|
71
71
|
resetOutgoingAttachments(session, config);
|
|
72
72
|
sendSystem(ws, '🆕 已开启新会话,之前上下文已清除。');
|
|
73
|
-
return
|
|
73
|
+
return completeLocalCommand(ws, session);
|
|
74
74
|
|
|
75
75
|
case '/stop':
|
|
76
76
|
stopAgentProcess(session, { clearAgentSession: false });
|
|
77
77
|
sendSystem(ws, '⏹️ 已停止当前 Agent 进程,下次消息会尝试恢复当前会话。');
|
|
78
|
-
return
|
|
78
|
+
return completeLocalCommand(ws, session);
|
|
79
79
|
|
|
80
80
|
case '/base':
|
|
81
81
|
sendSystem(ws, `🗄️ Linco 运行信息:
|
|
@@ -84,33 +84,38 @@ Linco Home: ${config.lincoHome}
|
|
|
84
84
|
会话运行目录: ${session.runtimeDir}
|
|
85
85
|
附件目录: ${session.attachmentsDir}
|
|
86
86
|
outbox 目录: ${session.outboxDir}`);
|
|
87
|
-
return
|
|
87
|
+
return completeLocalCommand(ws, session);
|
|
88
88
|
|
|
89
89
|
case '/list':
|
|
90
90
|
handleList(parts[1], ws, session);
|
|
91
|
-
return
|
|
91
|
+
return completeLocalCommand(ws, session);
|
|
92
92
|
|
|
93
93
|
case '/switch':
|
|
94
94
|
handleSwitch(parts[1], ws, session, config);
|
|
95
|
-
return
|
|
95
|
+
return completeLocalCommand(ws, session);
|
|
96
96
|
|
|
97
97
|
case '/delete':
|
|
98
98
|
handleDelete(parts[1], ws, session);
|
|
99
|
-
return
|
|
99
|
+
return completeLocalCommand(ws, session);
|
|
100
100
|
|
|
101
101
|
case '/approve':
|
|
102
102
|
handleApprove(parts[1], ws, session, config);
|
|
103
|
-
return
|
|
103
|
+
return completeLocalCommand(ws, session);
|
|
104
104
|
|
|
105
105
|
case '/usage':
|
|
106
106
|
handleUsage(ws, session);
|
|
107
|
-
return
|
|
107
|
+
return completeLocalCommand(ws, session);
|
|
108
108
|
|
|
109
109
|
default:
|
|
110
110
|
return false;
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
+
function completeLocalCommand(ws, session) {
|
|
115
|
+
sendTurnEnd(ws, session);
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
|
|
114
119
|
function sendStatus(ws, session) {
|
|
115
120
|
const processRunning = !!(
|
|
116
121
|
(session.agentProcess || session.claudeProcess) &&
|