@ccpocket/bridge 1.76.0 → 1.78.0
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/dist/git-operations.d.ts +2 -0
- package/dist/git-operations.js +107 -15
- package/dist/git-operations.js.map +1 -1
- package/dist/parser.d.ts +75 -0
- package/dist/parser.js +8 -2
- package/dist/parser.js.map +1 -1
- package/dist/websocket.js +356 -60
- package/dist/websocket.js.map +1 -1
- package/package.json +1 -1
package/dist/websocket.js
CHANGED
|
@@ -27,6 +27,12 @@ import { getPackageVersion } from "./version.js";
|
|
|
27
27
|
import { isPathWithinAllowedDirectory, resolvePlatformPath, resolvePlatformPathFrom, } from "./path-utils.js";
|
|
28
28
|
import { DirectoryListingError, listAllowedDirectories, } from "./directory-listing.js";
|
|
29
29
|
import { deriveCodexPermissionsMode, normalizeCodexPermissionsMode, withDerivedCodexPermissionsMode, } from "./codex-permissions.js";
|
|
30
|
+
function projectRequestMetadata(request) {
|
|
31
|
+
return {
|
|
32
|
+
projectPath: request.projectPath,
|
|
33
|
+
...(request.requestId ? { requestId: request.requestId } : {}),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
30
36
|
const RESUME_OPERATION_TIMEOUT_MS = 5 * 60 * 1000;
|
|
31
37
|
const RESUME_COMPLETED_TTL_MS = 30 * 1000;
|
|
32
38
|
// ---- Available model lists (delivered to clients via session_list) ----
|
|
@@ -792,11 +798,13 @@ export class BridgeWebSocketServer {
|
|
|
792
798
|
}
|
|
793
799
|
}
|
|
794
800
|
/** Build a user-friendly error for disallowed project paths. */
|
|
795
|
-
buildPathNotAllowedError(projectPath) {
|
|
801
|
+
buildPathNotAllowedError(projectPath, requestId) {
|
|
796
802
|
return {
|
|
797
803
|
type: "error",
|
|
798
804
|
message: `⚠ Project path not allowed\n\n"${projectPath}" is not in the allowed directories.\n\nFix: Update BRIDGE_ALLOWED_DIRS on the Bridge server to include this path.`,
|
|
799
805
|
errorCode: "path_not_allowed",
|
|
806
|
+
path: projectPath,
|
|
807
|
+
requestId,
|
|
800
808
|
};
|
|
801
809
|
}
|
|
802
810
|
sendToolActionError(ws, message, error) {
|
|
@@ -827,7 +835,7 @@ export class BridgeWebSocketServer {
|
|
|
827
835
|
return { roots: [...normalized.values()] };
|
|
828
836
|
}
|
|
829
837
|
buildSessionCreatedMessage(params) {
|
|
830
|
-
const { sessionId, provider, projectPath, session, permissionMode, executionMode, planMode, approvalsReviewer, codexPermissionsMode, sandboxMode, slashCommands, skills, skillMetadata, apps, appMetadata, plugins, pluginMetadata, sourceSessionId, resumeRequestId, } = params;
|
|
838
|
+
const { sessionId, provider, projectPath, session, permissionMode, executionMode, planMode, approvalsReviewer, codexPermissionsMode, sandboxMode, slashCommands, skills, skillMetadata, apps, appMetadata, plugins, pluginMetadata, sourceSessionId, resumeRequestId, requestId, } = params;
|
|
831
839
|
const derivedCodexSettings = provider === "codex"
|
|
832
840
|
? withDerivedCodexPermissionsMode(session?.codexSettings)
|
|
833
841
|
: session?.codexSettings;
|
|
@@ -923,6 +931,7 @@ export class BridgeWebSocketServer {
|
|
|
923
931
|
: {}),
|
|
924
932
|
...(sourceSessionId ? { sourceSessionId } : {}),
|
|
925
933
|
...(resumeRequestId ? { resumeRequestId } : {}),
|
|
934
|
+
...(requestId ? { requestId } : {}),
|
|
926
935
|
};
|
|
927
936
|
if (provider === "codex" && derivedCodexSettings) {
|
|
928
937
|
if (derivedCodexSettings.model !== undefined) {
|
|
@@ -957,6 +966,7 @@ export class BridgeWebSocketServer {
|
|
|
957
966
|
if (mode !== "conversation") {
|
|
958
967
|
this.send(ws, {
|
|
959
968
|
type: "rewind_result",
|
|
969
|
+
sessionId,
|
|
960
970
|
success: false,
|
|
961
971
|
mode,
|
|
962
972
|
error: "Codex only supports conversation rewind",
|
|
@@ -967,6 +977,7 @@ export class BridgeWebSocketServer {
|
|
|
967
977
|
if (!session) {
|
|
968
978
|
this.send(ws, {
|
|
969
979
|
type: "rewind_result",
|
|
980
|
+
sessionId,
|
|
970
981
|
success: false,
|
|
971
982
|
mode,
|
|
972
983
|
error: `Session ${sessionId} not found`,
|
|
@@ -978,6 +989,7 @@ export class BridgeWebSocketServer {
|
|
|
978
989
|
typeof codexProcess.rollbackThread !== "function") {
|
|
979
990
|
this.send(ws, {
|
|
980
991
|
type: "rewind_result",
|
|
992
|
+
sessionId,
|
|
981
993
|
success: false,
|
|
982
994
|
mode,
|
|
983
995
|
error: "Session is not a Codex session",
|
|
@@ -987,6 +999,7 @@ export class BridgeWebSocketServer {
|
|
|
987
999
|
if (session.status !== "idle" || (codexProcess.status ?? session.status) !== "idle") {
|
|
988
1000
|
this.send(ws, {
|
|
989
1001
|
type: "rewind_result",
|
|
1002
|
+
sessionId,
|
|
990
1003
|
success: false,
|
|
991
1004
|
mode,
|
|
992
1005
|
error: "Cannot rewind while Codex is running",
|
|
@@ -996,6 +1009,7 @@ export class BridgeWebSocketServer {
|
|
|
996
1009
|
if (session.codexQueuedInput) {
|
|
997
1010
|
this.send(ws, {
|
|
998
1011
|
type: "rewind_result",
|
|
1012
|
+
sessionId,
|
|
999
1013
|
success: false,
|
|
1000
1014
|
mode,
|
|
1001
1015
|
error: "Cannot rewind while Codex has queued input",
|
|
@@ -1007,6 +1021,7 @@ export class BridgeWebSocketServer {
|
|
|
1007
1021
|
if (targetOrdinal === null || targetOrdinal > totalUserTurns) {
|
|
1008
1022
|
this.send(ws, {
|
|
1009
1023
|
type: "rewind_result",
|
|
1024
|
+
sessionId,
|
|
1010
1025
|
success: false,
|
|
1011
1026
|
mode,
|
|
1012
1027
|
error: "Invalid Codex rewind target",
|
|
@@ -1017,6 +1032,7 @@ export class BridgeWebSocketServer {
|
|
|
1017
1032
|
if (numTurns <= 0) {
|
|
1018
1033
|
this.send(ws, {
|
|
1019
1034
|
type: "rewind_result",
|
|
1035
|
+
sessionId,
|
|
1020
1036
|
success: false,
|
|
1021
1037
|
mode,
|
|
1022
1038
|
error: "Invalid Codex rewind target",
|
|
@@ -1027,6 +1043,7 @@ export class BridgeWebSocketServer {
|
|
|
1027
1043
|
if (!threadId) {
|
|
1028
1044
|
this.send(ws, {
|
|
1029
1045
|
type: "rewind_result",
|
|
1046
|
+
sessionId,
|
|
1030
1047
|
success: false,
|
|
1031
1048
|
mode,
|
|
1032
1049
|
error: "No Codex thread ID available for rewind",
|
|
@@ -1055,6 +1072,7 @@ export class BridgeWebSocketServer {
|
|
|
1055
1072
|
const newSession = this.sessionManager.get(newSessionId);
|
|
1056
1073
|
this.send(ws, {
|
|
1057
1074
|
type: "rewind_result",
|
|
1075
|
+
sessionId,
|
|
1058
1076
|
success: true,
|
|
1059
1077
|
mode,
|
|
1060
1078
|
});
|
|
@@ -1888,7 +1906,11 @@ export class BridgeWebSocketServer {
|
|
|
1888
1906
|
case "start": {
|
|
1889
1907
|
const projectPath = resolvePlatformPath(msg.projectPath, this.platform);
|
|
1890
1908
|
if (!this.isPathAllowed(projectPath)) {
|
|
1891
|
-
this.send(ws,
|
|
1909
|
+
this.send(ws, {
|
|
1910
|
+
...this.buildPathNotAllowedError(msg.projectPath),
|
|
1911
|
+
requestId: msg.requestId,
|
|
1912
|
+
path: msg.projectPath,
|
|
1913
|
+
});
|
|
1892
1914
|
break;
|
|
1893
1915
|
}
|
|
1894
1916
|
try {
|
|
@@ -1933,6 +1955,8 @@ export class BridgeWebSocketServer {
|
|
|
1933
1955
|
!(await this.validateCodexProfile(msg.profile, projectPath))) {
|
|
1934
1956
|
this.send(ws, {
|
|
1935
1957
|
type: "error",
|
|
1958
|
+
requestId: msg.requestId,
|
|
1959
|
+
path: projectPath,
|
|
1936
1960
|
message: `Codex profile not found: ${msg.profile}`,
|
|
1937
1961
|
});
|
|
1938
1962
|
break;
|
|
@@ -1942,7 +1966,11 @@ export class BridgeWebSocketServer {
|
|
|
1942
1966
|
? this.normalizeAdditionalWritableRoots(msg.additionalWritableRoots, projectPath)
|
|
1943
1967
|
: {};
|
|
1944
1968
|
if (additionalWritableRoots.deniedRoot) {
|
|
1945
|
-
this.send(ws,
|
|
1969
|
+
this.send(ws, {
|
|
1970
|
+
...this.buildPathNotAllowedError(additionalWritableRoots.deniedRoot),
|
|
1971
|
+
requestId: msg.requestId,
|
|
1972
|
+
path: projectPath,
|
|
1973
|
+
});
|
|
1946
1974
|
break;
|
|
1947
1975
|
}
|
|
1948
1976
|
const { sessionId, permissionMode: effectivePermissionMode, executionMode: effectiveExecutionMode, planMode: effectivePlanMode, usedFallback: autoFallbackUsed, } = provider === "claude"
|
|
@@ -2028,6 +2056,7 @@ export class BridgeWebSocketServer {
|
|
|
2028
2056
|
: msg.sandboxMode,
|
|
2029
2057
|
codexPermissionsMode: createdSession?.codexSettings?.codexPermissionsMode,
|
|
2030
2058
|
approvalsReviewer: createdSession?.codexSettings?.approvalsReviewer,
|
|
2059
|
+
requestId: msg.requestId,
|
|
2031
2060
|
...(cached
|
|
2032
2061
|
? {
|
|
2033
2062
|
slashCommands: cached.slashCommands,
|
|
@@ -2079,6 +2108,8 @@ export class BridgeWebSocketServer {
|
|
|
2079
2108
|
console.error(`[ws] Failed to start session:`, err);
|
|
2080
2109
|
this.send(ws, {
|
|
2081
2110
|
type: "error",
|
|
2111
|
+
requestId: msg.requestId,
|
|
2112
|
+
path: msg.projectPath,
|
|
2082
2113
|
message: `Failed to start session: ${err.message}`,
|
|
2083
2114
|
});
|
|
2084
2115
|
}
|
|
@@ -2096,6 +2127,7 @@ export class BridgeWebSocketServer {
|
|
|
2096
2127
|
}
|
|
2097
2128
|
this.send(ws, {
|
|
2098
2129
|
type: "error",
|
|
2130
|
+
sessionId: msg.sessionId,
|
|
2099
2131
|
message: "No active session. Send 'start' first.",
|
|
2100
2132
|
});
|
|
2101
2133
|
return;
|
|
@@ -2409,12 +2441,17 @@ export class BridgeWebSocketServer {
|
|
|
2409
2441
|
case "update_queued_input": {
|
|
2410
2442
|
const session = this.resolveSession(msg.sessionId);
|
|
2411
2443
|
if (!session || session.provider !== "codex") {
|
|
2412
|
-
this.send(ws, {
|
|
2444
|
+
this.send(ws, {
|
|
2445
|
+
type: "error",
|
|
2446
|
+
sessionId: msg.sessionId,
|
|
2447
|
+
message: "No active Codex session.",
|
|
2448
|
+
});
|
|
2413
2449
|
return;
|
|
2414
2450
|
}
|
|
2415
2451
|
if (!msg.text.trim()) {
|
|
2416
2452
|
this.send(ws, {
|
|
2417
2453
|
type: "error",
|
|
2454
|
+
sessionId: msg.sessionId,
|
|
2418
2455
|
message: "Queued message cannot be empty.",
|
|
2419
2456
|
});
|
|
2420
2457
|
return;
|
|
@@ -2423,6 +2460,7 @@ export class BridgeWebSocketServer {
|
|
|
2423
2460
|
if (!success) {
|
|
2424
2461
|
this.send(ws, {
|
|
2425
2462
|
type: "error",
|
|
2463
|
+
sessionId: msg.sessionId,
|
|
2426
2464
|
message: "Queued message not found.",
|
|
2427
2465
|
errorCode: "queued_input_not_found",
|
|
2428
2466
|
});
|
|
@@ -2434,13 +2472,18 @@ export class BridgeWebSocketServer {
|
|
|
2434
2472
|
case "cancel_queued_input": {
|
|
2435
2473
|
const session = this.resolveSession(msg.sessionId);
|
|
2436
2474
|
if (!session || session.provider !== "codex") {
|
|
2437
|
-
this.send(ws, {
|
|
2475
|
+
this.send(ws, {
|
|
2476
|
+
type: "error",
|
|
2477
|
+
sessionId: msg.sessionId,
|
|
2478
|
+
message: "No active Codex session.",
|
|
2479
|
+
});
|
|
2438
2480
|
return;
|
|
2439
2481
|
}
|
|
2440
2482
|
const success = this.sessionManager.cancelCodexQueuedInput(session.id, msg.itemId);
|
|
2441
2483
|
if (!success) {
|
|
2442
2484
|
this.send(ws, {
|
|
2443
2485
|
type: "error",
|
|
2486
|
+
sessionId: msg.sessionId,
|
|
2444
2487
|
message: "Queued message not found.",
|
|
2445
2488
|
errorCode: "queued_input_not_found",
|
|
2446
2489
|
});
|
|
@@ -2452,13 +2495,18 @@ export class BridgeWebSocketServer {
|
|
|
2452
2495
|
case "steer_queued_input": {
|
|
2453
2496
|
const session = this.resolveSession(msg.sessionId);
|
|
2454
2497
|
if (!session || session.provider !== "codex") {
|
|
2455
|
-
this.send(ws, {
|
|
2498
|
+
this.send(ws, {
|
|
2499
|
+
type: "error",
|
|
2500
|
+
sessionId: msg.sessionId,
|
|
2501
|
+
message: "No active Codex session.",
|
|
2502
|
+
});
|
|
2456
2503
|
return;
|
|
2457
2504
|
}
|
|
2458
2505
|
const result = await this.sessionManager.steerCodexQueuedInput(session.id, msg.itemId);
|
|
2459
2506
|
if (!result.ok) {
|
|
2460
2507
|
this.send(ws, {
|
|
2461
2508
|
type: "error",
|
|
2509
|
+
sessionId: msg.sessionId,
|
|
2462
2510
|
message: result.error,
|
|
2463
2511
|
errorCode: result.error === "Queued message not found."
|
|
2464
2512
|
? "queued_input_not_found"
|
|
@@ -2559,6 +2607,7 @@ export class BridgeWebSocketServer {
|
|
|
2559
2607
|
if (this.failSetPermissionMode) {
|
|
2560
2608
|
this.send(ws, {
|
|
2561
2609
|
type: "error",
|
|
2610
|
+
sessionId: msg.sessionId,
|
|
2562
2611
|
message: "Failed to set permission mode: forced test failure",
|
|
2563
2612
|
errorCode: "set_permission_mode_rejected",
|
|
2564
2613
|
});
|
|
@@ -2566,7 +2615,11 @@ export class BridgeWebSocketServer {
|
|
|
2566
2615
|
}
|
|
2567
2616
|
const session = this.resolveSession(msg.sessionId);
|
|
2568
2617
|
if (!session) {
|
|
2569
|
-
this.send(ws, {
|
|
2618
|
+
this.send(ws, {
|
|
2619
|
+
type: "error",
|
|
2620
|
+
sessionId: msg.sessionId,
|
|
2621
|
+
message: "No active session.",
|
|
2622
|
+
});
|
|
2570
2623
|
return;
|
|
2571
2624
|
}
|
|
2572
2625
|
if (session.provider === "codex") {
|
|
@@ -2816,6 +2869,7 @@ export class BridgeWebSocketServer {
|
|
|
2816
2869
|
.catch((err) => {
|
|
2817
2870
|
this.send(ws, {
|
|
2818
2871
|
type: "error",
|
|
2872
|
+
sessionId: msg.sessionId,
|
|
2819
2873
|
message: `Failed to restart session for permission mode change: ${err}`,
|
|
2820
2874
|
});
|
|
2821
2875
|
});
|
|
@@ -2828,6 +2882,7 @@ export class BridgeWebSocketServer {
|
|
|
2828
2882
|
isClaudeAutoModeUnavailableError(err)) {
|
|
2829
2883
|
this.send(ws, {
|
|
2830
2884
|
type: "error",
|
|
2885
|
+
sessionId: msg.sessionId,
|
|
2831
2886
|
message: "Auto mode is unavailable in this environment. Keeping the current permission mode.",
|
|
2832
2887
|
errorCode: "auto_mode_unavailable",
|
|
2833
2888
|
});
|
|
@@ -2835,6 +2890,7 @@ export class BridgeWebSocketServer {
|
|
|
2835
2890
|
}
|
|
2836
2891
|
this.send(ws, {
|
|
2837
2892
|
type: "error",
|
|
2893
|
+
sessionId: msg.sessionId,
|
|
2838
2894
|
message: `Failed to set permission mode: ${errorMessageOf(err)}`,
|
|
2839
2895
|
});
|
|
2840
2896
|
});
|
|
@@ -2843,12 +2899,17 @@ export class BridgeWebSocketServer {
|
|
|
2843
2899
|
case "set_codex_model": {
|
|
2844
2900
|
const session = this.resolveSession(msg.sessionId);
|
|
2845
2901
|
if (!session) {
|
|
2846
|
-
this.send(ws, {
|
|
2902
|
+
this.send(ws, {
|
|
2903
|
+
type: "error",
|
|
2904
|
+
sessionId: msg.sessionId,
|
|
2905
|
+
message: "No active session.",
|
|
2906
|
+
});
|
|
2847
2907
|
return;
|
|
2848
2908
|
}
|
|
2849
2909
|
if (session.provider !== "codex") {
|
|
2850
2910
|
this.send(ws, {
|
|
2851
2911
|
type: "error",
|
|
2912
|
+
sessionId: msg.sessionId,
|
|
2852
2913
|
message: "Model switching is only supported for Codex sessions.",
|
|
2853
2914
|
errorCode: "set_codex_model_unsupported",
|
|
2854
2915
|
});
|
|
@@ -2858,6 +2919,7 @@ export class BridgeWebSocketServer {
|
|
|
2858
2919
|
if (!model) {
|
|
2859
2920
|
this.send(ws, {
|
|
2860
2921
|
type: "error",
|
|
2922
|
+
sessionId: msg.sessionId,
|
|
2861
2923
|
message: `Invalid Codex model: ${msg.model}`,
|
|
2862
2924
|
errorCode: "set_codex_model_rejected",
|
|
2863
2925
|
});
|
|
@@ -2904,6 +2966,7 @@ export class BridgeWebSocketServer {
|
|
|
2904
2966
|
if (!session || session.provider !== "codex") {
|
|
2905
2967
|
this.send(ws, {
|
|
2906
2968
|
type: "error",
|
|
2969
|
+
sessionId: msg.sessionId,
|
|
2907
2970
|
message: "No active Codex session.",
|
|
2908
2971
|
errorCode: "set_codex_speed_unsupported",
|
|
2909
2972
|
});
|
|
@@ -2935,6 +2998,7 @@ export class BridgeWebSocketServer {
|
|
|
2935
2998
|
if (!session || session.provider !== "codex") {
|
|
2936
2999
|
this.send(ws, {
|
|
2937
3000
|
type: "error",
|
|
3001
|
+
sessionId: msg.sessionId,
|
|
2938
3002
|
message: "Goal lookup is only supported for active Codex sessions.",
|
|
2939
3003
|
errorCode: "goal_get_unsupported",
|
|
2940
3004
|
});
|
|
@@ -2948,6 +3012,7 @@ export class BridgeWebSocketServer {
|
|
|
2948
3012
|
catch (err) {
|
|
2949
3013
|
this.send(ws, {
|
|
2950
3014
|
type: "error",
|
|
3015
|
+
sessionId: msg.sessionId,
|
|
2951
3016
|
message: `Failed to get goal: ${errorMessageOf(err)}`,
|
|
2952
3017
|
errorCode: "goal_get_failed",
|
|
2953
3018
|
});
|
|
@@ -2959,6 +3024,7 @@ export class BridgeWebSocketServer {
|
|
|
2959
3024
|
if (!session || session.provider !== "codex") {
|
|
2960
3025
|
this.send(ws, {
|
|
2961
3026
|
type: "error",
|
|
3027
|
+
sessionId: msg.sessionId,
|
|
2962
3028
|
message: "Goal updates are only supported for active Codex sessions.",
|
|
2963
3029
|
errorCode: "goal_set_unsupported",
|
|
2964
3030
|
});
|
|
@@ -2980,6 +3046,7 @@ export class BridgeWebSocketServer {
|
|
|
2980
3046
|
catch (err) {
|
|
2981
3047
|
this.send(ws, {
|
|
2982
3048
|
type: "error",
|
|
3049
|
+
sessionId: msg.sessionId,
|
|
2983
3050
|
message: `Failed to set goal: ${errorMessageOf(err)}`,
|
|
2984
3051
|
errorCode: "goal_set_failed",
|
|
2985
3052
|
});
|
|
@@ -2991,6 +3058,7 @@ export class BridgeWebSocketServer {
|
|
|
2991
3058
|
if (!session || session.provider !== "codex") {
|
|
2992
3059
|
this.send(ws, {
|
|
2993
3060
|
type: "error",
|
|
3061
|
+
sessionId: msg.sessionId,
|
|
2994
3062
|
message: "Goal clearing is only supported for active Codex sessions.",
|
|
2995
3063
|
errorCode: "goal_clear_unsupported",
|
|
2996
3064
|
});
|
|
@@ -3007,6 +3075,7 @@ export class BridgeWebSocketServer {
|
|
|
3007
3075
|
catch (err) {
|
|
3008
3076
|
this.send(ws, {
|
|
3009
3077
|
type: "error",
|
|
3078
|
+
sessionId: msg.sessionId,
|
|
3010
3079
|
message: `Failed to clear goal: ${errorMessageOf(err)}`,
|
|
3011
3080
|
errorCode: "goal_clear_failed",
|
|
3012
3081
|
});
|
|
@@ -3017,6 +3086,7 @@ export class BridgeWebSocketServer {
|
|
|
3017
3086
|
if (this.failSetSandboxMode) {
|
|
3018
3087
|
this.send(ws, {
|
|
3019
3088
|
type: "error",
|
|
3089
|
+
sessionId: msg.sessionId,
|
|
3020
3090
|
message: "Failed to set sandbox mode: forced test failure",
|
|
3021
3091
|
errorCode: "set_sandbox_mode_rejected",
|
|
3022
3092
|
});
|
|
@@ -3024,12 +3094,17 @@ export class BridgeWebSocketServer {
|
|
|
3024
3094
|
}
|
|
3025
3095
|
const session = this.resolveSession(msg.sessionId);
|
|
3026
3096
|
if (!session) {
|
|
3027
|
-
this.send(ws, {
|
|
3097
|
+
this.send(ws, {
|
|
3098
|
+
type: "error",
|
|
3099
|
+
sessionId: msg.sessionId,
|
|
3100
|
+
message: "No active session.",
|
|
3101
|
+
});
|
|
3028
3102
|
return;
|
|
3029
3103
|
}
|
|
3030
3104
|
if (msg.sandboxMode !== "on" && msg.sandboxMode !== "off") {
|
|
3031
3105
|
this.send(ws, {
|
|
3032
3106
|
type: "error",
|
|
3107
|
+
sessionId: msg.sessionId,
|
|
3033
3108
|
message: `Invalid sandbox mode: ${msg.sandboxMode}`,
|
|
3034
3109
|
});
|
|
3035
3110
|
return;
|
|
@@ -3217,6 +3292,7 @@ export class BridgeWebSocketServer {
|
|
|
3217
3292
|
.catch((err) => {
|
|
3218
3293
|
this.send(ws, {
|
|
3219
3294
|
type: "error",
|
|
3295
|
+
sessionId: msg.sessionId,
|
|
3220
3296
|
message: `Failed to restart session for sandbox mode change: ${err}`,
|
|
3221
3297
|
});
|
|
3222
3298
|
});
|
|
@@ -3388,6 +3464,7 @@ export class BridgeWebSocketServer {
|
|
|
3388
3464
|
else {
|
|
3389
3465
|
this.send(ws, {
|
|
3390
3466
|
type: "error",
|
|
3467
|
+
sessionId: msg.sessionId,
|
|
3391
3468
|
message: `Session ${msg.sessionId} not found`,
|
|
3392
3469
|
});
|
|
3393
3470
|
}
|
|
@@ -3497,6 +3574,7 @@ export class BridgeWebSocketServer {
|
|
|
3497
3574
|
if (!result) {
|
|
3498
3575
|
this.send(ws, {
|
|
3499
3576
|
type: "error",
|
|
3577
|
+
sessionId: msg.sessionId,
|
|
3500
3578
|
message: `Session ${msg.sessionId} not found`,
|
|
3501
3579
|
});
|
|
3502
3580
|
break;
|
|
@@ -3524,6 +3602,7 @@ export class BridgeWebSocketServer {
|
|
|
3524
3602
|
if (!result) {
|
|
3525
3603
|
this.send(ws, {
|
|
3526
3604
|
type: "error",
|
|
3605
|
+
sessionId: msg.sessionId,
|
|
3527
3606
|
message: `Session ${msg.sessionId} not found`,
|
|
3528
3607
|
});
|
|
3529
3608
|
break;
|
|
@@ -3554,6 +3633,7 @@ export class BridgeWebSocketServer {
|
|
|
3554
3633
|
else {
|
|
3555
3634
|
this.send(ws, {
|
|
3556
3635
|
type: "error",
|
|
3636
|
+
sessionId: msg.sessionId,
|
|
3557
3637
|
message: `Session ${msg.sessionId} not found`,
|
|
3558
3638
|
});
|
|
3559
3639
|
}
|
|
@@ -3584,6 +3664,7 @@ export class BridgeWebSocketServer {
|
|
|
3584
3664
|
else {
|
|
3585
3665
|
this.send(ws, {
|
|
3586
3666
|
type: "error",
|
|
3667
|
+
sessionId: msg.sessionId,
|
|
3587
3668
|
message: `Session ${msg.sessionId} not found`,
|
|
3588
3669
|
});
|
|
3589
3670
|
}
|
|
@@ -3594,6 +3675,7 @@ export class BridgeWebSocketServer {
|
|
|
3594
3675
|
if (!session) {
|
|
3595
3676
|
this.send(ws, {
|
|
3596
3677
|
type: "error",
|
|
3678
|
+
sessionId: msg.sessionId,
|
|
3597
3679
|
message: `Session ${msg.sessionId} not found`,
|
|
3598
3680
|
});
|
|
3599
3681
|
return;
|
|
@@ -4168,7 +4250,11 @@ export class BridgeWebSocketServer {
|
|
|
4168
4250
|
case "interrupt": {
|
|
4169
4251
|
const session = this.resolveSession(msg.sessionId);
|
|
4170
4252
|
if (!session) {
|
|
4171
|
-
this.send(ws, {
|
|
4253
|
+
this.send(ws, {
|
|
4254
|
+
type: "error",
|
|
4255
|
+
sessionId: msg.sessionId,
|
|
4256
|
+
message: "No active session.",
|
|
4257
|
+
});
|
|
4172
4258
|
return;
|
|
4173
4259
|
}
|
|
4174
4260
|
session.process.interrupt();
|
|
@@ -4228,11 +4314,15 @@ export class BridgeWebSocketServer {
|
|
|
4228
4314
|
}
|
|
4229
4315
|
case "read_file":
|
|
4230
4316
|
case "read_media_file": {
|
|
4317
|
+
const responseMetadata = {
|
|
4318
|
+
...projectRequestMetadata(msg),
|
|
4319
|
+
filePath: msg.filePath,
|
|
4320
|
+
};
|
|
4231
4321
|
const absPath = resolve(msg.projectPath, msg.filePath);
|
|
4232
4322
|
if (!this.isPathAllowed(absPath)) {
|
|
4233
4323
|
this.send(ws, {
|
|
4234
4324
|
type: "file_content",
|
|
4235
|
-
|
|
4325
|
+
...responseMetadata,
|
|
4236
4326
|
content: "",
|
|
4237
4327
|
error: "Path not allowed",
|
|
4238
4328
|
});
|
|
@@ -4243,7 +4333,7 @@ export class BridgeWebSocketServer {
|
|
|
4243
4333
|
if (!existsSync(absPath)) {
|
|
4244
4334
|
this.send(ws, {
|
|
4245
4335
|
type: "file_content",
|
|
4246
|
-
|
|
4336
|
+
...responseMetadata,
|
|
4247
4337
|
content: "",
|
|
4248
4338
|
error: "File not found",
|
|
4249
4339
|
});
|
|
@@ -4265,7 +4355,7 @@ export class BridgeWebSocketServer {
|
|
|
4265
4355
|
catch {
|
|
4266
4356
|
this.send(ws, {
|
|
4267
4357
|
type: "file_content",
|
|
4268
|
-
|
|
4358
|
+
...responseMetadata,
|
|
4269
4359
|
content: "",
|
|
4270
4360
|
error: targetPath.length > 0
|
|
4271
4361
|
? `This symbolic link points to a missing target: ${targetPath}`
|
|
@@ -4276,7 +4366,7 @@ export class BridgeWebSocketServer {
|
|
|
4276
4366
|
if (resolvedTargetStat.isDirectory()) {
|
|
4277
4367
|
this.send(ws, {
|
|
4278
4368
|
type: "file_content",
|
|
4279
|
-
|
|
4369
|
+
...responseMetadata,
|
|
4280
4370
|
content: "",
|
|
4281
4371
|
error: targetPath.length > 0
|
|
4282
4372
|
? `This symbolic link points to a directory (${targetPath}). Open the target directory instead.`
|
|
@@ -4288,7 +4378,7 @@ export class BridgeWebSocketServer {
|
|
|
4288
4378
|
else if (fileStat.isDirectory()) {
|
|
4289
4379
|
this.send(ws, {
|
|
4290
4380
|
type: "file_content",
|
|
4291
|
-
|
|
4381
|
+
...responseMetadata,
|
|
4292
4382
|
content: "",
|
|
4293
4383
|
error: "This path is a directory. Open a file instead.",
|
|
4294
4384
|
});
|
|
@@ -4301,7 +4391,7 @@ export class BridgeWebSocketServer {
|
|
|
4301
4391
|
if (!(await this.isCanonicalPathAllowed(canonicalPath))) {
|
|
4302
4392
|
this.send(ws, {
|
|
4303
4393
|
type: "file_content",
|
|
4304
|
-
|
|
4394
|
+
...responseMetadata,
|
|
4305
4395
|
content: "",
|
|
4306
4396
|
error: "Path not allowed",
|
|
4307
4397
|
});
|
|
@@ -4313,7 +4403,7 @@ export class BridgeWebSocketServer {
|
|
|
4313
4403
|
if (!this.mediaStore) {
|
|
4314
4404
|
this.send(ws, {
|
|
4315
4405
|
type: "file_content",
|
|
4316
|
-
|
|
4406
|
+
...responseMetadata,
|
|
4317
4407
|
kind: mediaType.kind,
|
|
4318
4408
|
content: "",
|
|
4319
4409
|
mimeType: mediaType.mimeType,
|
|
@@ -4325,7 +4415,7 @@ export class BridgeWebSocketServer {
|
|
|
4325
4415
|
const ref = await this.mediaStore.register(canonicalPath, mediaType.mimeType, resolvedFileStat.size);
|
|
4326
4416
|
this.send(ws, {
|
|
4327
4417
|
type: "file_content",
|
|
4328
|
-
|
|
4418
|
+
...responseMetadata,
|
|
4329
4419
|
kind: mediaType.kind,
|
|
4330
4420
|
content: "",
|
|
4331
4421
|
mimeType: ref.mimeType,
|
|
@@ -4337,7 +4427,7 @@ export class BridgeWebSocketServer {
|
|
|
4337
4427
|
if (msg.type === "read_media_file") {
|
|
4338
4428
|
this.send(ws, {
|
|
4339
4429
|
type: "file_content",
|
|
4340
|
-
|
|
4430
|
+
...responseMetadata,
|
|
4341
4431
|
content: "",
|
|
4342
4432
|
error: "Unsupported media file type.",
|
|
4343
4433
|
});
|
|
@@ -4348,7 +4438,7 @@ export class BridgeWebSocketServer {
|
|
|
4348
4438
|
if (resolvedFileStat.size > BridgeWebSocketServer.MAX_IMAGE_SIZE) {
|
|
4349
4439
|
this.send(ws, {
|
|
4350
4440
|
type: "file_content",
|
|
4351
|
-
|
|
4441
|
+
...responseMetadata,
|
|
4352
4442
|
kind: "image",
|
|
4353
4443
|
content: "",
|
|
4354
4444
|
mimeType,
|
|
@@ -4360,7 +4450,7 @@ export class BridgeWebSocketServer {
|
|
|
4360
4450
|
const buf = await readFile(absPath);
|
|
4361
4451
|
this.send(ws, {
|
|
4362
4452
|
type: "file_content",
|
|
4363
|
-
|
|
4453
|
+
...responseMetadata,
|
|
4364
4454
|
kind: "image",
|
|
4365
4455
|
content: "",
|
|
4366
4456
|
base64: buf.toString("base64"),
|
|
@@ -4416,7 +4506,7 @@ export class BridgeWebSocketServer {
|
|
|
4416
4506
|
: raw;
|
|
4417
4507
|
this.send(ws, {
|
|
4418
4508
|
type: "file_content",
|
|
4419
|
-
|
|
4509
|
+
...responseMetadata,
|
|
4420
4510
|
kind: "text",
|
|
4421
4511
|
content,
|
|
4422
4512
|
language,
|
|
@@ -4427,7 +4517,7 @@ export class BridgeWebSocketServer {
|
|
|
4427
4517
|
catch (err) {
|
|
4428
4518
|
this.send(ws, {
|
|
4429
4519
|
type: "file_content",
|
|
4430
|
-
|
|
4520
|
+
...responseMetadata,
|
|
4431
4521
|
content: "",
|
|
4432
4522
|
error: `Failed to read file: ${err}`,
|
|
4433
4523
|
});
|
|
@@ -4437,7 +4527,12 @@ export class BridgeWebSocketServer {
|
|
|
4437
4527
|
}
|
|
4438
4528
|
case "list_files": {
|
|
4439
4529
|
if (!this.isPathAllowed(msg.projectPath)) {
|
|
4440
|
-
this.send(ws,
|
|
4530
|
+
this.send(ws, {
|
|
4531
|
+
type: "file_list",
|
|
4532
|
+
...projectRequestMetadata(msg),
|
|
4533
|
+
files: [],
|
|
4534
|
+
error: this.buildPathNotAllowedError(msg.projectPath, msg.requestId).message,
|
|
4535
|
+
});
|
|
4441
4536
|
break;
|
|
4442
4537
|
}
|
|
4443
4538
|
void (async () => {
|
|
@@ -4448,7 +4543,10 @@ export class BridgeWebSocketServer {
|
|
|
4448
4543
|
});
|
|
4449
4544
|
this.send(ws, {
|
|
4450
4545
|
type: "file_list",
|
|
4546
|
+
...projectRequestMetadata(msg),
|
|
4451
4547
|
files: result.files,
|
|
4548
|
+
ignored: result.ignored,
|
|
4549
|
+
modifiedAt: result.modifiedAt,
|
|
4452
4550
|
totalFiles: result.totalFiles,
|
|
4453
4551
|
truncated: result.truncated,
|
|
4454
4552
|
});
|
|
@@ -4456,8 +4554,10 @@ export class BridgeWebSocketServer {
|
|
|
4456
4554
|
catch (err) {
|
|
4457
4555
|
const message = err instanceof Error ? err.message : String(err);
|
|
4458
4556
|
this.send(ws, {
|
|
4459
|
-
type: "
|
|
4460
|
-
|
|
4557
|
+
type: "file_list",
|
|
4558
|
+
...projectRequestMetadata(msg),
|
|
4559
|
+
files: [],
|
|
4560
|
+
error: `Failed to list files: ${message}`,
|
|
4461
4561
|
});
|
|
4462
4562
|
}
|
|
4463
4563
|
})();
|
|
@@ -4547,7 +4647,15 @@ export class BridgeWebSocketServer {
|
|
|
4547
4647
|
}
|
|
4548
4648
|
case "get_diff": {
|
|
4549
4649
|
if (!this.isPathAllowed(msg.projectPath)) {
|
|
4550
|
-
this.send(ws,
|
|
4650
|
+
this.send(ws, {
|
|
4651
|
+
type: "diff_result",
|
|
4652
|
+
...projectRequestMetadata(msg),
|
|
4653
|
+
staged: msg.staged === true,
|
|
4654
|
+
diff: "",
|
|
4655
|
+
error: this.buildPathNotAllowedError(msg.projectPath, msg.requestId)
|
|
4656
|
+
.message,
|
|
4657
|
+
errorCode: "path_not_allowed",
|
|
4658
|
+
});
|
|
4551
4659
|
break;
|
|
4552
4660
|
}
|
|
4553
4661
|
this.collectGitDiff(msg.projectPath, ({ diff, error }) => {
|
|
@@ -4555,6 +4663,8 @@ export class BridgeWebSocketServer {
|
|
|
4555
4663
|
if (/not a git repository/i.test(error)) {
|
|
4556
4664
|
this.send(ws, {
|
|
4557
4665
|
type: "diff_result",
|
|
4666
|
+
...projectRequestMetadata(msg),
|
|
4667
|
+
staged: msg.staged === true,
|
|
4558
4668
|
diff: "",
|
|
4559
4669
|
error: "This project is not a git repository",
|
|
4560
4670
|
errorCode: "git_not_available",
|
|
@@ -4563,6 +4673,8 @@ export class BridgeWebSocketServer {
|
|
|
4563
4673
|
else {
|
|
4564
4674
|
this.send(ws, {
|
|
4565
4675
|
type: "diff_result",
|
|
4676
|
+
...projectRequestMetadata(msg),
|
|
4677
|
+
staged: msg.staged === true,
|
|
4566
4678
|
diff: "",
|
|
4567
4679
|
error: `Failed to get diff: ${error}`,
|
|
4568
4680
|
});
|
|
@@ -4571,10 +4683,21 @@ export class BridgeWebSocketServer {
|
|
|
4571
4683
|
}
|
|
4572
4684
|
void this.collectImageChanges(msg.projectPath, diff).then((imageChanges) => {
|
|
4573
4685
|
if (imageChanges.length > 0) {
|
|
4574
|
-
this.send(ws, {
|
|
4686
|
+
this.send(ws, {
|
|
4687
|
+
type: "diff_result",
|
|
4688
|
+
...projectRequestMetadata(msg),
|
|
4689
|
+
staged: msg.staged === true,
|
|
4690
|
+
diff,
|
|
4691
|
+
imageChanges,
|
|
4692
|
+
});
|
|
4575
4693
|
}
|
|
4576
4694
|
else {
|
|
4577
|
-
this.send(ws, {
|
|
4695
|
+
this.send(ws, {
|
|
4696
|
+
type: "diff_result",
|
|
4697
|
+
...projectRequestMetadata(msg),
|
|
4698
|
+
staged: msg.staged === true,
|
|
4699
|
+
diff,
|
|
4700
|
+
});
|
|
4578
4701
|
}
|
|
4579
4702
|
});
|
|
4580
4703
|
}, msg.staged === true
|
|
@@ -4587,7 +4710,13 @@ export class BridgeWebSocketServer {
|
|
|
4587
4710
|
case "get_diff_image": {
|
|
4588
4711
|
if (!this.isPathAllowed(msg.projectPath) ||
|
|
4589
4712
|
!this.isPathAllowed(resolve(msg.projectPath, msg.filePath))) {
|
|
4590
|
-
this.send(ws, {
|
|
4713
|
+
this.send(ws, {
|
|
4714
|
+
type: "diff_image_result",
|
|
4715
|
+
...projectRequestMetadata(msg),
|
|
4716
|
+
filePath: msg.filePath,
|
|
4717
|
+
version: msg.version,
|
|
4718
|
+
error: "Path not allowed",
|
|
4719
|
+
});
|
|
4591
4720
|
break;
|
|
4592
4721
|
}
|
|
4593
4722
|
if (msg.version === "both") {
|
|
@@ -4600,6 +4729,7 @@ export class BridgeWebSocketServer {
|
|
|
4600
4729
|
const errors = [oldResult.error, newResult.error].filter(Boolean);
|
|
4601
4730
|
this.send(ws, {
|
|
4602
4731
|
type: "diff_image_result",
|
|
4732
|
+
...projectRequestMetadata(msg),
|
|
4603
4733
|
filePath: msg.filePath,
|
|
4604
4734
|
version: "both",
|
|
4605
4735
|
oldBase64: oldResult.base64,
|
|
@@ -4620,6 +4750,7 @@ export class BridgeWebSocketServer {
|
|
|
4620
4750
|
const result = await this.loadDiffImageAsync(msg.projectPath, msg.filePath, version);
|
|
4621
4751
|
this.send(ws, {
|
|
4622
4752
|
type: "diff_image_result",
|
|
4753
|
+
...projectRequestMetadata(msg),
|
|
4623
4754
|
filePath: msg.filePath,
|
|
4624
4755
|
version,
|
|
4625
4756
|
...result,
|
|
@@ -4634,25 +4765,42 @@ export class BridgeWebSocketServer {
|
|
|
4634
4765
|
}
|
|
4635
4766
|
case "list_worktrees": {
|
|
4636
4767
|
if (!this.isPathAllowed(msg.projectPath)) {
|
|
4637
|
-
this.send(ws,
|
|
4768
|
+
this.send(ws, {
|
|
4769
|
+
type: "worktree_list",
|
|
4770
|
+
...projectRequestMetadata(msg),
|
|
4771
|
+
worktrees: [],
|
|
4772
|
+
error: this.buildPathNotAllowedError(msg.projectPath, msg.requestId).message,
|
|
4773
|
+
});
|
|
4638
4774
|
break;
|
|
4639
4775
|
}
|
|
4640
4776
|
try {
|
|
4641
4777
|
const worktrees = listWorktrees(msg.projectPath);
|
|
4642
4778
|
const mainBranch = getMainBranch(msg.projectPath);
|
|
4643
|
-
this.send(ws, {
|
|
4779
|
+
this.send(ws, {
|
|
4780
|
+
type: "worktree_list",
|
|
4781
|
+
...projectRequestMetadata(msg),
|
|
4782
|
+
worktrees,
|
|
4783
|
+
mainBranch,
|
|
4784
|
+
});
|
|
4644
4785
|
}
|
|
4645
4786
|
catch (err) {
|
|
4646
4787
|
this.send(ws, {
|
|
4647
|
-
type: "
|
|
4648
|
-
|
|
4788
|
+
type: "worktree_list",
|
|
4789
|
+
...projectRequestMetadata(msg),
|
|
4790
|
+
worktrees: [],
|
|
4791
|
+
error: `Failed to list worktrees: ${err}`,
|
|
4649
4792
|
});
|
|
4650
4793
|
}
|
|
4651
4794
|
break;
|
|
4652
4795
|
}
|
|
4653
4796
|
case "remove_worktree": {
|
|
4654
4797
|
if (!this.isPathAllowed(msg.projectPath)) {
|
|
4655
|
-
this.send(ws,
|
|
4798
|
+
this.send(ws, {
|
|
4799
|
+
type: "worktree_removed",
|
|
4800
|
+
...projectRequestMetadata(msg),
|
|
4801
|
+
worktreePath: msg.worktreePath,
|
|
4802
|
+
error: this.buildPathNotAllowedError(msg.projectPath, msg.requestId).message,
|
|
4803
|
+
});
|
|
4656
4804
|
break;
|
|
4657
4805
|
}
|
|
4658
4806
|
try {
|
|
@@ -4660,13 +4808,16 @@ export class BridgeWebSocketServer {
|
|
|
4660
4808
|
this.worktreeStore.deleteByWorktreePath(msg.worktreePath);
|
|
4661
4809
|
this.send(ws, {
|
|
4662
4810
|
type: "worktree_removed",
|
|
4811
|
+
...projectRequestMetadata(msg),
|
|
4663
4812
|
worktreePath: msg.worktreePath,
|
|
4664
4813
|
});
|
|
4665
4814
|
}
|
|
4666
4815
|
catch (err) {
|
|
4667
4816
|
this.send(ws, {
|
|
4668
|
-
type: "
|
|
4669
|
-
|
|
4817
|
+
type: "worktree_removed",
|
|
4818
|
+
...projectRequestMetadata(msg),
|
|
4819
|
+
worktreePath: msg.worktreePath,
|
|
4820
|
+
error: `Failed to remove worktree: ${err}`,
|
|
4670
4821
|
});
|
|
4671
4822
|
}
|
|
4672
4823
|
break;
|
|
@@ -4674,7 +4825,12 @@ export class BridgeWebSocketServer {
|
|
|
4674
4825
|
// ---- Git Operations (Phase 1-3) ----
|
|
4675
4826
|
case "git_stage": {
|
|
4676
4827
|
if (!this.isPathAllowed(msg.projectPath)) {
|
|
4677
|
-
this.send(ws,
|
|
4828
|
+
this.send(ws, {
|
|
4829
|
+
type: "git_stage_result",
|
|
4830
|
+
...projectRequestMetadata(msg),
|
|
4831
|
+
success: false,
|
|
4832
|
+
error: this.buildPathNotAllowedError(msg.projectPath, msg.requestId).message,
|
|
4833
|
+
});
|
|
4678
4834
|
break;
|
|
4679
4835
|
}
|
|
4680
4836
|
try {
|
|
@@ -4682,11 +4838,16 @@ export class BridgeWebSocketServer {
|
|
|
4682
4838
|
stageFiles(msg.projectPath, msg.files);
|
|
4683
4839
|
if (msg.hunks?.length)
|
|
4684
4840
|
stageHunks(msg.projectPath, msg.hunks);
|
|
4685
|
-
this.send(ws, {
|
|
4841
|
+
this.send(ws, {
|
|
4842
|
+
type: "git_stage_result",
|
|
4843
|
+
...projectRequestMetadata(msg),
|
|
4844
|
+
success: true,
|
|
4845
|
+
});
|
|
4686
4846
|
}
|
|
4687
4847
|
catch (err) {
|
|
4688
4848
|
this.send(ws, {
|
|
4689
4849
|
type: "git_stage_result",
|
|
4850
|
+
...projectRequestMetadata(msg),
|
|
4690
4851
|
success: false,
|
|
4691
4852
|
error: String(err),
|
|
4692
4853
|
});
|
|
@@ -4695,16 +4856,26 @@ export class BridgeWebSocketServer {
|
|
|
4695
4856
|
}
|
|
4696
4857
|
case "git_unstage": {
|
|
4697
4858
|
if (!this.isPathAllowed(msg.projectPath)) {
|
|
4698
|
-
this.send(ws,
|
|
4859
|
+
this.send(ws, {
|
|
4860
|
+
type: "git_unstage_result",
|
|
4861
|
+
...projectRequestMetadata(msg),
|
|
4862
|
+
success: false,
|
|
4863
|
+
error: this.buildPathNotAllowedError(msg.projectPath, msg.requestId).message,
|
|
4864
|
+
});
|
|
4699
4865
|
break;
|
|
4700
4866
|
}
|
|
4701
4867
|
try {
|
|
4702
4868
|
unstageFiles(msg.projectPath, msg.files ?? []);
|
|
4703
|
-
this.send(ws, {
|
|
4869
|
+
this.send(ws, {
|
|
4870
|
+
type: "git_unstage_result",
|
|
4871
|
+
...projectRequestMetadata(msg),
|
|
4872
|
+
success: true,
|
|
4873
|
+
});
|
|
4704
4874
|
}
|
|
4705
4875
|
catch (err) {
|
|
4706
4876
|
this.send(ws, {
|
|
4707
4877
|
type: "git_unstage_result",
|
|
4878
|
+
...projectRequestMetadata(msg),
|
|
4708
4879
|
success: false,
|
|
4709
4880
|
error: String(err),
|
|
4710
4881
|
});
|
|
@@ -4713,16 +4884,26 @@ export class BridgeWebSocketServer {
|
|
|
4713
4884
|
}
|
|
4714
4885
|
case "git_unstage_hunks": {
|
|
4715
4886
|
if (!this.isPathAllowed(msg.projectPath)) {
|
|
4716
|
-
this.send(ws,
|
|
4887
|
+
this.send(ws, {
|
|
4888
|
+
type: "git_unstage_hunks_result",
|
|
4889
|
+
...projectRequestMetadata(msg),
|
|
4890
|
+
success: false,
|
|
4891
|
+
error: this.buildPathNotAllowedError(msg.projectPath, msg.requestId).message,
|
|
4892
|
+
});
|
|
4717
4893
|
break;
|
|
4718
4894
|
}
|
|
4719
4895
|
try {
|
|
4720
4896
|
unstageHunks(msg.projectPath, msg.hunks);
|
|
4721
|
-
this.send(ws, {
|
|
4897
|
+
this.send(ws, {
|
|
4898
|
+
type: "git_unstage_hunks_result",
|
|
4899
|
+
...projectRequestMetadata(msg),
|
|
4900
|
+
success: true,
|
|
4901
|
+
});
|
|
4722
4902
|
}
|
|
4723
4903
|
catch (err) {
|
|
4724
4904
|
this.send(ws, {
|
|
4725
4905
|
type: "git_unstage_hunks_result",
|
|
4906
|
+
...projectRequestMetadata(msg),
|
|
4726
4907
|
success: false,
|
|
4727
4908
|
error: String(err),
|
|
4728
4909
|
});
|
|
@@ -4731,7 +4912,12 @@ export class BridgeWebSocketServer {
|
|
|
4731
4912
|
}
|
|
4732
4913
|
case "git_commit": {
|
|
4733
4914
|
if (!this.isPathAllowed(msg.projectPath)) {
|
|
4734
|
-
this.send(ws,
|
|
4915
|
+
this.send(ws, {
|
|
4916
|
+
type: "git_commit_result",
|
|
4917
|
+
...projectRequestMetadata(msg),
|
|
4918
|
+
success: false,
|
|
4919
|
+
error: this.buildPathNotAllowedError(msg.projectPath, msg.requestId).message,
|
|
4920
|
+
});
|
|
4735
4921
|
break;
|
|
4736
4922
|
}
|
|
4737
4923
|
const session = msg.sessionId
|
|
@@ -4765,6 +4951,7 @@ export class BridgeWebSocketServer {
|
|
|
4765
4951
|
const result = gitCommit(msg.projectPath, message);
|
|
4766
4952
|
this.send(ws, {
|
|
4767
4953
|
type: "git_commit_result",
|
|
4954
|
+
...projectRequestMetadata(msg),
|
|
4768
4955
|
success: true,
|
|
4769
4956
|
commitHash: result.hash,
|
|
4770
4957
|
message: result.message,
|
|
@@ -4773,6 +4960,7 @@ export class BridgeWebSocketServer {
|
|
|
4773
4960
|
catch (err) {
|
|
4774
4961
|
this.send(ws, {
|
|
4775
4962
|
type: "git_commit_result",
|
|
4963
|
+
...projectRequestMetadata(msg),
|
|
4776
4964
|
success: false,
|
|
4777
4965
|
error: err instanceof Error ? err.message : String(err),
|
|
4778
4966
|
});
|
|
@@ -4781,19 +4969,26 @@ export class BridgeWebSocketServer {
|
|
|
4781
4969
|
}
|
|
4782
4970
|
case "git_push": {
|
|
4783
4971
|
if (!this.isPathAllowed(msg.projectPath)) {
|
|
4784
|
-
this.send(ws,
|
|
4972
|
+
this.send(ws, {
|
|
4973
|
+
type: "git_push_result",
|
|
4974
|
+
...projectRequestMetadata(msg),
|
|
4975
|
+
success: false,
|
|
4976
|
+
error: this.buildPathNotAllowedError(msg.projectPath, msg.requestId).message,
|
|
4977
|
+
});
|
|
4785
4978
|
break;
|
|
4786
4979
|
}
|
|
4787
4980
|
try {
|
|
4788
4981
|
gitPush(msg.projectPath);
|
|
4789
4982
|
this.send(ws, {
|
|
4790
4983
|
type: "git_push_result",
|
|
4984
|
+
...projectRequestMetadata(msg),
|
|
4791
4985
|
success: true,
|
|
4792
4986
|
});
|
|
4793
4987
|
}
|
|
4794
4988
|
catch (err) {
|
|
4795
4989
|
this.send(ws, {
|
|
4796
4990
|
type: "git_push_result",
|
|
4991
|
+
...projectRequestMetadata(msg),
|
|
4797
4992
|
success: false,
|
|
4798
4993
|
error: String(err),
|
|
4799
4994
|
});
|
|
@@ -4802,13 +4997,22 @@ export class BridgeWebSocketServer {
|
|
|
4802
4997
|
}
|
|
4803
4998
|
case "git_branches": {
|
|
4804
4999
|
if (!this.isPathAllowed(msg.projectPath)) {
|
|
4805
|
-
this.send(ws,
|
|
5000
|
+
this.send(ws, {
|
|
5001
|
+
type: "git_branches_result",
|
|
5002
|
+
...projectRequestMetadata(msg),
|
|
5003
|
+
current: "",
|
|
5004
|
+
branches: [],
|
|
5005
|
+
checkedOutBranches: [],
|
|
5006
|
+
remoteStatusByBranch: {},
|
|
5007
|
+
error: this.buildPathNotAllowedError(msg.projectPath, msg.requestId).message,
|
|
5008
|
+
});
|
|
4806
5009
|
break;
|
|
4807
5010
|
}
|
|
4808
5011
|
try {
|
|
4809
5012
|
const result = listBranches(msg.projectPath);
|
|
4810
5013
|
this.send(ws, {
|
|
4811
5014
|
type: "git_branches_result",
|
|
5015
|
+
...projectRequestMetadata(msg),
|
|
4812
5016
|
current: result.current,
|
|
4813
5017
|
branches: result.branches,
|
|
4814
5018
|
checkedOutBranches: result.checkedOutBranches,
|
|
@@ -4818,6 +5022,7 @@ export class BridgeWebSocketServer {
|
|
|
4818
5022
|
catch (err) {
|
|
4819
5023
|
this.send(ws, {
|
|
4820
5024
|
type: "git_branches_result",
|
|
5025
|
+
...projectRequestMetadata(msg),
|
|
4821
5026
|
current: "",
|
|
4822
5027
|
branches: [],
|
|
4823
5028
|
remoteStatusByBranch: {},
|
|
@@ -4828,16 +5033,26 @@ export class BridgeWebSocketServer {
|
|
|
4828
5033
|
}
|
|
4829
5034
|
case "git_create_branch": {
|
|
4830
5035
|
if (!this.isPathAllowed(msg.projectPath)) {
|
|
4831
|
-
this.send(ws,
|
|
5036
|
+
this.send(ws, {
|
|
5037
|
+
type: "git_create_branch_result",
|
|
5038
|
+
...projectRequestMetadata(msg),
|
|
5039
|
+
success: false,
|
|
5040
|
+
error: this.buildPathNotAllowedError(msg.projectPath, msg.requestId).message,
|
|
5041
|
+
});
|
|
4832
5042
|
break;
|
|
4833
5043
|
}
|
|
4834
5044
|
try {
|
|
4835
5045
|
createBranch(msg.projectPath, msg.name, msg.checkout);
|
|
4836
|
-
this.send(ws, {
|
|
5046
|
+
this.send(ws, {
|
|
5047
|
+
type: "git_create_branch_result",
|
|
5048
|
+
...projectRequestMetadata(msg),
|
|
5049
|
+
success: true,
|
|
5050
|
+
});
|
|
4837
5051
|
}
|
|
4838
5052
|
catch (err) {
|
|
4839
5053
|
this.send(ws, {
|
|
4840
5054
|
type: "git_create_branch_result",
|
|
5055
|
+
...projectRequestMetadata(msg),
|
|
4841
5056
|
success: false,
|
|
4842
5057
|
error: String(err),
|
|
4843
5058
|
});
|
|
@@ -4846,16 +5061,26 @@ export class BridgeWebSocketServer {
|
|
|
4846
5061
|
}
|
|
4847
5062
|
case "git_checkout_branch": {
|
|
4848
5063
|
if (!this.isPathAllowed(msg.projectPath)) {
|
|
4849
|
-
this.send(ws,
|
|
5064
|
+
this.send(ws, {
|
|
5065
|
+
type: "git_checkout_branch_result",
|
|
5066
|
+
...projectRequestMetadata(msg),
|
|
5067
|
+
success: false,
|
|
5068
|
+
error: this.buildPathNotAllowedError(msg.projectPath, msg.requestId).message,
|
|
5069
|
+
});
|
|
4850
5070
|
break;
|
|
4851
5071
|
}
|
|
4852
5072
|
try {
|
|
4853
5073
|
checkoutBranch(msg.projectPath, msg.branch);
|
|
4854
|
-
this.send(ws, {
|
|
5074
|
+
this.send(ws, {
|
|
5075
|
+
type: "git_checkout_branch_result",
|
|
5076
|
+
...projectRequestMetadata(msg),
|
|
5077
|
+
success: true,
|
|
5078
|
+
});
|
|
4855
5079
|
}
|
|
4856
5080
|
catch (err) {
|
|
4857
5081
|
this.send(ws, {
|
|
4858
5082
|
type: "git_checkout_branch_result",
|
|
5083
|
+
...projectRequestMetadata(msg),
|
|
4859
5084
|
success: false,
|
|
4860
5085
|
error: String(err),
|
|
4861
5086
|
});
|
|
@@ -4864,16 +5089,26 @@ export class BridgeWebSocketServer {
|
|
|
4864
5089
|
}
|
|
4865
5090
|
case "git_revert_file": {
|
|
4866
5091
|
if (!this.isPathAllowed(msg.projectPath)) {
|
|
4867
|
-
this.send(ws,
|
|
5092
|
+
this.send(ws, {
|
|
5093
|
+
type: "git_revert_file_result",
|
|
5094
|
+
...projectRequestMetadata(msg),
|
|
5095
|
+
success: false,
|
|
5096
|
+
error: this.buildPathNotAllowedError(msg.projectPath, msg.requestId).message,
|
|
5097
|
+
});
|
|
4868
5098
|
break;
|
|
4869
5099
|
}
|
|
4870
5100
|
try {
|
|
4871
5101
|
revertFiles(msg.projectPath, msg.files);
|
|
4872
|
-
this.send(ws, {
|
|
5102
|
+
this.send(ws, {
|
|
5103
|
+
type: "git_revert_file_result",
|
|
5104
|
+
...projectRequestMetadata(msg),
|
|
5105
|
+
success: true,
|
|
5106
|
+
});
|
|
4873
5107
|
}
|
|
4874
5108
|
catch (err) {
|
|
4875
5109
|
this.send(ws, {
|
|
4876
5110
|
type: "git_revert_file_result",
|
|
5111
|
+
...projectRequestMetadata(msg),
|
|
4877
5112
|
success: false,
|
|
4878
5113
|
error: String(err),
|
|
4879
5114
|
});
|
|
@@ -4882,16 +5117,26 @@ export class BridgeWebSocketServer {
|
|
|
4882
5117
|
}
|
|
4883
5118
|
case "git_revert_hunks": {
|
|
4884
5119
|
if (!this.isPathAllowed(msg.projectPath)) {
|
|
4885
|
-
this.send(ws,
|
|
5120
|
+
this.send(ws, {
|
|
5121
|
+
type: "git_revert_hunks_result",
|
|
5122
|
+
...projectRequestMetadata(msg),
|
|
5123
|
+
success: false,
|
|
5124
|
+
error: this.buildPathNotAllowedError(msg.projectPath, msg.requestId).message,
|
|
5125
|
+
});
|
|
4886
5126
|
break;
|
|
4887
5127
|
}
|
|
4888
5128
|
try {
|
|
4889
5129
|
revertHunks(msg.projectPath, msg.hunks);
|
|
4890
|
-
this.send(ws, {
|
|
5130
|
+
this.send(ws, {
|
|
5131
|
+
type: "git_revert_hunks_result",
|
|
5132
|
+
...projectRequestMetadata(msg),
|
|
5133
|
+
success: true,
|
|
5134
|
+
});
|
|
4891
5135
|
}
|
|
4892
5136
|
catch (err) {
|
|
4893
5137
|
this.send(ws, {
|
|
4894
5138
|
type: "git_revert_hunks_result",
|
|
5139
|
+
...projectRequestMetadata(msg),
|
|
4895
5140
|
success: false,
|
|
4896
5141
|
error: String(err),
|
|
4897
5142
|
});
|
|
@@ -4900,16 +5145,26 @@ export class BridgeWebSocketServer {
|
|
|
4900
5145
|
}
|
|
4901
5146
|
case "git_fetch": {
|
|
4902
5147
|
if (!this.isPathAllowed(msg.projectPath)) {
|
|
4903
|
-
this.send(ws,
|
|
5148
|
+
this.send(ws, {
|
|
5149
|
+
type: "git_fetch_result",
|
|
5150
|
+
...projectRequestMetadata(msg),
|
|
5151
|
+
success: false,
|
|
5152
|
+
error: this.buildPathNotAllowedError(msg.projectPath, msg.requestId).message,
|
|
5153
|
+
});
|
|
4904
5154
|
break;
|
|
4905
5155
|
}
|
|
4906
5156
|
try {
|
|
4907
5157
|
gitFetch(msg.projectPath);
|
|
4908
|
-
this.send(ws, {
|
|
5158
|
+
this.send(ws, {
|
|
5159
|
+
type: "git_fetch_result",
|
|
5160
|
+
...projectRequestMetadata(msg),
|
|
5161
|
+
success: true,
|
|
5162
|
+
});
|
|
4909
5163
|
}
|
|
4910
5164
|
catch (err) {
|
|
4911
5165
|
this.send(ws, {
|
|
4912
5166
|
type: "git_fetch_result",
|
|
5167
|
+
...projectRequestMetadata(msg),
|
|
4913
5168
|
success: false,
|
|
4914
5169
|
error: String(err),
|
|
4915
5170
|
});
|
|
@@ -4918,7 +5173,12 @@ export class BridgeWebSocketServer {
|
|
|
4918
5173
|
}
|
|
4919
5174
|
case "git_pull": {
|
|
4920
5175
|
if (!this.isPathAllowed(msg.projectPath)) {
|
|
4921
|
-
this.send(ws,
|
|
5176
|
+
this.send(ws, {
|
|
5177
|
+
type: "git_pull_result",
|
|
5178
|
+
...projectRequestMetadata(msg),
|
|
5179
|
+
success: false,
|
|
5180
|
+
error: this.buildPathNotAllowedError(msg.projectPath, msg.requestId).message,
|
|
5181
|
+
});
|
|
4922
5182
|
break;
|
|
4923
5183
|
}
|
|
4924
5184
|
try {
|
|
@@ -4926,6 +5186,7 @@ export class BridgeWebSocketServer {
|
|
|
4926
5186
|
if (result.success) {
|
|
4927
5187
|
this.send(ws, {
|
|
4928
5188
|
type: "git_pull_result",
|
|
5189
|
+
...projectRequestMetadata(msg),
|
|
4929
5190
|
success: true,
|
|
4930
5191
|
message: result.message,
|
|
4931
5192
|
});
|
|
@@ -4933,6 +5194,7 @@ export class BridgeWebSocketServer {
|
|
|
4933
5194
|
else {
|
|
4934
5195
|
this.send(ws, {
|
|
4935
5196
|
type: "git_pull_result",
|
|
5197
|
+
...projectRequestMetadata(msg),
|
|
4936
5198
|
success: false,
|
|
4937
5199
|
error: result.message,
|
|
4938
5200
|
});
|
|
@@ -4941,6 +5203,7 @@ export class BridgeWebSocketServer {
|
|
|
4941
5203
|
catch (err) {
|
|
4942
5204
|
this.send(ws, {
|
|
4943
5205
|
type: "git_pull_result",
|
|
5206
|
+
...projectRequestMetadata(msg),
|
|
4944
5207
|
success: false,
|
|
4945
5208
|
error: String(err),
|
|
4946
5209
|
});
|
|
@@ -4951,6 +5214,7 @@ export class BridgeWebSocketServer {
|
|
|
4951
5214
|
if (!this.isPathAllowed(msg.projectPath)) {
|
|
4952
5215
|
this.send(ws, {
|
|
4953
5216
|
type: "git_status_result",
|
|
5217
|
+
requestId: msg.requestId,
|
|
4954
5218
|
sessionId: msg.sessionId,
|
|
4955
5219
|
projectPath: msg.projectPath,
|
|
4956
5220
|
hasUncommittedChanges: false,
|
|
@@ -4972,6 +5236,7 @@ export class BridgeWebSocketServer {
|
|
|
4972
5236
|
});
|
|
4973
5237
|
this.send(ws, {
|
|
4974
5238
|
type: "git_status_result",
|
|
5239
|
+
requestId: msg.requestId,
|
|
4975
5240
|
sessionId: msg.sessionId,
|
|
4976
5241
|
projectPath: msg.projectPath,
|
|
4977
5242
|
hasUncommittedChanges: result.hasUncommittedChanges,
|
|
@@ -4990,6 +5255,7 @@ export class BridgeWebSocketServer {
|
|
|
4990
5255
|
catch (err) {
|
|
4991
5256
|
this.send(ws, {
|
|
4992
5257
|
type: "git_status_result",
|
|
5258
|
+
requestId: msg.requestId,
|
|
4993
5259
|
sessionId: msg.sessionId,
|
|
4994
5260
|
projectPath: msg.projectPath,
|
|
4995
5261
|
hasUncommittedChanges: false,
|
|
@@ -5008,13 +5274,22 @@ export class BridgeWebSocketServer {
|
|
|
5008
5274
|
}
|
|
5009
5275
|
case "git_remote_status": {
|
|
5010
5276
|
if (!this.isPathAllowed(msg.projectPath)) {
|
|
5011
|
-
this.send(ws,
|
|
5277
|
+
this.send(ws, {
|
|
5278
|
+
type: "git_remote_status_result",
|
|
5279
|
+
...projectRequestMetadata(msg),
|
|
5280
|
+
ahead: 0,
|
|
5281
|
+
behind: 0,
|
|
5282
|
+
branch: "",
|
|
5283
|
+
hasUpstream: false,
|
|
5284
|
+
error: this.buildPathNotAllowedError(msg.projectPath, msg.requestId).message,
|
|
5285
|
+
});
|
|
5012
5286
|
break;
|
|
5013
5287
|
}
|
|
5014
5288
|
try {
|
|
5015
5289
|
const result = gitRemoteStatus(msg.projectPath);
|
|
5016
5290
|
this.send(ws, {
|
|
5017
5291
|
type: "git_remote_status_result",
|
|
5292
|
+
...projectRequestMetadata(msg),
|
|
5018
5293
|
ahead: result.ahead,
|
|
5019
5294
|
behind: result.behind,
|
|
5020
5295
|
branch: result.branch,
|
|
@@ -5024,6 +5299,7 @@ export class BridgeWebSocketServer {
|
|
|
5024
5299
|
catch (err) {
|
|
5025
5300
|
this.send(ws, {
|
|
5026
5301
|
type: "git_remote_status_result",
|
|
5302
|
+
...projectRequestMetadata(msg),
|
|
5027
5303
|
ahead: 0,
|
|
5028
5304
|
behind: 0,
|
|
5029
5305
|
branch: "",
|
|
@@ -5037,6 +5313,7 @@ export class BridgeWebSocketServer {
|
|
|
5037
5313
|
if (!session) {
|
|
5038
5314
|
this.send(ws, {
|
|
5039
5315
|
type: "rewind_preview",
|
|
5316
|
+
sessionId: msg.sessionId,
|
|
5040
5317
|
canRewind: false,
|
|
5041
5318
|
error: `Session ${msg.sessionId} not found`,
|
|
5042
5319
|
});
|
|
@@ -5045,6 +5322,7 @@ export class BridgeWebSocketServer {
|
|
|
5045
5322
|
if (session.provider === "codex") {
|
|
5046
5323
|
this.send(ws, {
|
|
5047
5324
|
type: "rewind_preview",
|
|
5325
|
+
sessionId: msg.sessionId,
|
|
5048
5326
|
canRewind: false,
|
|
5049
5327
|
error: "Codex rewind does not restore files",
|
|
5050
5328
|
});
|
|
@@ -5055,6 +5333,7 @@ export class BridgeWebSocketServer {
|
|
|
5055
5333
|
.then((result) => {
|
|
5056
5334
|
this.send(ws, {
|
|
5057
5335
|
type: "rewind_preview",
|
|
5336
|
+
sessionId: msg.sessionId,
|
|
5058
5337
|
canRewind: result.canRewind,
|
|
5059
5338
|
filesChanged: result.filesChanged,
|
|
5060
5339
|
insertions: result.insertions,
|
|
@@ -5065,6 +5344,7 @@ export class BridgeWebSocketServer {
|
|
|
5065
5344
|
.catch((err) => {
|
|
5066
5345
|
this.send(ws, {
|
|
5067
5346
|
type: "rewind_preview",
|
|
5347
|
+
sessionId: msg.sessionId,
|
|
5068
5348
|
canRewind: false,
|
|
5069
5349
|
error: `Dry run failed: ${err}`,
|
|
5070
5350
|
});
|
|
@@ -5076,6 +5356,7 @@ export class BridgeWebSocketServer {
|
|
|
5076
5356
|
if (!session) {
|
|
5077
5357
|
this.send(ws, {
|
|
5078
5358
|
type: "rewind_result",
|
|
5359
|
+
sessionId: msg.sessionId,
|
|
5079
5360
|
success: false,
|
|
5080
5361
|
mode: msg.mode,
|
|
5081
5362
|
error: `Session ${msg.sessionId} not found`,
|
|
@@ -5086,6 +5367,7 @@ export class BridgeWebSocketServer {
|
|
|
5086
5367
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
5087
5368
|
this.send(ws, {
|
|
5088
5369
|
type: "rewind_result",
|
|
5370
|
+
sessionId: msg.sessionId,
|
|
5089
5371
|
success: false,
|
|
5090
5372
|
mode: msg.mode,
|
|
5091
5373
|
error: errMsg,
|
|
@@ -5104,6 +5386,7 @@ export class BridgeWebSocketServer {
|
|
|
5104
5386
|
if (result.canRewind) {
|
|
5105
5387
|
this.send(ws, {
|
|
5106
5388
|
type: "rewind_result",
|
|
5389
|
+
sessionId: msg.sessionId,
|
|
5107
5390
|
success: true,
|
|
5108
5391
|
mode: "code",
|
|
5109
5392
|
});
|
|
@@ -5111,6 +5394,7 @@ export class BridgeWebSocketServer {
|
|
|
5111
5394
|
else {
|
|
5112
5395
|
this.send(ws, {
|
|
5113
5396
|
type: "rewind_result",
|
|
5397
|
+
sessionId: msg.sessionId,
|
|
5114
5398
|
success: false,
|
|
5115
5399
|
mode: "code",
|
|
5116
5400
|
error: result.error ?? "Cannot rewind files",
|
|
@@ -5126,6 +5410,7 @@ export class BridgeWebSocketServer {
|
|
|
5126
5410
|
this.sessionManager.rewindConversation(msg.sessionId, msg.targetUuid, (newSessionId) => {
|
|
5127
5411
|
this.send(ws, {
|
|
5128
5412
|
type: "rewind_result",
|
|
5413
|
+
sessionId: msg.sessionId,
|
|
5129
5414
|
success: true,
|
|
5130
5415
|
mode: "conversation",
|
|
5131
5416
|
});
|
|
@@ -5157,6 +5442,7 @@ export class BridgeWebSocketServer {
|
|
|
5157
5442
|
if (!result.canRewind) {
|
|
5158
5443
|
this.send(ws, {
|
|
5159
5444
|
type: "rewind_result",
|
|
5445
|
+
sessionId: msg.sessionId,
|
|
5160
5446
|
success: false,
|
|
5161
5447
|
mode: "both",
|
|
5162
5448
|
error: result.error ?? "Cannot rewind files",
|
|
@@ -5168,6 +5454,7 @@ export class BridgeWebSocketServer {
|
|
|
5168
5454
|
this.sessionManager.rewindConversation(msg.sessionId, msg.targetUuid, (newSessionId) => {
|
|
5169
5455
|
this.send(ws, {
|
|
5170
5456
|
type: "rewind_result",
|
|
5457
|
+
sessionId: msg.sessionId,
|
|
5171
5458
|
success: true,
|
|
5172
5459
|
mode: "both",
|
|
5173
5460
|
});
|
|
@@ -5199,6 +5486,7 @@ export class BridgeWebSocketServer {
|
|
|
5199
5486
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
5200
5487
|
this.send(ws, {
|
|
5201
5488
|
type: "error",
|
|
5489
|
+
sessionId: msg.sessionId,
|
|
5202
5490
|
message: errMsg,
|
|
5203
5491
|
errorCode: "fork_failed",
|
|
5204
5492
|
});
|
|
@@ -5244,6 +5532,8 @@ export class BridgeWebSocketServer {
|
|
|
5244
5532
|
const info = this.galleryStore.metaToInfo(meta);
|
|
5245
5533
|
this.send(ws, {
|
|
5246
5534
|
type: "screenshot_result",
|
|
5535
|
+
...projectRequestMetadata(msg),
|
|
5536
|
+
sessionId: msg.sessionId,
|
|
5247
5537
|
success: true,
|
|
5248
5538
|
image: info,
|
|
5249
5539
|
});
|
|
@@ -5253,6 +5543,8 @@ export class BridgeWebSocketServer {
|
|
|
5253
5543
|
}
|
|
5254
5544
|
this.send(ws, {
|
|
5255
5545
|
type: "screenshot_result",
|
|
5546
|
+
...projectRequestMetadata(msg),
|
|
5547
|
+
sessionId: msg.sessionId,
|
|
5256
5548
|
success: false,
|
|
5257
5549
|
error: "Failed to save screenshot to gallery",
|
|
5258
5550
|
});
|
|
@@ -5265,6 +5557,8 @@ export class BridgeWebSocketServer {
|
|
|
5265
5557
|
.catch((err) => {
|
|
5266
5558
|
this.send(ws, {
|
|
5267
5559
|
type: "screenshot_result",
|
|
5560
|
+
...projectRequestMetadata(msg),
|
|
5561
|
+
sessionId: msg.sessionId,
|
|
5268
5562
|
success: false,
|
|
5269
5563
|
error: err instanceof Error ? err.message : String(err),
|
|
5270
5564
|
});
|
|
@@ -5817,6 +6111,7 @@ export class BridgeWebSocketServer {
|
|
|
5817
6111
|
defaultCodexProfile: this.defaultCodexProfile,
|
|
5818
6112
|
codexAutoReviewDisabled: this.codexAutoReviewDisabled,
|
|
5819
6113
|
bridgeVersion: getPackageVersion(),
|
|
6114
|
+
protocolCapabilities: ["project_request_correlation_v1"],
|
|
5820
6115
|
});
|
|
5821
6116
|
}
|
|
5822
6117
|
sendPromptHistoryStatus(ws) {
|
|
@@ -5849,6 +6144,7 @@ export class BridgeWebSocketServer {
|
|
|
5849
6144
|
defaultCodexProfile: this.defaultCodexProfile,
|
|
5850
6145
|
codexAutoReviewDisabled: this.codexAutoReviewDisabled,
|
|
5851
6146
|
bridgeVersion: getPackageVersion(),
|
|
6147
|
+
protocolCapabilities: ["project_request_correlation_v1"],
|
|
5852
6148
|
});
|
|
5853
6149
|
}
|
|
5854
6150
|
broadcastPromptHistoryStatus() {
|
|
@@ -6740,7 +7036,7 @@ export class BridgeWebSocketServer {
|
|
|
6740
7036
|
if (!compatibleMsg)
|
|
6741
7037
|
return;
|
|
6742
7038
|
const sessionId = this.extractSessionIdFromServerMessage(compatibleMsg);
|
|
6743
|
-
if (sessionId) {
|
|
7039
|
+
if (sessionId && this.debugEvents.has(sessionId)) {
|
|
6744
7040
|
this.recordDebugEvent(sessionId, {
|
|
6745
7041
|
direction: "outgoing",
|
|
6746
7042
|
channel: "ws",
|