mirror of
https://github.com/aiclientproxy/proxycast.git
synced 2026-09-01 15:30:52 +08:00
Fix App Server bridge read timeout classification
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# Lime v1.125.0 发布执行计划
|
||||
|
||||
状态:release-git-confirmation-pending / windows-runner-pending
|
||||
状态:windows-gate-b-timeout-fix-in-progress
|
||||
日期:2026-08-09
|
||||
目标版本:`1.125.0`
|
||||
目标 tag:`v1.125.0`
|
||||
@@ -191,3 +191,16 @@
|
||||
- 本地验证:`cargo test --manifest-path lime-rs/Cargo.toml -p app-server plugin_uninstall_invalidates_mcp_runtimes_before_removing_package` 通过;`npm run test:rust:related -- lime-rs/crates/app-server/src/runtime.rs lime-rs/crates/app-server/src/runtime/plugins.rs lime-rs/crates/app-server/src/runtime_backend/execution_backend.rs lime-rs/crates/app-server/src/runtime/tests/plugins.rs` 通过,`app-server` lib `1642 passed / 0 failed`;`cargo fmt --all -- --check` 与 `git diff --check` 通过。
|
||||
- `npm run typecheck`、`npm run test:contracts`、`npm run verify:app-version`、`npm run verify:gui-smoke` 均通过。真实 macOS packaged Plugin Gate B 通过:`ok=true`、卸载/installed projection/history recovery 全部通过、MCP App resource/HTML `4/4`、provider request `2`、`productionMockFallbackHitCount=0`、`missingRequiredMethods=[]`。
|
||||
- 当前状态:`fix-validated-locally / release-git-confirmation-pending / windows-runner-pending`;下一步获得危险 Git 写操作确认后提交并推送窄修复,以新完整 SHA 重跑 Windows runner,不移动已发布 `v1.125.0` tag。
|
||||
|
||||
## Windows runner `31422354829`
|
||||
|
||||
状态:`bridge-timeout-fix-in-progress / windows-runner-pending`
|
||||
|
||||
- 使用完整 SHA `cd5bc4eae8211a2f4bdc1a7843b310618df18dc4`;Windows Plugin path contract、sherpa runtime、Electron Windows x64 Squirrel package、N-1 installer download 与 installed Squirrel smoke 全部通过。上一轮 `os error 32` 未复现,但 Gate B 在 reload 后的 session hydration 阶段失败,尚未执行到卸载。
|
||||
- 失败 evidence 已证明首次 MCP App surface、`mcpServer/resource/read`、HTML load、reload 后 canonical MCP item/plugin/resource URI 均正确;直接错误是 `thread/items/list` 经 `app_server_handle_json_lines` 在 5000ms 内未返回,Renderer fail closed 后主内容与 App surface 消失。
|
||||
- 根因:`commandPolicy.ts` 用手工 `APP_SERVER_CURRENT_METHODS` 同步 JSON-RPC method,漏掉 `thread/items/list` 与 `thread/turns/list`,导致新 read method 退回普通 truth 命令的 5 秒超时。该集合是 App Server protocol 之外的重复事实源。
|
||||
- 修复:保留 `turn/start`、conversation import、startup、knowledge compile、long-running 与 provider network 专项 profile;专项匹配后,所有 `app_server_handle_json_lines` 统一使用 `app-server-read` 的 30 秒窗口。删除手工 current method catalog 及判断 helper;method 合法性继续由 App Server protocol/handler fail closed,不由 bridge timeout policy 承担。
|
||||
- 窄写集:`src/lib/dev-bridge/commandPolicy.ts`、`src/lib/dev-bridge/commandPolicy.test.ts` 与本计划;不触碰并发架构、命令文档、projection drift 和治理 fixture 改动。
|
||||
- 本地验证:commandPolicy Vitest `11 passed / 0 failed`;定向 ESLint、`npm run typecheck`、`npm run test:contracts`、`npm run verify:app-version`、`npm run verify:gui-smoke` 与 `git diff --check` 均通过。GUI evidence:`standalone-shell-01-20260810194309-62252`。
|
||||
- 本机真实 packaged Plugin Gate B 通过:summary `ok=true`、provider request `2`、provider final text、MCP App 首次/reload/cold restore、App Center 卸载、installed projection 清理、卸载后历史恢复全部通过,`productionMockFallbackHitCount=0`、`missingRequiredMethods=[]`。
|
||||
- 退出条件:定向回归覆盖 `thread/items/list`、`thread/turns/list` 和未来 App Server method 均归 `app-server-read`;typecheck、contracts、GUI smoke 与本机真实 Electron Plugin Gate B 通过;随后提交并推送新完整 SHA,重新跟踪 Windows Gate B 到卸载、installed projection 清理与历史恢复全部通过。`v1.125.0` tag 保持不动。
|
||||
|
||||
@@ -440,6 +440,35 @@ describe("commandPolicy", () => {
|
||||
},
|
||||
}),
|
||||
).toBe("app-server-read");
|
||||
for (const method of [
|
||||
"thread/items/list",
|
||||
"thread/turns/list",
|
||||
"futureDomain/futureMethod",
|
||||
]) {
|
||||
expect(
|
||||
resolveDevBridgeCommandTimeoutProfile("app_server_handle_json_lines", {
|
||||
request: {
|
||||
lines: [JSON.stringify({ id: `read-${method}`, method, params: {} })],
|
||||
},
|
||||
}),
|
||||
).toBe("app-server-read");
|
||||
}
|
||||
for (const method of [
|
||||
"pluginLocalPackage/inspect",
|
||||
"pluginLocalPackage/export",
|
||||
"pluginInstalled/save",
|
||||
"pluginUiRuntime/start",
|
||||
]) {
|
||||
expect(
|
||||
resolveDevBridgeCommandTimeoutProfile("app_server_handle_json_lines", {
|
||||
request: {
|
||||
lines: [
|
||||
JSON.stringify({ id: `retired-${method}`, method, params: {} }),
|
||||
],
|
||||
},
|
||||
}),
|
||||
).toBe("app-server-read");
|
||||
}
|
||||
expect(
|
||||
resolveDevBridgeCommandTimeoutProfile("app_server_handle_json_lines", {
|
||||
request: {
|
||||
@@ -501,22 +530,6 @@ describe("commandPolicy", () => {
|
||||
}),
|
||||
).toBe("app-server-read");
|
||||
}
|
||||
for (const method of [
|
||||
"pluginLocalPackage/inspect",
|
||||
"pluginLocalPackage/export",
|
||||
"pluginInstalled/save",
|
||||
"pluginUiRuntime/start",
|
||||
]) {
|
||||
expect(
|
||||
resolveDevBridgeCommandTimeoutProfile("app_server_handle_json_lines", {
|
||||
request: {
|
||||
lines: [
|
||||
JSON.stringify({ id: `retired-${method}`, method, params: {} }),
|
||||
],
|
||||
},
|
||||
}),
|
||||
).toBe("truth");
|
||||
}
|
||||
expect(
|
||||
resolveDevBridgeCommandTimeoutProfile("app_server_handle_json_lines", {
|
||||
request: {
|
||||
|
||||
@@ -99,163 +99,6 @@ const APP_SERVER_PROVIDER_NETWORK_METHODS = new Set([
|
||||
"modelProvider/testChat",
|
||||
"modelProvider/fetchModels",
|
||||
]);
|
||||
const APP_SERVER_MODEL_CONTROL_METHODS = new Set([
|
||||
"modelProvider/list",
|
||||
"modelProvider/catalog/list",
|
||||
"modelProvider/read",
|
||||
"modelProvider/create",
|
||||
"modelProvider/update",
|
||||
"modelProvider/delete",
|
||||
"modelProvider/sortOrders/update",
|
||||
"modelProviderConfig/export",
|
||||
"modelProviderConfig/import",
|
||||
...APP_SERVER_PROVIDER_NETWORK_METHODS,
|
||||
"modelProviderKey/create",
|
||||
"modelProviderKey/update",
|
||||
"modelProviderKey/delete",
|
||||
"modelProviderUiState/read",
|
||||
"modelProviderUiState/write",
|
||||
"modelProviderAlias/read",
|
||||
"modelProviderAlias/list",
|
||||
]);
|
||||
const APP_SERVER_CURRENT_METHODS = new Set([
|
||||
"capability/list",
|
||||
"artifact/read",
|
||||
"fs/readFile",
|
||||
"fs/writeFile",
|
||||
"fs/createDirectory",
|
||||
"fs/getMetadata",
|
||||
"fs/readDirectory",
|
||||
"fs/remove",
|
||||
"fs/copy",
|
||||
"fs/watch",
|
||||
"fs/unwatch",
|
||||
"thread/start",
|
||||
"thread/read",
|
||||
"workflow/read",
|
||||
"workflow/cancel",
|
||||
"workflow/retry",
|
||||
"workflow/respond",
|
||||
"thread/settings/update",
|
||||
"thread/archive",
|
||||
"thread/unarchive",
|
||||
"skills/list",
|
||||
"skill/read",
|
||||
"skillManagement/list",
|
||||
"skillManagement/install",
|
||||
"skillManagement/uninstall",
|
||||
"skillRepository/list",
|
||||
"skillRepository/save",
|
||||
"skillRepository/delete",
|
||||
"skillCache/refresh",
|
||||
"skillInstalledDirectories/list",
|
||||
"skillLocal/inspect",
|
||||
"skillLocal/scaffold/create",
|
||||
"skillLocal/import",
|
||||
"skillRemote/inspect",
|
||||
"workspaceSkillBindings/list",
|
||||
"workspaceRegisteredSkills/list",
|
||||
"plugin/list",
|
||||
"plugin/search",
|
||||
"plugin/read",
|
||||
"plugin/install",
|
||||
"plugin/uninstall",
|
||||
"plugin/installed",
|
||||
"plugin/enabled/set",
|
||||
"knowledgePack/list",
|
||||
"knowledgePack/read",
|
||||
"knowledgePack/source/import",
|
||||
"knowledgePack/compile",
|
||||
"knowledgePack/default/set",
|
||||
"knowledgePack/status/update",
|
||||
"knowledgeContext/resolve",
|
||||
"knowledgeContextRun/validate",
|
||||
"automationScheduler/config/read",
|
||||
"automationScheduler/config/update",
|
||||
"automationScheduler/status",
|
||||
"automationJob/list",
|
||||
"automationJob/read",
|
||||
"automationJob/create",
|
||||
"automationJob/update",
|
||||
"automationJob/delete",
|
||||
"automationJob/runNow",
|
||||
"automationJob/health",
|
||||
"automationJob/runHistory",
|
||||
"automationSchedule/preview",
|
||||
"automationSchedule/validate",
|
||||
"projectMemory/read",
|
||||
"gatewayChannel/status",
|
||||
"wechatChannel/accounts/list",
|
||||
"mediaTaskArtifact/image/create",
|
||||
"mediaTaskArtifact/audio/create",
|
||||
"mediaTaskArtifact/image/complete",
|
||||
"mediaTaskArtifact/audio/complete",
|
||||
"mediaTaskArtifact/get",
|
||||
"mediaTaskArtifact/list",
|
||||
"mediaTaskArtifact/cancel",
|
||||
"workspaceRightSurface/request",
|
||||
"workspaceRightSurface/pending/list",
|
||||
"workspaceRightSurface/pending/consume",
|
||||
"workspaceRightSurface/pending/dismiss",
|
||||
"sessionFile/getOrCreate",
|
||||
"sessionFile/updateMeta",
|
||||
"sessionFile/save",
|
||||
"sessionFile/list",
|
||||
"sessionFile/read",
|
||||
"sessionFile/resolvePath",
|
||||
"sessionFile/delete",
|
||||
"collaborationMode/list",
|
||||
"model/list",
|
||||
"modelPreferences/list",
|
||||
"modelSyncState/read",
|
||||
...APP_SERVER_MODEL_CONTROL_METHODS,
|
||||
"mcpServer/list",
|
||||
"mcpServerStatus/list",
|
||||
"mcpServer/create",
|
||||
"mcpServer/update",
|
||||
"mcpServer/delete",
|
||||
"mcpServer/enabled/set",
|
||||
"mcpServer/importFromApp",
|
||||
"mcpServer/syncAllToLive",
|
||||
"mcpServer/oauth/login",
|
||||
"mcpServer/start",
|
||||
"mcpServer/stop",
|
||||
"mcpServer/resource/read",
|
||||
"mcpServer/tool/call",
|
||||
"mcpTool/list",
|
||||
"mcpTool/listForContext",
|
||||
"mcpTool/search",
|
||||
"mcpPrompt/list",
|
||||
"mcpPrompt/get",
|
||||
"mcpResource/list",
|
||||
"mcpResource/subscribe",
|
||||
"mcpResource/unsubscribe",
|
||||
"connectDeepLink/resolve",
|
||||
"connectOpenDeepLink/resolve",
|
||||
"voiceAsrCredential/list",
|
||||
"voiceAsrCredential/create",
|
||||
"voiceAsrCredential/update",
|
||||
"voiceAsrCredential/delete",
|
||||
"voiceAsrCredential/default/set",
|
||||
"voiceAsrCredential/test",
|
||||
"voiceInstruction/list",
|
||||
"voiceInstruction/save",
|
||||
"voiceInstruction/delete",
|
||||
"voiceModel/default/set",
|
||||
"voiceModel/testTranscribeFile",
|
||||
"voiceTranscription/transcribeAudio",
|
||||
"voiceTranscription/polishText",
|
||||
"conversationImport/source/scan",
|
||||
"conversationImport/job/read",
|
||||
"conversationImport/thread/preview",
|
||||
"conversationImport/thread/commit",
|
||||
"projectGit/status",
|
||||
"projectGit/diff",
|
||||
"projectGit/commits/list",
|
||||
"projectGit/branch/checkout",
|
||||
"projectGit/branch/create",
|
||||
"projectGit/worktree/create",
|
||||
]);
|
||||
const APP_SERVER_STARTUP_TRUTH_METHODS = new Set([
|
||||
"workspace/default/read",
|
||||
"workspace/default/ensure",
|
||||
@@ -351,7 +194,7 @@ export function resolveDevBridgeCommandTimeoutProfile(
|
||||
if (isAppServerProviderNetworkCommand(command, args)) {
|
||||
return "app-server-provider-network";
|
||||
}
|
||||
if (isAppServerCurrentMethodCommand(command, args)) {
|
||||
if (command === APP_SERVER_HANDLE_JSON_LINES_COMMAND) {
|
||||
return "app-server-read";
|
||||
}
|
||||
if (command === APP_SERVER_DRAIN_EVENTS_COMMAND) {
|
||||
@@ -435,18 +278,6 @@ function isAppServerLongRunningCommand(
|
||||
);
|
||||
}
|
||||
|
||||
function isAppServerCurrentMethodCommand(
|
||||
command: string,
|
||||
args: unknown,
|
||||
): boolean {
|
||||
if (command !== APP_SERVER_HANDLE_JSON_LINES_COMMAND) {
|
||||
return false;
|
||||
}
|
||||
return extractAppServerJsonLines(args).some((line) =>
|
||||
jsonRpcLineHasAnyMethod(line, APP_SERVER_CURRENT_METHODS),
|
||||
);
|
||||
}
|
||||
|
||||
function isAppServerProviderNetworkCommand(
|
||||
command: string,
|
||||
args: unknown,
|
||||
|
||||
Reference in New Issue
Block a user