@ccpocket/bridge 1.76.0 → 1.77.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/parser.d.ts +73 -0
- package/dist/parser.js +8 -2
- package/dist/parser.js.map +1 -1
- package/dist/websocket.js +354 -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,6 +4543,7 @@ export class BridgeWebSocketServer {
|
|
|
4448
4543
|
});
|
|
4449
4544
|
this.send(ws, {
|
|
4450
4545
|
type: "file_list",
|
|
4546
|
+
...projectRequestMetadata(msg),
|
|
4451
4547
|
files: result.files,
|
|
4452
4548
|
totalFiles: result.totalFiles,
|
|
4453
4549
|
truncated: result.truncated,
|
|
@@ -4456,8 +4552,10 @@ export class BridgeWebSocketServer {
|
|
|
4456
4552
|
catch (err) {
|
|
4457
4553
|
const message = err instanceof Error ? err.message : String(err);
|
|
4458
4554
|
this.send(ws, {
|
|
4459
|
-
type: "
|
|
4460
|
-
|
|
4555
|
+
type: "file_list",
|
|
4556
|
+
...projectRequestMetadata(msg),
|
|
4557
|
+
files: [],
|
|
4558
|
+
error: `Failed to list files: ${message}`,
|
|
4461
4559
|
});
|
|
4462
4560
|
}
|
|
4463
4561
|
})();
|
|
@@ -4547,7 +4645,15 @@ export class BridgeWebSocketServer {
|
|
|
4547
4645
|
}
|
|
4548
4646
|
case "get_diff": {
|
|
4549
4647
|
if (!this.isPathAllowed(msg.projectPath)) {
|
|
4550
|
-
this.send(ws,
|
|
4648
|
+
this.send(ws, {
|
|
4649
|
+
type: "diff_result",
|
|
4650
|
+
...projectRequestMetadata(msg),
|
|
4651
|
+
staged: msg.staged === true,
|
|
4652
|
+
diff: "",
|
|
4653
|
+
error: this.buildPathNotAllowedError(msg.projectPath, msg.requestId)
|
|
4654
|
+
.message,
|
|
4655
|
+
errorCode: "path_not_allowed",
|
|
4656
|
+
});
|
|
4551
4657
|
break;
|
|
4552
4658
|
}
|
|
4553
4659
|
this.collectGitDiff(msg.projectPath, ({ diff, error }) => {
|
|
@@ -4555,6 +4661,8 @@ export class BridgeWebSocketServer {
|
|
|
4555
4661
|
if (/not a git repository/i.test(error)) {
|
|
4556
4662
|
this.send(ws, {
|
|
4557
4663
|
type: "diff_result",
|
|
4664
|
+
...projectRequestMetadata(msg),
|
|
4665
|
+
staged: msg.staged === true,
|
|
4558
4666
|
diff: "",
|
|
4559
4667
|
error: "This project is not a git repository",
|
|
4560
4668
|
errorCode: "git_not_available",
|
|
@@ -4563,6 +4671,8 @@ export class BridgeWebSocketServer {
|
|
|
4563
4671
|
else {
|
|
4564
4672
|
this.send(ws, {
|
|
4565
4673
|
type: "diff_result",
|
|
4674
|
+
...projectRequestMetadata(msg),
|
|
4675
|
+
staged: msg.staged === true,
|
|
4566
4676
|
diff: "",
|
|
4567
4677
|
error: `Failed to get diff: ${error}`,
|
|
4568
4678
|
});
|
|
@@ -4571,10 +4681,21 @@ export class BridgeWebSocketServer {
|
|
|
4571
4681
|
}
|
|
4572
4682
|
void this.collectImageChanges(msg.projectPath, diff).then((imageChanges) => {
|
|
4573
4683
|
if (imageChanges.length > 0) {
|
|
4574
|
-
this.send(ws, {
|
|
4684
|
+
this.send(ws, {
|
|
4685
|
+
type: "diff_result",
|
|
4686
|
+
...projectRequestMetadata(msg),
|
|
4687
|
+
staged: msg.staged === true,
|
|
4688
|
+
diff,
|
|
4689
|
+
imageChanges,
|
|
4690
|
+
});
|
|
4575
4691
|
}
|
|
4576
4692
|
else {
|
|
4577
|
-
this.send(ws, {
|
|
4693
|
+
this.send(ws, {
|
|
4694
|
+
type: "diff_result",
|
|
4695
|
+
...projectRequestMetadata(msg),
|
|
4696
|
+
staged: msg.staged === true,
|
|
4697
|
+
diff,
|
|
4698
|
+
});
|
|
4578
4699
|
}
|
|
4579
4700
|
});
|
|
4580
4701
|
}, msg.staged === true
|
|
@@ -4587,7 +4708,13 @@ export class BridgeWebSocketServer {
|
|
|
4587
4708
|
case "get_diff_image": {
|
|
4588
4709
|
if (!this.isPathAllowed(msg.projectPath) ||
|
|
4589
4710
|
!this.isPathAllowed(resolve(msg.projectPath, msg.filePath))) {
|
|
4590
|
-
this.send(ws, {
|
|
4711
|
+
this.send(ws, {
|
|
4712
|
+
type: "diff_image_result",
|
|
4713
|
+
...projectRequestMetadata(msg),
|
|
4714
|
+
filePath: msg.filePath,
|
|
4715
|
+
version: msg.version,
|
|
4716
|
+
error: "Path not allowed",
|
|
4717
|
+
});
|
|
4591
4718
|
break;
|
|
4592
4719
|
}
|
|
4593
4720
|
if (msg.version === "both") {
|
|
@@ -4600,6 +4727,7 @@ export class BridgeWebSocketServer {
|
|
|
4600
4727
|
const errors = [oldResult.error, newResult.error].filter(Boolean);
|
|
4601
4728
|
this.send(ws, {
|
|
4602
4729
|
type: "diff_image_result",
|
|
4730
|
+
...projectRequestMetadata(msg),
|
|
4603
4731
|
filePath: msg.filePath,
|
|
4604
4732
|
version: "both",
|
|
4605
4733
|
oldBase64: oldResult.base64,
|
|
@@ -4620,6 +4748,7 @@ export class BridgeWebSocketServer {
|
|
|
4620
4748
|
const result = await this.loadDiffImageAsync(msg.projectPath, msg.filePath, version);
|
|
4621
4749
|
this.send(ws, {
|
|
4622
4750
|
type: "diff_image_result",
|
|
4751
|
+
...projectRequestMetadata(msg),
|
|
4623
4752
|
filePath: msg.filePath,
|
|
4624
4753
|
version,
|
|
4625
4754
|
...result,
|
|
@@ -4634,25 +4763,42 @@ export class BridgeWebSocketServer {
|
|
|
4634
4763
|
}
|
|
4635
4764
|
case "list_worktrees": {
|
|
4636
4765
|
if (!this.isPathAllowed(msg.projectPath)) {
|
|
4637
|
-
this.send(ws,
|
|
4766
|
+
this.send(ws, {
|
|
4767
|
+
type: "worktree_list",
|
|
4768
|
+
...projectRequestMetadata(msg),
|
|
4769
|
+
worktrees: [],
|
|
4770
|
+
error: this.buildPathNotAllowedError(msg.projectPath, msg.requestId).message,
|
|
4771
|
+
});
|
|
4638
4772
|
break;
|
|
4639
4773
|
}
|
|
4640
4774
|
try {
|
|
4641
4775
|
const worktrees = listWorktrees(msg.projectPath);
|
|
4642
4776
|
const mainBranch = getMainBranch(msg.projectPath);
|
|
4643
|
-
this.send(ws, {
|
|
4777
|
+
this.send(ws, {
|
|
4778
|
+
type: "worktree_list",
|
|
4779
|
+
...projectRequestMetadata(msg),
|
|
4780
|
+
worktrees,
|
|
4781
|
+
mainBranch,
|
|
4782
|
+
});
|
|
4644
4783
|
}
|
|
4645
4784
|
catch (err) {
|
|
4646
4785
|
this.send(ws, {
|
|
4647
|
-
type: "
|
|
4648
|
-
|
|
4786
|
+
type: "worktree_list",
|
|
4787
|
+
...projectRequestMetadata(msg),
|
|
4788
|
+
worktrees: [],
|
|
4789
|
+
error: `Failed to list worktrees: ${err}`,
|
|
4649
4790
|
});
|
|
4650
4791
|
}
|
|
4651
4792
|
break;
|
|
4652
4793
|
}
|
|
4653
4794
|
case "remove_worktree": {
|
|
4654
4795
|
if (!this.isPathAllowed(msg.projectPath)) {
|
|
4655
|
-
this.send(ws,
|
|
4796
|
+
this.send(ws, {
|
|
4797
|
+
type: "worktree_removed",
|
|
4798
|
+
...projectRequestMetadata(msg),
|
|
4799
|
+
worktreePath: msg.worktreePath,
|
|
4800
|
+
error: this.buildPathNotAllowedError(msg.projectPath, msg.requestId).message,
|
|
4801
|
+
});
|
|
4656
4802
|
break;
|
|
4657
4803
|
}
|
|
4658
4804
|
try {
|
|
@@ -4660,13 +4806,16 @@ export class BridgeWebSocketServer {
|
|
|
4660
4806
|
this.worktreeStore.deleteByWorktreePath(msg.worktreePath);
|
|
4661
4807
|
this.send(ws, {
|
|
4662
4808
|
type: "worktree_removed",
|
|
4809
|
+
...projectRequestMetadata(msg),
|
|
4663
4810
|
worktreePath: msg.worktreePath,
|
|
4664
4811
|
});
|
|
4665
4812
|
}
|
|
4666
4813
|
catch (err) {
|
|
4667
4814
|
this.send(ws, {
|
|
4668
|
-
type: "
|
|
4669
|
-
|
|
4815
|
+
type: "worktree_removed",
|
|
4816
|
+
...projectRequestMetadata(msg),
|
|
4817
|
+
worktreePath: msg.worktreePath,
|
|
4818
|
+
error: `Failed to remove worktree: ${err}`,
|
|
4670
4819
|
});
|
|
4671
4820
|
}
|
|
4672
4821
|
break;
|
|
@@ -4674,7 +4823,12 @@ export class BridgeWebSocketServer {
|
|
|
4674
4823
|
// ---- Git Operations (Phase 1-3) ----
|
|
4675
4824
|
case "git_stage": {
|
|
4676
4825
|
if (!this.isPathAllowed(msg.projectPath)) {
|
|
4677
|
-
this.send(ws,
|
|
4826
|
+
this.send(ws, {
|
|
4827
|
+
type: "git_stage_result",
|
|
4828
|
+
...projectRequestMetadata(msg),
|
|
4829
|
+
success: false,
|
|
4830
|
+
error: this.buildPathNotAllowedError(msg.projectPath, msg.requestId).message,
|
|
4831
|
+
});
|
|
4678
4832
|
break;
|
|
4679
4833
|
}
|
|
4680
4834
|
try {
|
|
@@ -4682,11 +4836,16 @@ export class BridgeWebSocketServer {
|
|
|
4682
4836
|
stageFiles(msg.projectPath, msg.files);
|
|
4683
4837
|
if (msg.hunks?.length)
|
|
4684
4838
|
stageHunks(msg.projectPath, msg.hunks);
|
|
4685
|
-
this.send(ws, {
|
|
4839
|
+
this.send(ws, {
|
|
4840
|
+
type: "git_stage_result",
|
|
4841
|
+
...projectRequestMetadata(msg),
|
|
4842
|
+
success: true,
|
|
4843
|
+
});
|
|
4686
4844
|
}
|
|
4687
4845
|
catch (err) {
|
|
4688
4846
|
this.send(ws, {
|
|
4689
4847
|
type: "git_stage_result",
|
|
4848
|
+
...projectRequestMetadata(msg),
|
|
4690
4849
|
success: false,
|
|
4691
4850
|
error: String(err),
|
|
4692
4851
|
});
|
|
@@ -4695,16 +4854,26 @@ export class BridgeWebSocketServer {
|
|
|
4695
4854
|
}
|
|
4696
4855
|
case "git_unstage": {
|
|
4697
4856
|
if (!this.isPathAllowed(msg.projectPath)) {
|
|
4698
|
-
this.send(ws,
|
|
4857
|
+
this.send(ws, {
|
|
4858
|
+
type: "git_unstage_result",
|
|
4859
|
+
...projectRequestMetadata(msg),
|
|
4860
|
+
success: false,
|
|
4861
|
+
error: this.buildPathNotAllowedError(msg.projectPath, msg.requestId).message,
|
|
4862
|
+
});
|
|
4699
4863
|
break;
|
|
4700
4864
|
}
|
|
4701
4865
|
try {
|
|
4702
4866
|
unstageFiles(msg.projectPath, msg.files ?? []);
|
|
4703
|
-
this.send(ws, {
|
|
4867
|
+
this.send(ws, {
|
|
4868
|
+
type: "git_unstage_result",
|
|
4869
|
+
...projectRequestMetadata(msg),
|
|
4870
|
+
success: true,
|
|
4871
|
+
});
|
|
4704
4872
|
}
|
|
4705
4873
|
catch (err) {
|
|
4706
4874
|
this.send(ws, {
|
|
4707
4875
|
type: "git_unstage_result",
|
|
4876
|
+
...projectRequestMetadata(msg),
|
|
4708
4877
|
success: false,
|
|
4709
4878
|
error: String(err),
|
|
4710
4879
|
});
|
|
@@ -4713,16 +4882,26 @@ export class BridgeWebSocketServer {
|
|
|
4713
4882
|
}
|
|
4714
4883
|
case "git_unstage_hunks": {
|
|
4715
4884
|
if (!this.isPathAllowed(msg.projectPath)) {
|
|
4716
|
-
this.send(ws,
|
|
4885
|
+
this.send(ws, {
|
|
4886
|
+
type: "git_unstage_hunks_result",
|
|
4887
|
+
...projectRequestMetadata(msg),
|
|
4888
|
+
success: false,
|
|
4889
|
+
error: this.buildPathNotAllowedError(msg.projectPath, msg.requestId).message,
|
|
4890
|
+
});
|
|
4717
4891
|
break;
|
|
4718
4892
|
}
|
|
4719
4893
|
try {
|
|
4720
4894
|
unstageHunks(msg.projectPath, msg.hunks);
|
|
4721
|
-
this.send(ws, {
|
|
4895
|
+
this.send(ws, {
|
|
4896
|
+
type: "git_unstage_hunks_result",
|
|
4897
|
+
...projectRequestMetadata(msg),
|
|
4898
|
+
success: true,
|
|
4899
|
+
});
|
|
4722
4900
|
}
|
|
4723
4901
|
catch (err) {
|
|
4724
4902
|
this.send(ws, {
|
|
4725
4903
|
type: "git_unstage_hunks_result",
|
|
4904
|
+
...projectRequestMetadata(msg),
|
|
4726
4905
|
success: false,
|
|
4727
4906
|
error: String(err),
|
|
4728
4907
|
});
|
|
@@ -4731,7 +4910,12 @@ export class BridgeWebSocketServer {
|
|
|
4731
4910
|
}
|
|
4732
4911
|
case "git_commit": {
|
|
4733
4912
|
if (!this.isPathAllowed(msg.projectPath)) {
|
|
4734
|
-
this.send(ws,
|
|
4913
|
+
this.send(ws, {
|
|
4914
|
+
type: "git_commit_result",
|
|
4915
|
+
...projectRequestMetadata(msg),
|
|
4916
|
+
success: false,
|
|
4917
|
+
error: this.buildPathNotAllowedError(msg.projectPath, msg.requestId).message,
|
|
4918
|
+
});
|
|
4735
4919
|
break;
|
|
4736
4920
|
}
|
|
4737
4921
|
const session = msg.sessionId
|
|
@@ -4765,6 +4949,7 @@ export class BridgeWebSocketServer {
|
|
|
4765
4949
|
const result = gitCommit(msg.projectPath, message);
|
|
4766
4950
|
this.send(ws, {
|
|
4767
4951
|
type: "git_commit_result",
|
|
4952
|
+
...projectRequestMetadata(msg),
|
|
4768
4953
|
success: true,
|
|
4769
4954
|
commitHash: result.hash,
|
|
4770
4955
|
message: result.message,
|
|
@@ -4773,6 +4958,7 @@ export class BridgeWebSocketServer {
|
|
|
4773
4958
|
catch (err) {
|
|
4774
4959
|
this.send(ws, {
|
|
4775
4960
|
type: "git_commit_result",
|
|
4961
|
+
...projectRequestMetadata(msg),
|
|
4776
4962
|
success: false,
|
|
4777
4963
|
error: err instanceof Error ? err.message : String(err),
|
|
4778
4964
|
});
|
|
@@ -4781,19 +4967,26 @@ export class BridgeWebSocketServer {
|
|
|
4781
4967
|
}
|
|
4782
4968
|
case "git_push": {
|
|
4783
4969
|
if (!this.isPathAllowed(msg.projectPath)) {
|
|
4784
|
-
this.send(ws,
|
|
4970
|
+
this.send(ws, {
|
|
4971
|
+
type: "git_push_result",
|
|
4972
|
+
...projectRequestMetadata(msg),
|
|
4973
|
+
success: false,
|
|
4974
|
+
error: this.buildPathNotAllowedError(msg.projectPath, msg.requestId).message,
|
|
4975
|
+
});
|
|
4785
4976
|
break;
|
|
4786
4977
|
}
|
|
4787
4978
|
try {
|
|
4788
4979
|
gitPush(msg.projectPath);
|
|
4789
4980
|
this.send(ws, {
|
|
4790
4981
|
type: "git_push_result",
|
|
4982
|
+
...projectRequestMetadata(msg),
|
|
4791
4983
|
success: true,
|
|
4792
4984
|
});
|
|
4793
4985
|
}
|
|
4794
4986
|
catch (err) {
|
|
4795
4987
|
this.send(ws, {
|
|
4796
4988
|
type: "git_push_result",
|
|
4989
|
+
...projectRequestMetadata(msg),
|
|
4797
4990
|
success: false,
|
|
4798
4991
|
error: String(err),
|
|
4799
4992
|
});
|
|
@@ -4802,13 +4995,22 @@ export class BridgeWebSocketServer {
|
|
|
4802
4995
|
}
|
|
4803
4996
|
case "git_branches": {
|
|
4804
4997
|
if (!this.isPathAllowed(msg.projectPath)) {
|
|
4805
|
-
this.send(ws,
|
|
4998
|
+
this.send(ws, {
|
|
4999
|
+
type: "git_branches_result",
|
|
5000
|
+
...projectRequestMetadata(msg),
|
|
5001
|
+
current: "",
|
|
5002
|
+
branches: [],
|
|
5003
|
+
checkedOutBranches: [],
|
|
5004
|
+
remoteStatusByBranch: {},
|
|
5005
|
+
error: this.buildPathNotAllowedError(msg.projectPath, msg.requestId).message,
|
|
5006
|
+
});
|
|
4806
5007
|
break;
|
|
4807
5008
|
}
|
|
4808
5009
|
try {
|
|
4809
5010
|
const result = listBranches(msg.projectPath);
|
|
4810
5011
|
this.send(ws, {
|
|
4811
5012
|
type: "git_branches_result",
|
|
5013
|
+
...projectRequestMetadata(msg),
|
|
4812
5014
|
current: result.current,
|
|
4813
5015
|
branches: result.branches,
|
|
4814
5016
|
checkedOutBranches: result.checkedOutBranches,
|
|
@@ -4818,6 +5020,7 @@ export class BridgeWebSocketServer {
|
|
|
4818
5020
|
catch (err) {
|
|
4819
5021
|
this.send(ws, {
|
|
4820
5022
|
type: "git_branches_result",
|
|
5023
|
+
...projectRequestMetadata(msg),
|
|
4821
5024
|
current: "",
|
|
4822
5025
|
branches: [],
|
|
4823
5026
|
remoteStatusByBranch: {},
|
|
@@ -4828,16 +5031,26 @@ export class BridgeWebSocketServer {
|
|
|
4828
5031
|
}
|
|
4829
5032
|
case "git_create_branch": {
|
|
4830
5033
|
if (!this.isPathAllowed(msg.projectPath)) {
|
|
4831
|
-
this.send(ws,
|
|
5034
|
+
this.send(ws, {
|
|
5035
|
+
type: "git_create_branch_result",
|
|
5036
|
+
...projectRequestMetadata(msg),
|
|
5037
|
+
success: false,
|
|
5038
|
+
error: this.buildPathNotAllowedError(msg.projectPath, msg.requestId).message,
|
|
5039
|
+
});
|
|
4832
5040
|
break;
|
|
4833
5041
|
}
|
|
4834
5042
|
try {
|
|
4835
5043
|
createBranch(msg.projectPath, msg.name, msg.checkout);
|
|
4836
|
-
this.send(ws, {
|
|
5044
|
+
this.send(ws, {
|
|
5045
|
+
type: "git_create_branch_result",
|
|
5046
|
+
...projectRequestMetadata(msg),
|
|
5047
|
+
success: true,
|
|
5048
|
+
});
|
|
4837
5049
|
}
|
|
4838
5050
|
catch (err) {
|
|
4839
5051
|
this.send(ws, {
|
|
4840
5052
|
type: "git_create_branch_result",
|
|
5053
|
+
...projectRequestMetadata(msg),
|
|
4841
5054
|
success: false,
|
|
4842
5055
|
error: String(err),
|
|
4843
5056
|
});
|
|
@@ -4846,16 +5059,26 @@ export class BridgeWebSocketServer {
|
|
|
4846
5059
|
}
|
|
4847
5060
|
case "git_checkout_branch": {
|
|
4848
5061
|
if (!this.isPathAllowed(msg.projectPath)) {
|
|
4849
|
-
this.send(ws,
|
|
5062
|
+
this.send(ws, {
|
|
5063
|
+
type: "git_checkout_branch_result",
|
|
5064
|
+
...projectRequestMetadata(msg),
|
|
5065
|
+
success: false,
|
|
5066
|
+
error: this.buildPathNotAllowedError(msg.projectPath, msg.requestId).message,
|
|
5067
|
+
});
|
|
4850
5068
|
break;
|
|
4851
5069
|
}
|
|
4852
5070
|
try {
|
|
4853
5071
|
checkoutBranch(msg.projectPath, msg.branch);
|
|
4854
|
-
this.send(ws, {
|
|
5072
|
+
this.send(ws, {
|
|
5073
|
+
type: "git_checkout_branch_result",
|
|
5074
|
+
...projectRequestMetadata(msg),
|
|
5075
|
+
success: true,
|
|
5076
|
+
});
|
|
4855
5077
|
}
|
|
4856
5078
|
catch (err) {
|
|
4857
5079
|
this.send(ws, {
|
|
4858
5080
|
type: "git_checkout_branch_result",
|
|
5081
|
+
...projectRequestMetadata(msg),
|
|
4859
5082
|
success: false,
|
|
4860
5083
|
error: String(err),
|
|
4861
5084
|
});
|
|
@@ -4864,16 +5087,26 @@ export class BridgeWebSocketServer {
|
|
|
4864
5087
|
}
|
|
4865
5088
|
case "git_revert_file": {
|
|
4866
5089
|
if (!this.isPathAllowed(msg.projectPath)) {
|
|
4867
|
-
this.send(ws,
|
|
5090
|
+
this.send(ws, {
|
|
5091
|
+
type: "git_revert_file_result",
|
|
5092
|
+
...projectRequestMetadata(msg),
|
|
5093
|
+
success: false,
|
|
5094
|
+
error: this.buildPathNotAllowedError(msg.projectPath, msg.requestId).message,
|
|
5095
|
+
});
|
|
4868
5096
|
break;
|
|
4869
5097
|
}
|
|
4870
5098
|
try {
|
|
4871
5099
|
revertFiles(msg.projectPath, msg.files);
|
|
4872
|
-
this.send(ws, {
|
|
5100
|
+
this.send(ws, {
|
|
5101
|
+
type: "git_revert_file_result",
|
|
5102
|
+
...projectRequestMetadata(msg),
|
|
5103
|
+
success: true,
|
|
5104
|
+
});
|
|
4873
5105
|
}
|
|
4874
5106
|
catch (err) {
|
|
4875
5107
|
this.send(ws, {
|
|
4876
5108
|
type: "git_revert_file_result",
|
|
5109
|
+
...projectRequestMetadata(msg),
|
|
4877
5110
|
success: false,
|
|
4878
5111
|
error: String(err),
|
|
4879
5112
|
});
|
|
@@ -4882,16 +5115,26 @@ export class BridgeWebSocketServer {
|
|
|
4882
5115
|
}
|
|
4883
5116
|
case "git_revert_hunks": {
|
|
4884
5117
|
if (!this.isPathAllowed(msg.projectPath)) {
|
|
4885
|
-
this.send(ws,
|
|
5118
|
+
this.send(ws, {
|
|
5119
|
+
type: "git_revert_hunks_result",
|
|
5120
|
+
...projectRequestMetadata(msg),
|
|
5121
|
+
success: false,
|
|
5122
|
+
error: this.buildPathNotAllowedError(msg.projectPath, msg.requestId).message,
|
|
5123
|
+
});
|
|
4886
5124
|
break;
|
|
4887
5125
|
}
|
|
4888
5126
|
try {
|
|
4889
5127
|
revertHunks(msg.projectPath, msg.hunks);
|
|
4890
|
-
this.send(ws, {
|
|
5128
|
+
this.send(ws, {
|
|
5129
|
+
type: "git_revert_hunks_result",
|
|
5130
|
+
...projectRequestMetadata(msg),
|
|
5131
|
+
success: true,
|
|
5132
|
+
});
|
|
4891
5133
|
}
|
|
4892
5134
|
catch (err) {
|
|
4893
5135
|
this.send(ws, {
|
|
4894
5136
|
type: "git_revert_hunks_result",
|
|
5137
|
+
...projectRequestMetadata(msg),
|
|
4895
5138
|
success: false,
|
|
4896
5139
|
error: String(err),
|
|
4897
5140
|
});
|
|
@@ -4900,16 +5143,26 @@ export class BridgeWebSocketServer {
|
|
|
4900
5143
|
}
|
|
4901
5144
|
case "git_fetch": {
|
|
4902
5145
|
if (!this.isPathAllowed(msg.projectPath)) {
|
|
4903
|
-
this.send(ws,
|
|
5146
|
+
this.send(ws, {
|
|
5147
|
+
type: "git_fetch_result",
|
|
5148
|
+
...projectRequestMetadata(msg),
|
|
5149
|
+
success: false,
|
|
5150
|
+
error: this.buildPathNotAllowedError(msg.projectPath, msg.requestId).message,
|
|
5151
|
+
});
|
|
4904
5152
|
break;
|
|
4905
5153
|
}
|
|
4906
5154
|
try {
|
|
4907
5155
|
gitFetch(msg.projectPath);
|
|
4908
|
-
this.send(ws, {
|
|
5156
|
+
this.send(ws, {
|
|
5157
|
+
type: "git_fetch_result",
|
|
5158
|
+
...projectRequestMetadata(msg),
|
|
5159
|
+
success: true,
|
|
5160
|
+
});
|
|
4909
5161
|
}
|
|
4910
5162
|
catch (err) {
|
|
4911
5163
|
this.send(ws, {
|
|
4912
5164
|
type: "git_fetch_result",
|
|
5165
|
+
...projectRequestMetadata(msg),
|
|
4913
5166
|
success: false,
|
|
4914
5167
|
error: String(err),
|
|
4915
5168
|
});
|
|
@@ -4918,7 +5171,12 @@ export class BridgeWebSocketServer {
|
|
|
4918
5171
|
}
|
|
4919
5172
|
case "git_pull": {
|
|
4920
5173
|
if (!this.isPathAllowed(msg.projectPath)) {
|
|
4921
|
-
this.send(ws,
|
|
5174
|
+
this.send(ws, {
|
|
5175
|
+
type: "git_pull_result",
|
|
5176
|
+
...projectRequestMetadata(msg),
|
|
5177
|
+
success: false,
|
|
5178
|
+
error: this.buildPathNotAllowedError(msg.projectPath, msg.requestId).message,
|
|
5179
|
+
});
|
|
4922
5180
|
break;
|
|
4923
5181
|
}
|
|
4924
5182
|
try {
|
|
@@ -4926,6 +5184,7 @@ export class BridgeWebSocketServer {
|
|
|
4926
5184
|
if (result.success) {
|
|
4927
5185
|
this.send(ws, {
|
|
4928
5186
|
type: "git_pull_result",
|
|
5187
|
+
...projectRequestMetadata(msg),
|
|
4929
5188
|
success: true,
|
|
4930
5189
|
message: result.message,
|
|
4931
5190
|
});
|
|
@@ -4933,6 +5192,7 @@ export class BridgeWebSocketServer {
|
|
|
4933
5192
|
else {
|
|
4934
5193
|
this.send(ws, {
|
|
4935
5194
|
type: "git_pull_result",
|
|
5195
|
+
...projectRequestMetadata(msg),
|
|
4936
5196
|
success: false,
|
|
4937
5197
|
error: result.message,
|
|
4938
5198
|
});
|
|
@@ -4941,6 +5201,7 @@ export class BridgeWebSocketServer {
|
|
|
4941
5201
|
catch (err) {
|
|
4942
5202
|
this.send(ws, {
|
|
4943
5203
|
type: "git_pull_result",
|
|
5204
|
+
...projectRequestMetadata(msg),
|
|
4944
5205
|
success: false,
|
|
4945
5206
|
error: String(err),
|
|
4946
5207
|
});
|
|
@@ -4951,6 +5212,7 @@ export class BridgeWebSocketServer {
|
|
|
4951
5212
|
if (!this.isPathAllowed(msg.projectPath)) {
|
|
4952
5213
|
this.send(ws, {
|
|
4953
5214
|
type: "git_status_result",
|
|
5215
|
+
requestId: msg.requestId,
|
|
4954
5216
|
sessionId: msg.sessionId,
|
|
4955
5217
|
projectPath: msg.projectPath,
|
|
4956
5218
|
hasUncommittedChanges: false,
|
|
@@ -4972,6 +5234,7 @@ export class BridgeWebSocketServer {
|
|
|
4972
5234
|
});
|
|
4973
5235
|
this.send(ws, {
|
|
4974
5236
|
type: "git_status_result",
|
|
5237
|
+
requestId: msg.requestId,
|
|
4975
5238
|
sessionId: msg.sessionId,
|
|
4976
5239
|
projectPath: msg.projectPath,
|
|
4977
5240
|
hasUncommittedChanges: result.hasUncommittedChanges,
|
|
@@ -4990,6 +5253,7 @@ export class BridgeWebSocketServer {
|
|
|
4990
5253
|
catch (err) {
|
|
4991
5254
|
this.send(ws, {
|
|
4992
5255
|
type: "git_status_result",
|
|
5256
|
+
requestId: msg.requestId,
|
|
4993
5257
|
sessionId: msg.sessionId,
|
|
4994
5258
|
projectPath: msg.projectPath,
|
|
4995
5259
|
hasUncommittedChanges: false,
|
|
@@ -5008,13 +5272,22 @@ export class BridgeWebSocketServer {
|
|
|
5008
5272
|
}
|
|
5009
5273
|
case "git_remote_status": {
|
|
5010
5274
|
if (!this.isPathAllowed(msg.projectPath)) {
|
|
5011
|
-
this.send(ws,
|
|
5275
|
+
this.send(ws, {
|
|
5276
|
+
type: "git_remote_status_result",
|
|
5277
|
+
...projectRequestMetadata(msg),
|
|
5278
|
+
ahead: 0,
|
|
5279
|
+
behind: 0,
|
|
5280
|
+
branch: "",
|
|
5281
|
+
hasUpstream: false,
|
|
5282
|
+
error: this.buildPathNotAllowedError(msg.projectPath, msg.requestId).message,
|
|
5283
|
+
});
|
|
5012
5284
|
break;
|
|
5013
5285
|
}
|
|
5014
5286
|
try {
|
|
5015
5287
|
const result = gitRemoteStatus(msg.projectPath);
|
|
5016
5288
|
this.send(ws, {
|
|
5017
5289
|
type: "git_remote_status_result",
|
|
5290
|
+
...projectRequestMetadata(msg),
|
|
5018
5291
|
ahead: result.ahead,
|
|
5019
5292
|
behind: result.behind,
|
|
5020
5293
|
branch: result.branch,
|
|
@@ -5024,6 +5297,7 @@ export class BridgeWebSocketServer {
|
|
|
5024
5297
|
catch (err) {
|
|
5025
5298
|
this.send(ws, {
|
|
5026
5299
|
type: "git_remote_status_result",
|
|
5300
|
+
...projectRequestMetadata(msg),
|
|
5027
5301
|
ahead: 0,
|
|
5028
5302
|
behind: 0,
|
|
5029
5303
|
branch: "",
|
|
@@ -5037,6 +5311,7 @@ export class BridgeWebSocketServer {
|
|
|
5037
5311
|
if (!session) {
|
|
5038
5312
|
this.send(ws, {
|
|
5039
5313
|
type: "rewind_preview",
|
|
5314
|
+
sessionId: msg.sessionId,
|
|
5040
5315
|
canRewind: false,
|
|
5041
5316
|
error: `Session ${msg.sessionId} not found`,
|
|
5042
5317
|
});
|
|
@@ -5045,6 +5320,7 @@ export class BridgeWebSocketServer {
|
|
|
5045
5320
|
if (session.provider === "codex") {
|
|
5046
5321
|
this.send(ws, {
|
|
5047
5322
|
type: "rewind_preview",
|
|
5323
|
+
sessionId: msg.sessionId,
|
|
5048
5324
|
canRewind: false,
|
|
5049
5325
|
error: "Codex rewind does not restore files",
|
|
5050
5326
|
});
|
|
@@ -5055,6 +5331,7 @@ export class BridgeWebSocketServer {
|
|
|
5055
5331
|
.then((result) => {
|
|
5056
5332
|
this.send(ws, {
|
|
5057
5333
|
type: "rewind_preview",
|
|
5334
|
+
sessionId: msg.sessionId,
|
|
5058
5335
|
canRewind: result.canRewind,
|
|
5059
5336
|
filesChanged: result.filesChanged,
|
|
5060
5337
|
insertions: result.insertions,
|
|
@@ -5065,6 +5342,7 @@ export class BridgeWebSocketServer {
|
|
|
5065
5342
|
.catch((err) => {
|
|
5066
5343
|
this.send(ws, {
|
|
5067
5344
|
type: "rewind_preview",
|
|
5345
|
+
sessionId: msg.sessionId,
|
|
5068
5346
|
canRewind: false,
|
|
5069
5347
|
error: `Dry run failed: ${err}`,
|
|
5070
5348
|
});
|
|
@@ -5076,6 +5354,7 @@ export class BridgeWebSocketServer {
|
|
|
5076
5354
|
if (!session) {
|
|
5077
5355
|
this.send(ws, {
|
|
5078
5356
|
type: "rewind_result",
|
|
5357
|
+
sessionId: msg.sessionId,
|
|
5079
5358
|
success: false,
|
|
5080
5359
|
mode: msg.mode,
|
|
5081
5360
|
error: `Session ${msg.sessionId} not found`,
|
|
@@ -5086,6 +5365,7 @@ export class BridgeWebSocketServer {
|
|
|
5086
5365
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
5087
5366
|
this.send(ws, {
|
|
5088
5367
|
type: "rewind_result",
|
|
5368
|
+
sessionId: msg.sessionId,
|
|
5089
5369
|
success: false,
|
|
5090
5370
|
mode: msg.mode,
|
|
5091
5371
|
error: errMsg,
|
|
@@ -5104,6 +5384,7 @@ export class BridgeWebSocketServer {
|
|
|
5104
5384
|
if (result.canRewind) {
|
|
5105
5385
|
this.send(ws, {
|
|
5106
5386
|
type: "rewind_result",
|
|
5387
|
+
sessionId: msg.sessionId,
|
|
5107
5388
|
success: true,
|
|
5108
5389
|
mode: "code",
|
|
5109
5390
|
});
|
|
@@ -5111,6 +5392,7 @@ export class BridgeWebSocketServer {
|
|
|
5111
5392
|
else {
|
|
5112
5393
|
this.send(ws, {
|
|
5113
5394
|
type: "rewind_result",
|
|
5395
|
+
sessionId: msg.sessionId,
|
|
5114
5396
|
success: false,
|
|
5115
5397
|
mode: "code",
|
|
5116
5398
|
error: result.error ?? "Cannot rewind files",
|
|
@@ -5126,6 +5408,7 @@ export class BridgeWebSocketServer {
|
|
|
5126
5408
|
this.sessionManager.rewindConversation(msg.sessionId, msg.targetUuid, (newSessionId) => {
|
|
5127
5409
|
this.send(ws, {
|
|
5128
5410
|
type: "rewind_result",
|
|
5411
|
+
sessionId: msg.sessionId,
|
|
5129
5412
|
success: true,
|
|
5130
5413
|
mode: "conversation",
|
|
5131
5414
|
});
|
|
@@ -5157,6 +5440,7 @@ export class BridgeWebSocketServer {
|
|
|
5157
5440
|
if (!result.canRewind) {
|
|
5158
5441
|
this.send(ws, {
|
|
5159
5442
|
type: "rewind_result",
|
|
5443
|
+
sessionId: msg.sessionId,
|
|
5160
5444
|
success: false,
|
|
5161
5445
|
mode: "both",
|
|
5162
5446
|
error: result.error ?? "Cannot rewind files",
|
|
@@ -5168,6 +5452,7 @@ export class BridgeWebSocketServer {
|
|
|
5168
5452
|
this.sessionManager.rewindConversation(msg.sessionId, msg.targetUuid, (newSessionId) => {
|
|
5169
5453
|
this.send(ws, {
|
|
5170
5454
|
type: "rewind_result",
|
|
5455
|
+
sessionId: msg.sessionId,
|
|
5171
5456
|
success: true,
|
|
5172
5457
|
mode: "both",
|
|
5173
5458
|
});
|
|
@@ -5199,6 +5484,7 @@ export class BridgeWebSocketServer {
|
|
|
5199
5484
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
5200
5485
|
this.send(ws, {
|
|
5201
5486
|
type: "error",
|
|
5487
|
+
sessionId: msg.sessionId,
|
|
5202
5488
|
message: errMsg,
|
|
5203
5489
|
errorCode: "fork_failed",
|
|
5204
5490
|
});
|
|
@@ -5244,6 +5530,8 @@ export class BridgeWebSocketServer {
|
|
|
5244
5530
|
const info = this.galleryStore.metaToInfo(meta);
|
|
5245
5531
|
this.send(ws, {
|
|
5246
5532
|
type: "screenshot_result",
|
|
5533
|
+
...projectRequestMetadata(msg),
|
|
5534
|
+
sessionId: msg.sessionId,
|
|
5247
5535
|
success: true,
|
|
5248
5536
|
image: info,
|
|
5249
5537
|
});
|
|
@@ -5253,6 +5541,8 @@ export class BridgeWebSocketServer {
|
|
|
5253
5541
|
}
|
|
5254
5542
|
this.send(ws, {
|
|
5255
5543
|
type: "screenshot_result",
|
|
5544
|
+
...projectRequestMetadata(msg),
|
|
5545
|
+
sessionId: msg.sessionId,
|
|
5256
5546
|
success: false,
|
|
5257
5547
|
error: "Failed to save screenshot to gallery",
|
|
5258
5548
|
});
|
|
@@ -5265,6 +5555,8 @@ export class BridgeWebSocketServer {
|
|
|
5265
5555
|
.catch((err) => {
|
|
5266
5556
|
this.send(ws, {
|
|
5267
5557
|
type: "screenshot_result",
|
|
5558
|
+
...projectRequestMetadata(msg),
|
|
5559
|
+
sessionId: msg.sessionId,
|
|
5268
5560
|
success: false,
|
|
5269
5561
|
error: err instanceof Error ? err.message : String(err),
|
|
5270
5562
|
});
|
|
@@ -5817,6 +6109,7 @@ export class BridgeWebSocketServer {
|
|
|
5817
6109
|
defaultCodexProfile: this.defaultCodexProfile,
|
|
5818
6110
|
codexAutoReviewDisabled: this.codexAutoReviewDisabled,
|
|
5819
6111
|
bridgeVersion: getPackageVersion(),
|
|
6112
|
+
protocolCapabilities: ["project_request_correlation_v1"],
|
|
5820
6113
|
});
|
|
5821
6114
|
}
|
|
5822
6115
|
sendPromptHistoryStatus(ws) {
|
|
@@ -5849,6 +6142,7 @@ export class BridgeWebSocketServer {
|
|
|
5849
6142
|
defaultCodexProfile: this.defaultCodexProfile,
|
|
5850
6143
|
codexAutoReviewDisabled: this.codexAutoReviewDisabled,
|
|
5851
6144
|
bridgeVersion: getPackageVersion(),
|
|
6145
|
+
protocolCapabilities: ["project_request_correlation_v1"],
|
|
5852
6146
|
});
|
|
5853
6147
|
}
|
|
5854
6148
|
broadcastPromptHistoryStatus() {
|
|
@@ -6740,7 +7034,7 @@ export class BridgeWebSocketServer {
|
|
|
6740
7034
|
if (!compatibleMsg)
|
|
6741
7035
|
return;
|
|
6742
7036
|
const sessionId = this.extractSessionIdFromServerMessage(compatibleMsg);
|
|
6743
|
-
if (sessionId) {
|
|
7037
|
+
if (sessionId && this.debugEvents.has(sessionId)) {
|
|
6744
7038
|
this.recordDebugEvent(sessionId, {
|
|
6745
7039
|
direction: "outgoing",
|
|
6746
7040
|
channel: "ws",
|