aws-runtime-bridge 1.4.0 → 1.6.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/README.md +1 -1
- package/dist/adapter/AdapterRegistry.d.ts +1 -1
- package/dist/adapter/AdapterRegistry.d.ts.map +1 -1
- package/dist/adapter/AdapterRegistry.js +0 -2
- package/dist/adapter/ClaudeSdkAdapter.d.ts +4 -0
- package/dist/adapter/ClaudeSdkAdapter.d.ts.map +1 -1
- package/dist/adapter/ClaudeSdkAdapter.js +11 -2
- package/dist/adapter/CodexSdkAdapter.js +1 -1
- package/dist/adapter/OpencodeSdkAdapter.d.ts +13 -1
- package/dist/adapter/OpencodeSdkAdapter.d.ts.map +1 -1
- package/dist/adapter/OpencodeSdkAdapter.js +58 -6
- package/dist/adapter/OpencodeSdkAdapter.test.js +57 -1
- package/dist/adapter/types.d.ts +10 -0
- package/dist/adapter/types.d.ts.map +1 -1
- package/dist/index.js +14 -43
- package/dist/middleware/auth.d.ts +5 -0
- package/dist/middleware/auth.d.ts.map +1 -1
- package/dist/middleware/auth.js +9 -1
- package/dist/routes/file-browser.d.ts +10 -0
- package/dist/routes/file-browser.d.ts.map +1 -1
- package/dist/routes/file-browser.js +226 -4
- package/dist/routes/file-browser.test.js +31 -0
- package/dist/routes/instance.d.ts +10 -0
- package/dist/routes/instance.d.ts.map +1 -1
- package/dist/routes/instance.js +93 -2
- package/dist/routes/instance.test.js +50 -0
- package/dist/routes/pty.d.ts +106 -0
- package/dist/routes/pty.d.ts.map +1 -0
- package/dist/routes/pty.js +526 -0
- package/dist/routes/pty.test.d.ts +2 -0
- package/dist/routes/pty.test.d.ts.map +1 -0
- package/dist/routes/pty.test.js +73 -0
- package/dist/routes/sessions.d.ts +1 -1
- package/dist/routes/sessions.d.ts.map +1 -1
- package/dist/routes/sessions.js +32 -213
- package/dist/routes/terminal.d.ts +32 -3
- package/dist/routes/terminal.d.ts.map +1 -1
- package/dist/routes/terminal.js +411 -243
- package/dist/routes/terminal.test.js +105 -29
- package/dist/services/agent-process-manager.d.ts +2 -2
- package/dist/services/agent-process-manager.d.ts.map +1 -1
- package/dist/services/agent-process-manager.js +3 -3
- package/dist/services/process-detector.d.ts +2 -4
- package/dist/services/process-detector.d.ts.map +1 -1
- package/dist/services/process-detector.js +9 -16
- package/dist/services/process-registry.d.ts +2 -2
- package/dist/services/process-registry.d.ts.map +1 -1
- package/dist/services/process-registry.js +1 -1
- package/dist/services/session-output.d.ts +27 -5
- package/dist/services/session-output.d.ts.map +1 -1
- package/dist/services/session-output.js +48 -3
- package/dist/services/session-output.test.js +43 -29
- package/dist/services/terminal-persistence.d.ts +9 -0
- package/dist/services/terminal-persistence.d.ts.map +1 -1
- package/dist/services/terminal-persistence.js +20 -0
- package/dist/services/tool-installer.d.ts +10 -0
- package/dist/services/tool-installer.d.ts.map +1 -1
- package/dist/services/tool-installer.js +126 -5
- package/dist/services/tool-installer.test.js +32 -1
- package/dist/services/workspace-files.d.ts +86 -0
- package/dist/services/workspace-files.d.ts.map +1 -1
- package/dist/services/workspace-files.js +571 -21
- package/dist/services/workspace-files.test.js +471 -11
- package/dist/services/workspace-watch.d.ts +21 -0
- package/dist/services/workspace-watch.d.ts.map +1 -0
- package/dist/services/workspace-watch.js +123 -0
- package/dist/services/workspace-watch.test.d.ts +2 -0
- package/dist/services/workspace-watch.test.d.ts.map +1 -0
- package/dist/services/workspace-watch.test.js +38 -0
- package/dist/types.d.ts +8 -4
- package/dist/types.d.ts.map +1 -1
- package/package.json +9 -1
package/README.md
CHANGED
|
@@ -58,7 +58,7 @@ If an existing runtime binding still stores an old scheduler URL such as `http:/
|
|
|
58
58
|
`aws-runtime-bridge` 命令仍作为兼容别名保留。安装 `aws-runtime-bridge` 后,包内会随附
|
|
59
59
|
`aws-client-agent-mcp` 的编译产物;bridge 启动时只负责准备该 MCP 产物,不再在 Agent 启动时默认动态注入 `aws-mcp`。
|
|
60
60
|
|
|
61
|
-
请在面板中为目标运行时安装/配置 MCP;这样 Claude Code、Codex、OpenCode
|
|
61
|
+
请在面板中为目标运行时安装/配置 MCP;这样 Claude Code、Codex、OpenCode 等 SDK 启动模式都走一致的持久化 MCP 配置链路。
|
|
62
62
|
|
|
63
63
|
如需使用自定义 MCP 可执行文件,可设置:
|
|
64
64
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Adapter 注册表 —— 管理 Provider ID → Adapter 实例的映射
|
|
3
3
|
*/
|
|
4
4
|
import type { BaseProviderAdapter } from './types.js';
|
|
5
|
-
export type AdapterType = 'claude-sdk' | 'codex-sdk' | 'opencode-sdk'
|
|
5
|
+
export type AdapterType = 'claude-sdk' | 'codex-sdk' | 'opencode-sdk';
|
|
6
6
|
/**
|
|
7
7
|
* Adapter 注册表
|
|
8
8
|
* 管理所有 Provider Adapter 实例的生命周期
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdapterRegistry.d.ts","sourceRoot":"","sources":["../../src/adapter/AdapterRegistry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,WAAW,GAAG,cAAc,
|
|
1
|
+
{"version":3,"file":"AdapterRegistry.d.ts","sourceRoot":"","sources":["../../src/adapter/AdapterRegistry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,WAAW,GAAG,cAAc,CAAC;AAEtE;;;GAGG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAA+C;IAE/D;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,mBAAmB,GAAG,IAAI;IAO5C;;;;OAIG;IACH,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,mBAAmB;IAU5C;;;;OAIG;IACH,SAAS,CAAC,WAAW,EAAE,WAAW,GAAG,mBAAmB;IASxD;;;OAGG;IACH,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;IAIhC;;OAEG;IACH,gBAAgB,IAAI,MAAM,EAAE;IAI5B;;OAEG;IACH,MAAM,IAAI,mBAAmB,EAAE;IAI/B;;OAEG;IACH,OAAO,IAAI,IAAI;IAWf;;OAEG;IACH,OAAO,CAAC,SAAS;CAYlB;AAGD,eAAO,MAAM,eAAe,iBAAwB,CAAC"}
|
|
@@ -73,6 +73,10 @@ export declare class ClaudeSdkAdapter extends EventEmitter implements BaseProvid
|
|
|
73
73
|
private isTaskPollingIdleCommand;
|
|
74
74
|
private isMessagePollingIdleCommand;
|
|
75
75
|
private buildMessagePollingIdlePrompt;
|
|
76
|
+
/**
|
|
77
|
+
* 发送手动快捷键 token 序列,和空闲自动命令共用解析逻辑。
|
|
78
|
+
*/
|
|
79
|
+
sendShortcutInput(sessionId: string, command: string): Promise<void>;
|
|
76
80
|
/**
|
|
77
81
|
* 执行空闲命令(支持 [enter], [wait:n] 等 token)
|
|
78
82
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClaudeSdkAdapter.d.ts","sourceRoot":"","sources":["../../src/adapter/ClaudeSdkAdapter.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"ClaudeSdkAdapter.d.ts","sourceRoot":"","sources":["../../src/adapter/ClaudeSdkAdapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -463,6 +463,12 @@ export class ClaudeSdkAdapter extends EventEmitter {
|
|
|
463
463
|
buildMessagePollingIdlePrompt() {
|
|
464
464
|
return '请调用 poll_message 工具阻塞等待新消息;收到消息后再处理消息内容。';
|
|
465
465
|
}
|
|
466
|
+
/**
|
|
467
|
+
* 发送手动快捷键 token 序列,和空闲自动命令共用解析逻辑。
|
|
468
|
+
*/
|
|
469
|
+
async sendShortcutInput(sessionId, command) {
|
|
470
|
+
await this.executeIdleCommand(sessionId, command);
|
|
471
|
+
}
|
|
466
472
|
/**
|
|
467
473
|
* 执行空闲命令(支持 [enter], [wait:n] 等 token)
|
|
468
474
|
*/
|
|
@@ -921,12 +927,13 @@ export class ClaudeSdkAdapter extends EventEmitter {
|
|
|
921
927
|
case 'tool_use_start':
|
|
922
928
|
// AI 正在调用工具
|
|
923
929
|
{
|
|
924
|
-
const actionInfo = getToolActionInfo(msg.tool_name, msg.tool_input);
|
|
930
|
+
const actionInfo = { ...getToolActionInfo(msg.tool_name, msg.tool_input), actionId: msg.tool_use_id };
|
|
925
931
|
session.status = 'tool_using';
|
|
926
932
|
this.emit('status-change', sessionId, 'tool_using', {
|
|
927
933
|
actionType: actionInfo.actionType,
|
|
928
934
|
actionLabel: actionInfo.actionLabel,
|
|
929
935
|
actionDetail: actionInfo.actionDetail,
|
|
936
|
+
actionId: actionInfo.actionId,
|
|
930
937
|
});
|
|
931
938
|
this.stopIdleDetection(sessionId);
|
|
932
939
|
this.handleToolUse(sessionId, session, msg, timestamp);
|
|
@@ -1141,13 +1148,14 @@ export class ClaudeSdkAdapter extends EventEmitter {
|
|
|
1141
1148
|
}
|
|
1142
1149
|
}
|
|
1143
1150
|
// 获取工具动作分类信息(使用完整参数)
|
|
1144
|
-
const actionInfo = getToolActionInfo(recentInfo.name, toolInput);
|
|
1151
|
+
const actionInfo = { ...getToolActionInfo(recentInfo.name, toolInput), actionId: toolId };
|
|
1145
1152
|
// 更新状态
|
|
1146
1153
|
session.status = 'tool_using';
|
|
1147
1154
|
this.emit('status-change', sessionId, 'tool_using', {
|
|
1148
1155
|
actionType: actionInfo.actionType,
|
|
1149
1156
|
actionLabel: actionInfo.actionLabel,
|
|
1150
1157
|
actionDetail: actionInfo.actionDetail,
|
|
1158
|
+
actionId: actionInfo.actionId,
|
|
1151
1159
|
});
|
|
1152
1160
|
this.stopIdleDetection(sessionId);
|
|
1153
1161
|
// 发送工具调用开始事件(此时有完整参数)
|
|
@@ -1162,6 +1170,7 @@ export class ClaudeSdkAdapter extends EventEmitter {
|
|
|
1162
1170
|
actionType: actionInfo.actionType,
|
|
1163
1171
|
actionLabel: actionInfo.actionLabel,
|
|
1164
1172
|
actionDetail: actionInfo.actionDetail,
|
|
1173
|
+
actionId: actionInfo.actionId,
|
|
1165
1174
|
},
|
|
1166
1175
|
});
|
|
1167
1176
|
// 记录到消息历史
|
|
@@ -663,7 +663,7 @@ export class CodexSdkAdapter extends EventEmitter {
|
|
|
663
663
|
handleToolLikeItem(sessionId, session, item) {
|
|
664
664
|
if (!session.emittedToolStarts.has(item.id)) {
|
|
665
665
|
session.emittedToolStarts.add(item.id);
|
|
666
|
-
const actionInfo = getToolActionInfo(item.toolName, item.toolInput, item.metadata);
|
|
666
|
+
const actionInfo = { ...getToolActionInfo(item.toolName, item.toolInput, item.metadata), actionId: item.id };
|
|
667
667
|
this.emitEvent({
|
|
668
668
|
type: 'tool_use_start',
|
|
669
669
|
sessionId,
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* 参考:spectrai-community/src/main/adapter/OpenCodeSdkAdapter.ts
|
|
12
12
|
*/
|
|
13
13
|
import { EventEmitter } from 'node:events';
|
|
14
|
-
import type {
|
|
14
|
+
import type { AdapterSessionConfig, BaseProviderAdapter, ConversationMessage, SessionStatus } from './types.js';
|
|
15
15
|
export declare class OpencodeSdkAdapter extends EventEmitter implements BaseProviderAdapter {
|
|
16
16
|
readonly providerId = "opencode";
|
|
17
17
|
readonly displayName = "OpenCode";
|
|
@@ -39,6 +39,18 @@ export declare class OpencodeSdkAdapter extends EventEmitter implements BaseProv
|
|
|
39
39
|
*/
|
|
40
40
|
private loadSdk;
|
|
41
41
|
private waitForServer;
|
|
42
|
+
/**
|
|
43
|
+
* 记录 OpenCode serve 启动阶段输出,用于进程提前退出时返回可诊断错误。
|
|
44
|
+
*/
|
|
45
|
+
private recordStartupOutput;
|
|
46
|
+
/**
|
|
47
|
+
* 将 OpenCode serve 提前退出信息转成前端可直接展示的错误文本。
|
|
48
|
+
*/
|
|
49
|
+
private formatStartupExitMessage;
|
|
50
|
+
/**
|
|
51
|
+
* 异步投递启动提示,避免首轮 OpenCode 处理耗时导致 /runtime/start 被前端误判为启动失败。
|
|
52
|
+
*/
|
|
53
|
+
private dispatchInitialPrompt;
|
|
42
54
|
private startSseLoop;
|
|
43
55
|
private runSseLoop;
|
|
44
56
|
private handleOpenCodeEvent;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OpencodeSdkAdapter.d.ts","sourceRoot":"","sources":["../../src/adapter/OpencodeSdkAdapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;
|
|
1
|
+
{"version":3,"file":"OpencodeSdkAdapter.d.ts","sourceRoot":"","sources":["../../src/adapter/OpencodeSdkAdapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAc3C,OAAO,KAAK,EACV,oBAAoB,EAEpB,mBAAmB,EACnB,mBAAmB,EAEnB,aAAa,EACd,MAAM,YAAY,CAAC;AA4GpB,qBAAa,kBAAmB,SAAQ,YAAa,YAAW,mBAAmB;IACjF,QAAQ,CAAC,UAAU,cAAc;IACjC,QAAQ,CAAC,WAAW,cAAc;IAElC,OAAO,CAAC,QAAQ,CAA2C;IAC3D,OAAO,CAAC,SAAS,CAAC,CAAoB;IAEhC,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IA+I5E,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAwC9D,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBnE,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7F,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE;QAAE,gBAAgB,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAUnG,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAclD,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA4BxD,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,mBAAmB,EAAE;IAIzD,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAItC,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI3D,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAI9D,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAOpD,OAAO,IAAI,IAAI;IAaf;;;OAGG;YACW,OAAO;YA6BP,aAAa;IAmB3B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAO3B;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAahC;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAY7B,OAAO,CAAC,YAAY;YAYN,UAAU;IAuBxB,OAAO,CAAC,mBAAmB;IA6H3B,OAAO,CAAC,gBAAgB;IA6GxB,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,kBAAkB;IAW1B,OAAO,CAAC,iBAAiB;IAQzB,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,2BAA2B;CAOpC"}
|
|
@@ -132,11 +132,16 @@ export class OpencodeSdkAdapter extends EventEmitter {
|
|
|
132
132
|
shell: useShell,
|
|
133
133
|
});
|
|
134
134
|
session.serverProcess = proc;
|
|
135
|
+
session.startupOutput = [];
|
|
135
136
|
proc.stdout?.on('data', (d) => {
|
|
136
|
-
|
|
137
|
+
const text = d.toString();
|
|
138
|
+
this.recordStartupOutput(session, text);
|
|
139
|
+
console.debug(`[OpencodeSdkAdapter] serve stdout: ${text.slice(0, 200)}`);
|
|
137
140
|
});
|
|
138
141
|
proc.stderr?.on('data', (d) => {
|
|
139
|
-
|
|
142
|
+
const text = d.toString();
|
|
143
|
+
this.recordStartupOutput(session, text);
|
|
144
|
+
console.debug(`[OpencodeSdkAdapter] serve stderr: ${text.slice(0, 200)}`);
|
|
140
145
|
});
|
|
141
146
|
proc.on('error', (err) => {
|
|
142
147
|
console.error(`[OpencodeSdkAdapter] Server process error:`, err);
|
|
@@ -155,6 +160,9 @@ export class OpencodeSdkAdapter extends EventEmitter {
|
|
|
155
160
|
console.log(`[OpencodeSdkAdapter] Server exited with code ${code}`);
|
|
156
161
|
session.sseActive = false;
|
|
157
162
|
});
|
|
163
|
+
const exitDuringStartup = new Promise((resolve) => {
|
|
164
|
+
proc.once('exit', (code, signal) => resolve({ code, signal }));
|
|
165
|
+
});
|
|
158
166
|
// 步骤 3:创建 SDK 客户端
|
|
159
167
|
const sdk = await this.loadSdk();
|
|
160
168
|
const client = sdk.createOpencodeClient({
|
|
@@ -162,7 +170,12 @@ export class OpencodeSdkAdapter extends EventEmitter {
|
|
|
162
170
|
});
|
|
163
171
|
session.client = client;
|
|
164
172
|
// 步骤 4:等待服务器就绪
|
|
165
|
-
await
|
|
173
|
+
await Promise.race([
|
|
174
|
+
this.waitForServer(client, config.workingDirectory, 10_000, port),
|
|
175
|
+
exitDuringStartup.then((exitInfo) => {
|
|
176
|
+
throw new Error(this.formatStartupExitMessage(exitInfo, session.startupOutput));
|
|
177
|
+
}),
|
|
178
|
+
]);
|
|
166
179
|
console.log(`[OpencodeSdkAdapter] ★★★ OpenCode server ready ★★★ port=${port}`);
|
|
167
180
|
// 步骤 5:创建 OpenCode 会话
|
|
168
181
|
const createResult = await client.session.create({
|
|
@@ -182,7 +195,7 @@ export class OpencodeSdkAdapter extends EventEmitter {
|
|
|
182
195
|
this.emit('status-change', sessionId, 'waiting_input');
|
|
183
196
|
// 步骤 7:发送初始 Prompt
|
|
184
197
|
if (config.initialPrompt) {
|
|
185
|
-
|
|
198
|
+
this.dispatchInitialPrompt(sessionId, config.initialPrompt);
|
|
186
199
|
}
|
|
187
200
|
}
|
|
188
201
|
catch (err) {
|
|
@@ -264,6 +277,9 @@ export class OpencodeSdkAdapter extends EventEmitter {
|
|
|
264
277
|
const session = this.sessions.get(sessionId);
|
|
265
278
|
if (session) {
|
|
266
279
|
session.idleCommands = commands;
|
|
280
|
+
if (session.adapterSession.status === 'waiting_input' && (commands.idleInputCommand || commands.nonInputCommand)) {
|
|
281
|
+
this.startIdleDetection(sessionId);
|
|
282
|
+
}
|
|
267
283
|
}
|
|
268
284
|
}
|
|
269
285
|
async abortCurrentTurn(sessionId) {
|
|
@@ -382,6 +398,42 @@ export class OpencodeSdkAdapter extends EventEmitter {
|
|
|
382
398
|
}
|
|
383
399
|
throw new Error(`OpenCode server (port ${port}) did not start within ${timeoutMs}ms`);
|
|
384
400
|
}
|
|
401
|
+
/**
|
|
402
|
+
* 记录 OpenCode serve 启动阶段输出,用于进程提前退出时返回可诊断错误。
|
|
403
|
+
*/
|
|
404
|
+
recordStartupOutput(session, text) {
|
|
405
|
+
const normalized = text.trim();
|
|
406
|
+
if (!normalized)
|
|
407
|
+
return;
|
|
408
|
+
session.startupOutput = [...(session.startupOutput ?? []), normalized].slice(-8);
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* 将 OpenCode serve 提前退出信息转成前端可直接展示的错误文本。
|
|
412
|
+
*/
|
|
413
|
+
formatStartupExitMessage(exitInfo, startupOutput) {
|
|
414
|
+
const exitReason = exitInfo.signal
|
|
415
|
+
? `signal ${exitInfo.signal}`
|
|
416
|
+
: `code ${exitInfo.code ?? 'unknown'}`;
|
|
417
|
+
const output = (startupOutput ?? []).join('\n').trim();
|
|
418
|
+
if (!output) {
|
|
419
|
+
return `OpenCode server exited during startup (${exitReason}). Please check whether opencode serve can run in this workspace.`;
|
|
420
|
+
}
|
|
421
|
+
return `OpenCode server exited during startup (${exitReason}): ${output}`;
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* 异步投递启动提示,避免首轮 OpenCode 处理耗时导致 /runtime/start 被前端误判为启动失败。
|
|
425
|
+
*/
|
|
426
|
+
dispatchInitialPrompt(sessionId, initialPrompt) {
|
|
427
|
+
void this.sendMessage(sessionId, initialPrompt).catch((err) => {
|
|
428
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
429
|
+
this.emitEvent({
|
|
430
|
+
type: 'error',
|
|
431
|
+
sessionId,
|
|
432
|
+
timestamp: new Date().toISOString(),
|
|
433
|
+
data: { text: `OpenCode initial prompt failed: ${msg}` },
|
|
434
|
+
});
|
|
435
|
+
});
|
|
436
|
+
}
|
|
385
437
|
startSseLoop(sessionId, session) {
|
|
386
438
|
session.sseActive = true;
|
|
387
439
|
const ac = new AbortController();
|
|
@@ -578,7 +630,7 @@ export class OpencodeSdkAdapter extends EventEmitter {
|
|
|
578
630
|
if (session.emittedToolStarts.has(toolUseId))
|
|
579
631
|
return;
|
|
580
632
|
session.emittedToolStarts.add(toolUseId);
|
|
581
|
-
const actionInfo = getToolActionInfo(toolName, toolInput, metadata);
|
|
633
|
+
const actionInfo = { ...getToolActionInfo(toolName, toolInput, metadata), actionId: toolUseId };
|
|
582
634
|
this.emitEvent({
|
|
583
635
|
type: 'tool_use_start',
|
|
584
636
|
sessionId,
|
|
@@ -598,7 +650,7 @@ export class OpencodeSdkAdapter extends EventEmitter {
|
|
|
598
650
|
};
|
|
599
651
|
if (state.status === 'running') {
|
|
600
652
|
emitToolStart();
|
|
601
|
-
const actionInfo = getToolActionInfo(toolName, toolInput, metadata);
|
|
653
|
+
const actionInfo = { ...getToolActionInfo(toolName, toolInput, metadata), actionId: toolUseId };
|
|
602
654
|
this.emit('status-change', sessionId, 'tool_using', actionInfo);
|
|
603
655
|
}
|
|
604
656
|
else if (state.status === 'completed') {
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
1
|
+
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
2
2
|
import { OpencodeSdkAdapter } from './OpencodeSdkAdapter.js';
|
|
3
|
+
afterEach(() => {
|
|
4
|
+
vi.useRealTimers();
|
|
5
|
+
vi.restoreAllMocks();
|
|
6
|
+
});
|
|
3
7
|
describe('OpencodeSdkAdapter', () => {
|
|
4
8
|
it('should expose opencode provider identity', () => {
|
|
5
9
|
const adapter = new OpencodeSdkAdapter();
|
|
@@ -16,4 +20,56 @@ describe('OpencodeSdkAdapter', () => {
|
|
|
16
20
|
const prompt = Reflect.get(adapter, 'toIdlePrompt').call(adapter, 'system: 醒来了吗?使用get_profile获取自己的信息,继续未完成的任务或使用poll_message阻塞获取消息');
|
|
17
21
|
expect(prompt).toBe('请调用 poll_message 工具阻塞等待新消息;收到消息后再处理消息内容。');
|
|
18
22
|
});
|
|
23
|
+
it('starts idle detection when commands are set after OpenCode is already waiting for input', async () => {
|
|
24
|
+
vi.useFakeTimers();
|
|
25
|
+
const adapter = new OpencodeSdkAdapter();
|
|
26
|
+
const sentMessages = [];
|
|
27
|
+
Reflect.set(adapter, 'sessions', new Map([
|
|
28
|
+
[
|
|
29
|
+
'session-1',
|
|
30
|
+
{
|
|
31
|
+
adapterSession: {
|
|
32
|
+
sessionId: 'session-1',
|
|
33
|
+
status: 'waiting_input',
|
|
34
|
+
messages: [],
|
|
35
|
+
createdAt: new Date().toISOString(),
|
|
36
|
+
totalUsage: { inputTokens: 0, outputTokens: 0 },
|
|
37
|
+
},
|
|
38
|
+
config: {
|
|
39
|
+
command: 'opencode',
|
|
40
|
+
workingDirectory: process.cwd(),
|
|
41
|
+
autoAccept: true,
|
|
42
|
+
},
|
|
43
|
+
sseActive: false,
|
|
44
|
+
pendingPermissions: new Map(),
|
|
45
|
+
emittedToolStarts: new Set(),
|
|
46
|
+
workingDirectory: process.cwd(),
|
|
47
|
+
userMessageIds: new Set(),
|
|
48
|
+
currentAssistantText: '',
|
|
49
|
+
seenTextPartIds: new Set(),
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
]));
|
|
53
|
+
vi.spyOn(adapter, 'sendMessage').mockImplementation(async (_sessionId, message) => {
|
|
54
|
+
sentMessages.push(message);
|
|
55
|
+
});
|
|
56
|
+
adapter.setIdleCommands('session-1', {
|
|
57
|
+
idleInputCommand: 'system: 使用poll_message阻塞获取消息',
|
|
58
|
+
nonInputCommand: '',
|
|
59
|
+
});
|
|
60
|
+
await vi.advanceTimersByTimeAsync(500);
|
|
61
|
+
expect(sentMessages).toEqual(['请调用 poll_message 工具阻塞等待新消息;收到消息后再处理消息内容。']);
|
|
62
|
+
});
|
|
63
|
+
it('includes serve startup output when the OpenCode process exits early', () => {
|
|
64
|
+
const adapter = new OpencodeSdkAdapter();
|
|
65
|
+
const message = Reflect.get(adapter, 'formatStartupExitMessage').call(adapter, { code: 1, signal: null }, ['missing auth configuration']);
|
|
66
|
+
expect(message).toContain('OpenCode server exited during startup (code 1)');
|
|
67
|
+
expect(message).toContain('missing auth configuration');
|
|
68
|
+
});
|
|
69
|
+
it('dispatches the initial prompt asynchronously so launch can return after session creation', () => {
|
|
70
|
+
const adapter = new OpencodeSdkAdapter();
|
|
71
|
+
const sendMessage = vi.spyOn(adapter, 'sendMessage').mockResolvedValue(undefined);
|
|
72
|
+
Reflect.get(adapter, 'dispatchInitialPrompt').call(adapter, 'session-1', 'hello');
|
|
73
|
+
expect(sendMessage).toHaveBeenCalledWith('session-1', 'hello');
|
|
74
|
+
});
|
|
19
75
|
});
|
package/dist/adapter/types.d.ts
CHANGED
|
@@ -81,6 +81,10 @@ export interface ProviderEvent {
|
|
|
81
81
|
actionLabel?: string;
|
|
82
82
|
/** 工具动作详情(tool_use_start) */
|
|
83
83
|
actionDetail?: string;
|
|
84
|
+
/** 工具调用关联 ID(tool_use_start / tool_use_end) */
|
|
85
|
+
actionId?: string;
|
|
86
|
+
/** 工具返回数据(tool_use_end) */
|
|
87
|
+
actionResult?: string;
|
|
84
88
|
};
|
|
85
89
|
}
|
|
86
90
|
export interface AdapterSessionConfig {
|
|
@@ -230,6 +234,12 @@ export declare abstract class BaseProviderAdapter extends EventEmitter {
|
|
|
230
234
|
idleInputCommand: string;
|
|
231
235
|
nonInputCommand: string;
|
|
232
236
|
}): void;
|
|
237
|
+
/**
|
|
238
|
+
* 发送快捷键 token 序列(如 [enter]、[ctrl+c]),复用 SDK 输入流但不创建普通用户消息。
|
|
239
|
+
* @param sessionId 会话 ID
|
|
240
|
+
* @param command 快捷 token 文本
|
|
241
|
+
*/
|
|
242
|
+
abstract sendShortcutInput?(sessionId: string, command: string): Promise<void>;
|
|
233
243
|
/**
|
|
234
244
|
* 中止当前正在执行的轮次(软中断)
|
|
235
245
|
* 会话保持活跃,用户可继续发送新消息。
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/adapter/types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/adapter/types.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -21,8 +21,8 @@ import { gitRouter } from "./routes/git.js";
|
|
|
21
21
|
import { fileBrowserRouter } from "./routes/file-browser.js";
|
|
22
22
|
import { aiSourcesRouter } from "./routes/ai-sources.js";
|
|
23
23
|
import { processesRouter } from "./routes/processes.js";
|
|
24
|
+
import { attachPtyWebSocketServer, closeAllPtySessions, ptyRouter, ptySessions, } from "./routes/pty.js";
|
|
24
25
|
import { runtimeBindingRouter, logRuntimeBindingStartupState, } from "./routes/runtime-binding.js";
|
|
25
|
-
import { sessions, flushSessionOutput } from "./services/session-output.js";
|
|
26
26
|
import { loadPersistedSessions, savePersistedSessions, } from "./services/terminal-persistence.js";
|
|
27
27
|
import { detectOrphanProcesses } from "./services/process-detector.js";
|
|
28
28
|
import { startOrphanMonitor, stopOrphanMonitor, } from "./services/orphan-monitor.js";
|
|
@@ -124,7 +124,7 @@ async function rebuildProcessRegistry() {
|
|
|
124
124
|
pid: s.pid,
|
|
125
125
|
workspacePath: s.workspacePath,
|
|
126
126
|
command: s.command,
|
|
127
|
-
mode:
|
|
127
|
+
mode: "sdk",
|
|
128
128
|
})));
|
|
129
129
|
logger.info(`[runtime-bridge] 进程注册表重建完成: ${persistedSessions.length} 条记录`);
|
|
130
130
|
}
|
|
@@ -175,12 +175,11 @@ async function detectOrphansOnStartup() {
|
|
|
175
175
|
pid: s.pid,
|
|
176
176
|
workspacePath: s.workspacePath,
|
|
177
177
|
command: s.command,
|
|
178
|
-
mode:
|
|
178
|
+
mode: "sdk",
|
|
179
179
|
})));
|
|
180
180
|
return;
|
|
181
181
|
}
|
|
182
182
|
logger.info(`[runtime-bridge] ★ Bridge 重启,检测 ${persistedSessions.length} 个持久化会话的孤儿进程...`);
|
|
183
|
-
// ★★★ 修复:不再区分 SDK 和 PTY 模式,全部清理
|
|
184
183
|
// bridge 重启 = 整个运行环境重启,所有 agent 都应该被终止
|
|
185
184
|
const orphans = detectOrphanProcesses(persistedSessions.map((s) => ({
|
|
186
185
|
agentId: s.agentId,
|
|
@@ -264,6 +263,7 @@ app.use("/runtime", sessionsRouter);
|
|
|
264
263
|
app.use("/runtime", processesRouter);
|
|
265
264
|
app.use("/runtime", gitRouter);
|
|
266
265
|
app.use("/runtime", aiSourcesRouter);
|
|
266
|
+
app.use("/pty", ptyRouter);
|
|
267
267
|
app.use("/api/file-browser", fileBrowserRouter);
|
|
268
268
|
/**
|
|
269
269
|
* 启动 HTTP 服务并对端口占用给出可诊断错误,避免未捕获异常直接崩溃。
|
|
@@ -272,6 +272,7 @@ function startServer() {
|
|
|
272
272
|
const server = app.listen(port, () => {
|
|
273
273
|
logger.info(`[runtime-bridge] listening on ${port}`);
|
|
274
274
|
});
|
|
275
|
+
attachPtyWebSocketServer(server);
|
|
275
276
|
server.on("error", (error) => {
|
|
276
277
|
if (error.code === "EADDRINUSE") {
|
|
277
278
|
logger.error(`[runtime-bridge] port ${port} is already in use. ` +
|
|
@@ -288,11 +289,10 @@ function startServer() {
|
|
|
288
289
|
* 优雅关闭处理
|
|
289
290
|
*
|
|
290
291
|
* 在收到终止信号时:
|
|
291
|
-
* 1. 停止所有
|
|
292
|
-
* 2.
|
|
293
|
-
* 3.
|
|
294
|
-
* 4.
|
|
295
|
-
* 5. 关闭 HTTP 服务器
|
|
292
|
+
* 1. 停止所有 SDK 会话(终止 Agent 进程)
|
|
293
|
+
* 2. 验证所有进程已终止
|
|
294
|
+
* 3. 清空持久化状态(避免恢复残留会话)
|
|
295
|
+
* 4. 关闭 HTTP 服务器
|
|
296
296
|
*
|
|
297
297
|
* ★★★ 修复:添加 preserveSessions 参数
|
|
298
298
|
* - preserveSessions=true: aws-mcp-server 触发的关闭,保留会话状态
|
|
@@ -318,39 +318,7 @@ async function gracefulShutdown(signal, server, preserveSessions = false) {
|
|
|
318
318
|
logger.info(`[runtime-bridge] 收到 ${signal} 信号,开始优雅关闭... (preserveSessions=${preserveSessions})`);
|
|
319
319
|
const startTime = Date.now();
|
|
320
320
|
try {
|
|
321
|
-
// 1. 停止所有
|
|
322
|
-
const ptyCount = sessions.size;
|
|
323
|
-
logger.info(`[runtime-bridge] 正在停止 ${ptyCount} 个 PTY 会话...`);
|
|
324
|
-
for (const [sessionId, session] of sessions.entries()) {
|
|
325
|
-
try {
|
|
326
|
-
// 清理定时器
|
|
327
|
-
if (session.flushTimer) {
|
|
328
|
-
clearTimeout(session.flushTimer);
|
|
329
|
-
session.flushTimer = null;
|
|
330
|
-
}
|
|
331
|
-
// 刷新剩余输出
|
|
332
|
-
try {
|
|
333
|
-
await flushSessionOutput(sessionId);
|
|
334
|
-
}
|
|
335
|
-
catch {
|
|
336
|
-
// 忽略刷新错误
|
|
337
|
-
}
|
|
338
|
-
// 杀死 PTY 进程
|
|
339
|
-
try {
|
|
340
|
-
session.ptyProcess.kill();
|
|
341
|
-
logger.info(`[runtime-bridge] PTY 会话 ${sessionId} 已终止 (PID: ${session.ptyProcess.pid})`);
|
|
342
|
-
}
|
|
343
|
-
catch {
|
|
344
|
-
// 忽略终止错误
|
|
345
|
-
}
|
|
346
|
-
sessions.delete(sessionId);
|
|
347
|
-
}
|
|
348
|
-
catch (e) {
|
|
349
|
-
const err = e;
|
|
350
|
-
logger.error(`[runtime-bridge] PTY 会话 ${sessionId} 终止失败:`, err.message);
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
// 2. 停止所有 SDK 会话
|
|
321
|
+
// 1. 停止所有 SDK 会话
|
|
354
322
|
const sdkCount = sdkSessions.size;
|
|
355
323
|
logger.info(`[runtime-bridge] 正在停止 ${sdkCount} 个 SDK 会话...`);
|
|
356
324
|
for (const [sessionId, entry] of sdkSessions.entries()) {
|
|
@@ -379,6 +347,9 @@ async function gracefulShutdown(signal, server, preserveSessions = false) {
|
|
|
379
347
|
sdkSessions.delete(sessionId);
|
|
380
348
|
}
|
|
381
349
|
}
|
|
350
|
+
const ptyCount = ptySessions.size;
|
|
351
|
+
logger.info(`[runtime-bridge] 正在停止 ${ptyCount} 个 PTY 会话...`);
|
|
352
|
+
closeAllPtySessions("shutdown");
|
|
382
353
|
// 3. 停止孤儿进程监控
|
|
383
354
|
logger.info("[runtime-bridge] 正在停止孤儿进程监控...");
|
|
384
355
|
stopOrphanMonitor();
|
|
@@ -440,7 +411,7 @@ async function gracefulShutdown(signal, server, preserveSessions = false) {
|
|
|
440
411
|
}
|
|
441
412
|
// 8. 关闭 HTTP 服务器
|
|
442
413
|
const elapsed = Date.now() - startTime;
|
|
443
|
-
logger.info(`[runtime-bridge] 优雅关闭完成 (耗时 ${elapsed}ms),停止 ${
|
|
414
|
+
logger.info(`[runtime-bridge] 优雅关闭完成 (耗时 ${elapsed}ms),停止 ${sdkCount} SDK 会话`);
|
|
444
415
|
server.close(() => {
|
|
445
416
|
logger.info("[runtime-bridge] HTTP 服务器已关闭");
|
|
446
417
|
process.exit(0);
|
|
@@ -4,6 +4,11 @@
|
|
|
4
4
|
* 验证请求头中的 X-Runtime-Token 是否为已配对的 connectionKey 或 runtime binding token。
|
|
5
5
|
*/
|
|
6
6
|
import type { Request, Response, NextFunction } from "express";
|
|
7
|
+
/**
|
|
8
|
+
* 校验 runtime token。
|
|
9
|
+
* 主流程:复用 REST 中间件的 runtime binding token 与 connectionKey 校验逻辑,供 WebSocket upgrade 使用。
|
|
10
|
+
*/
|
|
11
|
+
export declare function isRuntimeTokenValid(token: unknown): boolean;
|
|
7
12
|
/**
|
|
8
13
|
* Token 验证中间件
|
|
9
14
|
* 检查请求头中的 X-Runtime-Token 或 Authorization: Bearer 是否有效。
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AA8B/D;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,QAAQ,EACb,IAAI,EAAE,YAAY,GACjB,IAAI,CAmBN"}
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AA8B/D;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAG3D;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,QAAQ,EACb,IAAI,EAAE,YAAY,GACjB,IAAI,CAmBN"}
|
package/dist/middleware/auth.js
CHANGED
|
@@ -23,6 +23,14 @@ function validateConfiguredToken(token) {
|
|
|
23
23
|
}
|
|
24
24
|
return false;
|
|
25
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* 校验 runtime token。
|
|
28
|
+
* 主流程:复用 REST 中间件的 runtime binding token 与 connectionKey 校验逻辑,供 WebSocket upgrade 使用。
|
|
29
|
+
*/
|
|
30
|
+
export function isRuntimeTokenValid(token) {
|
|
31
|
+
const normalized = String(token || "").trim();
|
|
32
|
+
return validateRuntimeBindingToken(normalized) || validateConfiguredToken(normalized);
|
|
33
|
+
}
|
|
26
34
|
/**
|
|
27
35
|
* Token 验证中间件
|
|
28
36
|
* 检查请求头中的 X-Runtime-Token 或 Authorization: Bearer 是否有效。
|
|
@@ -31,7 +39,7 @@ function validateConfiguredToken(token) {
|
|
|
31
39
|
*/
|
|
32
40
|
export function validateToken(req, res, next) {
|
|
33
41
|
const token = extractRuntimeToken(req);
|
|
34
|
-
if (
|
|
42
|
+
if (isRuntimeTokenValid(token)) {
|
|
35
43
|
next();
|
|
36
44
|
return;
|
|
37
45
|
}
|
|
@@ -3,5 +3,15 @@
|
|
|
3
3
|
*
|
|
4
4
|
* 提供文件系统浏览功能
|
|
5
5
|
*/
|
|
6
|
+
import multer from 'multer';
|
|
6
7
|
export declare const fileBrowserRouter: import("express-serve-static-core").Router;
|
|
8
|
+
export declare const WORKSPACE_UPLOAD_FILE_LIMIT = 2000;
|
|
9
|
+
export declare function createWorkspaceUploadLimitResponse(error: multer.MulterError): {
|
|
10
|
+
status: number;
|
|
11
|
+
body: {
|
|
12
|
+
error: string;
|
|
13
|
+
code: string;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
export declare function parseWorkspaceUploadRelativePaths(body: Record<string, unknown>): string[];
|
|
7
17
|
//# sourceMappingURL=file-browser.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-browser.d.ts","sourceRoot":"","sources":["../../src/routes/file-browser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"file-browser.d.ts","sourceRoot":"","sources":["../../src/routes/file-browser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,OAAO,MAAM,MAAM,QAAQ,CAAC;AAuB5B,eAAO,MAAM,iBAAiB,4CAAW,CAAC;AAE1C,eAAO,MAAM,2BAA2B,OAAO,CAAC;AAqChD,wBAAgB,kCAAkC,CAAC,KAAK,EAAE,MAAM,CAAC,WAAW,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAUvI;AAED,wBAAgB,iCAAiC,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,EAAE,CAgBzF"}
|