@junctionpanel/server 0.1.52 → 0.1.54
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/server/client/daemon-client.d.ts +17 -1
- package/dist/server/client/daemon-client.d.ts.map +1 -1
- package/dist/server/client/daemon-client.js +147 -6
- package/dist/server/client/daemon-client.js.map +1 -1
- package/dist/server/server/agent/agent-metadata-generator.d.ts.map +1 -1
- package/dist/server/server/agent/agent-metadata-generator.js +54 -17
- package/dist/server/server/agent/agent-metadata-generator.js.map +1 -1
- package/dist/server/server/file-explorer/service.d.ts +6 -1
- package/dist/server/server/file-explorer/service.d.ts.map +1 -1
- package/dist/server/server/file-explorer/service.js +72 -23
- package/dist/server/server/file-explorer/service.js.map +1 -1
- package/dist/server/server/session.d.ts +25 -0
- package/dist/server/server/session.d.ts.map +1 -1
- package/dist/server/server/session.js +589 -86
- package/dist/server/server/session.js.map +1 -1
- package/dist/server/server/tool-call-preview.d.ts.map +1 -1
- package/dist/server/server/tool-call-preview.js +5 -3
- package/dist/server/server/tool-call-preview.js.map +1 -1
- package/dist/server/shared/messages.d.ts +7614 -2138
- package/dist/server/shared/messages.d.ts.map +1 -1
- package/dist/server/shared/messages.js +45 -0
- package/dist/server/shared/messages.js.map +1 -1
- package/dist/server/utils/checkout-git.d.ts.map +1 -1
- package/dist/server/utils/checkout-git.js +28 -3
- package/dist/server/utils/checkout-git.js.map +1 -1
- package/dist/server/utils/worktree.d.ts +1 -1
- package/dist/server/utils/worktree.d.ts.map +1 -1
- package/dist/server/utils/worktree.js +7 -1
- package/dist/server/utils/worktree.js.map +1 -1
- package/package.json +2 -2
|
@@ -51,6 +51,10 @@ const pendingAgentMessageExecutions = new Map();
|
|
|
51
51
|
const DEFAULT_AGENT_PROVIDER = AGENT_PROVIDER_IDS[0];
|
|
52
52
|
const CHECKOUT_DIFF_WATCH_DEBOUNCE_MS = 150;
|
|
53
53
|
const CHECKOUT_DIFF_FALLBACK_REFRESH_MS = 5000;
|
|
54
|
+
const WORKSPACE_STATUS_WATCH_DEBOUNCE_MS = 250;
|
|
55
|
+
const WORKSPACE_STATUS_GIT_REFRESH_MS = 3000;
|
|
56
|
+
const WORKSPACE_STATUS_PR_ACTIVE_REFRESH_MS = 15000;
|
|
57
|
+
const WORKSPACE_STATUS_PR_PASSIVE_REFRESH_MS = 60000;
|
|
54
58
|
const TERMINAL_STREAM_WINDOW_BYTES = 256 * 1024;
|
|
55
59
|
const TERMINAL_STREAM_MAX_PENDING_BYTES = 2 * 1024 * 1024;
|
|
56
60
|
const TERMINAL_STREAM_MAX_PENDING_CHUNKS = 2048;
|
|
@@ -119,6 +123,8 @@ export class Session {
|
|
|
119
123
|
this.clientActivity = null;
|
|
120
124
|
this.MOBILE_BACKGROUND_STREAM_GRACE_MS = 60000;
|
|
121
125
|
this.subscribedTerminalDirectories = new Set();
|
|
126
|
+
this.workspaceStatusSubscriptions = new Map();
|
|
127
|
+
this.workspaceStatusTargets = new Map();
|
|
122
128
|
this.unsubscribeTerminalsChanged = null;
|
|
123
129
|
this.terminalSubscriptions = new Map();
|
|
124
130
|
this.terminalExitSubscriptions = new Map();
|
|
@@ -863,6 +869,12 @@ export class Session {
|
|
|
863
869
|
case 'checkout_status_request':
|
|
864
870
|
await this.handleCheckoutStatusRequest(msg);
|
|
865
871
|
break;
|
|
872
|
+
case 'subscribe_workspace_status_request':
|
|
873
|
+
await this.handleSubscribeWorkspaceStatusRequest(msg);
|
|
874
|
+
break;
|
|
875
|
+
case 'unsubscribe_workspace_status_request':
|
|
876
|
+
this.handleUnsubscribeWorkspaceStatusRequest(msg);
|
|
877
|
+
break;
|
|
866
878
|
case 'validate_branch_request':
|
|
867
879
|
await this.handleValidateBranchRequest(msg);
|
|
868
880
|
break;
|
|
@@ -2702,101 +2714,191 @@ export class Session {
|
|
|
2702
2714
|
throw error;
|
|
2703
2715
|
}
|
|
2704
2716
|
}
|
|
2717
|
+
buildCheckoutStatusPayload(cwd, status) {
|
|
2718
|
+
if (!status.isGit) {
|
|
2719
|
+
return {
|
|
2720
|
+
cwd,
|
|
2721
|
+
isGit: false,
|
|
2722
|
+
repoRoot: null,
|
|
2723
|
+
currentBranch: null,
|
|
2724
|
+
isDirty: null,
|
|
2725
|
+
baseRef: null,
|
|
2726
|
+
aheadBehind: null,
|
|
2727
|
+
aheadOfOrigin: null,
|
|
2728
|
+
behindOfOrigin: null,
|
|
2729
|
+
hasUpstream: false,
|
|
2730
|
+
upstreamBranch: null,
|
|
2731
|
+
hasRemote: false,
|
|
2732
|
+
remoteUrl: null,
|
|
2733
|
+
isJunctionOwnedWorktree: false,
|
|
2734
|
+
error: null,
|
|
2735
|
+
};
|
|
2736
|
+
}
|
|
2737
|
+
if (status.isJunctionOwnedWorktree) {
|
|
2738
|
+
return {
|
|
2739
|
+
cwd,
|
|
2740
|
+
isGit: true,
|
|
2741
|
+
repoRoot: status.repoRoot ?? null,
|
|
2742
|
+
mainRepoRoot: status.mainRepoRoot,
|
|
2743
|
+
currentBranch: status.currentBranch ?? null,
|
|
2744
|
+
isDirty: status.isDirty ?? null,
|
|
2745
|
+
baseRef: status.baseRef,
|
|
2746
|
+
aheadBehind: status.aheadBehind ?? null,
|
|
2747
|
+
aheadOfOrigin: status.aheadOfOrigin ?? null,
|
|
2748
|
+
behindOfOrigin: status.behindOfOrigin ?? null,
|
|
2749
|
+
hasUpstream: status.hasUpstream,
|
|
2750
|
+
upstreamBranch: status.upstreamBranch ?? null,
|
|
2751
|
+
hasRemote: status.hasRemote,
|
|
2752
|
+
remoteUrl: status.remoteUrl,
|
|
2753
|
+
isJunctionOwnedWorktree: true,
|
|
2754
|
+
error: null,
|
|
2755
|
+
};
|
|
2756
|
+
}
|
|
2757
|
+
return {
|
|
2758
|
+
cwd,
|
|
2759
|
+
isGit: true,
|
|
2760
|
+
repoRoot: status.repoRoot ?? null,
|
|
2761
|
+
currentBranch: status.currentBranch ?? null,
|
|
2762
|
+
isDirty: status.isDirty ?? null,
|
|
2763
|
+
baseRef: status.baseRef ?? null,
|
|
2764
|
+
aheadBehind: status.aheadBehind ?? null,
|
|
2765
|
+
aheadOfOrigin: status.aheadOfOrigin ?? null,
|
|
2766
|
+
behindOfOrigin: status.behindOfOrigin ?? null,
|
|
2767
|
+
hasUpstream: status.hasUpstream,
|
|
2768
|
+
upstreamBranch: status.upstreamBranch ?? null,
|
|
2769
|
+
hasRemote: status.hasRemote,
|
|
2770
|
+
remoteUrl: status.remoteUrl,
|
|
2771
|
+
isJunctionOwnedWorktree: false,
|
|
2772
|
+
error: null,
|
|
2773
|
+
};
|
|
2774
|
+
}
|
|
2775
|
+
buildCheckoutStatusErrorPayload(cwd, error) {
|
|
2776
|
+
return {
|
|
2777
|
+
cwd,
|
|
2778
|
+
isGit: false,
|
|
2779
|
+
repoRoot: null,
|
|
2780
|
+
currentBranch: null,
|
|
2781
|
+
isDirty: null,
|
|
2782
|
+
baseRef: null,
|
|
2783
|
+
aheadBehind: null,
|
|
2784
|
+
aheadOfOrigin: null,
|
|
2785
|
+
behindOfOrigin: null,
|
|
2786
|
+
hasUpstream: false,
|
|
2787
|
+
upstreamBranch: null,
|
|
2788
|
+
hasRemote: false,
|
|
2789
|
+
remoteUrl: null,
|
|
2790
|
+
isJunctionOwnedWorktree: false,
|
|
2791
|
+
error: this.toCheckoutError(error),
|
|
2792
|
+
requestId: '',
|
|
2793
|
+
};
|
|
2794
|
+
}
|
|
2795
|
+
buildCheckoutStatusLitePayload(cwd, repoRoot, status) {
|
|
2796
|
+
if (!status.isGit) {
|
|
2797
|
+
return {
|
|
2798
|
+
cwd,
|
|
2799
|
+
isGit: false,
|
|
2800
|
+
repoRoot: null,
|
|
2801
|
+
currentBranch: null,
|
|
2802
|
+
isDirty: null,
|
|
2803
|
+
baseRef: null,
|
|
2804
|
+
aheadBehind: null,
|
|
2805
|
+
aheadOfOrigin: null,
|
|
2806
|
+
behindOfOrigin: null,
|
|
2807
|
+
hasUpstream: false,
|
|
2808
|
+
upstreamBranch: null,
|
|
2809
|
+
hasRemote: Boolean(status.remoteUrl),
|
|
2810
|
+
remoteUrl: status.remoteUrl,
|
|
2811
|
+
isJunctionOwnedWorktree: false,
|
|
2812
|
+
error: null,
|
|
2813
|
+
};
|
|
2814
|
+
}
|
|
2815
|
+
return {
|
|
2816
|
+
cwd,
|
|
2817
|
+
isGit: true,
|
|
2818
|
+
repoRoot,
|
|
2819
|
+
currentBranch: status.currentBranch ?? null,
|
|
2820
|
+
isDirty: false,
|
|
2821
|
+
baseRef: null,
|
|
2822
|
+
aheadBehind: null,
|
|
2823
|
+
aheadOfOrigin: null,
|
|
2824
|
+
behindOfOrigin: null,
|
|
2825
|
+
hasUpstream: false,
|
|
2826
|
+
upstreamBranch: null,
|
|
2827
|
+
hasRemote: Boolean(status.remoteUrl),
|
|
2828
|
+
remoteUrl: status.remoteUrl,
|
|
2829
|
+
isJunctionOwnedWorktree: false,
|
|
2830
|
+
error: null,
|
|
2831
|
+
};
|
|
2832
|
+
}
|
|
2833
|
+
toWorkspaceGitStatus(payload) {
|
|
2834
|
+
const normalizedPayload = payload;
|
|
2835
|
+
const { cwd: _cwd, error: _error, requestId: _requestId, ...git } = normalizedPayload;
|
|
2836
|
+
return git;
|
|
2837
|
+
}
|
|
2838
|
+
async resolveWorkspaceGitSnapshot(cwd, options) {
|
|
2839
|
+
try {
|
|
2840
|
+
const payload = await (async () => {
|
|
2841
|
+
if (!options?.lite) {
|
|
2842
|
+
return this.buildCheckoutStatusPayload(cwd, await getCheckoutStatus(expandTilde(cwd), { junctionHome: this.junctionHome }));
|
|
2843
|
+
}
|
|
2844
|
+
const liteStatus = await getCheckoutStatusLite(expandTilde(cwd), {
|
|
2845
|
+
junctionHome: this.junctionHome,
|
|
2846
|
+
});
|
|
2847
|
+
if (liteStatus.isGit && liteStatus.isJunctionOwnedWorktree) {
|
|
2848
|
+
return this.buildCheckoutStatusPayload(cwd, await getCheckoutStatus(expandTilde(cwd), { junctionHome: this.junctionHome }));
|
|
2849
|
+
}
|
|
2850
|
+
return this.buildCheckoutStatusLitePayload(cwd, options.repoRoot ?? cwd, liteStatus);
|
|
2851
|
+
})();
|
|
2852
|
+
return {
|
|
2853
|
+
git: this.toWorkspaceGitStatus(payload),
|
|
2854
|
+
gitError: payload.error,
|
|
2855
|
+
};
|
|
2856
|
+
}
|
|
2857
|
+
catch (error) {
|
|
2858
|
+
const payload = this.buildCheckoutStatusErrorPayload(cwd, error);
|
|
2859
|
+
return {
|
|
2860
|
+
git: this.toWorkspaceGitStatus(payload),
|
|
2861
|
+
gitError: payload.error,
|
|
2862
|
+
};
|
|
2863
|
+
}
|
|
2864
|
+
}
|
|
2865
|
+
async resolveWorkspacePullRequestSnapshot(cwd, remoteName) {
|
|
2866
|
+
try {
|
|
2867
|
+
const prStatus = await getPullRequestStatus(expandTilde(cwd), {
|
|
2868
|
+
...(remoteName ? { remoteName } : {}),
|
|
2869
|
+
});
|
|
2870
|
+
return {
|
|
2871
|
+
pullRequest: prStatus.status,
|
|
2872
|
+
pullRequestError: null,
|
|
2873
|
+
githubFeaturesEnabled: prStatus.githubFeaturesEnabled,
|
|
2874
|
+
};
|
|
2875
|
+
}
|
|
2876
|
+
catch (error) {
|
|
2877
|
+
return {
|
|
2878
|
+
pullRequest: null,
|
|
2879
|
+
pullRequestError: this.toCheckoutError(error),
|
|
2880
|
+
githubFeaturesEnabled: true,
|
|
2881
|
+
};
|
|
2882
|
+
}
|
|
2883
|
+
}
|
|
2705
2884
|
async handleCheckoutStatusRequest(msg) {
|
|
2706
2885
|
const { cwd, requestId } = msg;
|
|
2707
|
-
const resolvedCwd = expandTilde(cwd);
|
|
2708
2886
|
try {
|
|
2709
|
-
const status = await getCheckoutStatus(
|
|
2710
|
-
if (!status.isGit) {
|
|
2711
|
-
this.emit({
|
|
2712
|
-
type: 'checkout_status_response',
|
|
2713
|
-
payload: {
|
|
2714
|
-
cwd,
|
|
2715
|
-
isGit: false,
|
|
2716
|
-
repoRoot: null,
|
|
2717
|
-
currentBranch: null,
|
|
2718
|
-
isDirty: null,
|
|
2719
|
-
baseRef: null,
|
|
2720
|
-
aheadBehind: null,
|
|
2721
|
-
aheadOfOrigin: null,
|
|
2722
|
-
behindOfOrigin: null,
|
|
2723
|
-
hasUpstream: false,
|
|
2724
|
-
upstreamBranch: null,
|
|
2725
|
-
hasRemote: false,
|
|
2726
|
-
remoteUrl: null,
|
|
2727
|
-
isJunctionOwnedWorktree: false,
|
|
2728
|
-
error: null,
|
|
2729
|
-
requestId,
|
|
2730
|
-
},
|
|
2731
|
-
});
|
|
2732
|
-
return;
|
|
2733
|
-
}
|
|
2734
|
-
if (status.isJunctionOwnedWorktree) {
|
|
2735
|
-
this.emit({
|
|
2736
|
-
type: 'checkout_status_response',
|
|
2737
|
-
payload: {
|
|
2738
|
-
cwd,
|
|
2739
|
-
isGit: true,
|
|
2740
|
-
repoRoot: status.repoRoot ?? null,
|
|
2741
|
-
mainRepoRoot: status.mainRepoRoot,
|
|
2742
|
-
currentBranch: status.currentBranch ?? null,
|
|
2743
|
-
isDirty: status.isDirty ?? null,
|
|
2744
|
-
baseRef: status.baseRef,
|
|
2745
|
-
aheadBehind: status.aheadBehind ?? null,
|
|
2746
|
-
aheadOfOrigin: status.aheadOfOrigin ?? null,
|
|
2747
|
-
behindOfOrigin: status.behindOfOrigin ?? null,
|
|
2748
|
-
hasUpstream: status.hasUpstream,
|
|
2749
|
-
upstreamBranch: status.upstreamBranch ?? null,
|
|
2750
|
-
hasRemote: status.hasRemote,
|
|
2751
|
-
remoteUrl: status.remoteUrl,
|
|
2752
|
-
isJunctionOwnedWorktree: true,
|
|
2753
|
-
error: null,
|
|
2754
|
-
requestId,
|
|
2755
|
-
},
|
|
2756
|
-
});
|
|
2757
|
-
return;
|
|
2758
|
-
}
|
|
2887
|
+
const status = await getCheckoutStatus(expandTilde(cwd), { junctionHome: this.junctionHome });
|
|
2759
2888
|
this.emit({
|
|
2760
2889
|
type: 'checkout_status_response',
|
|
2761
2890
|
payload: {
|
|
2762
|
-
cwd,
|
|
2763
|
-
isGit: true,
|
|
2764
|
-
repoRoot: status.repoRoot ?? null,
|
|
2765
|
-
currentBranch: status.currentBranch ?? null,
|
|
2766
|
-
isDirty: status.isDirty ?? null,
|
|
2767
|
-
baseRef: status.baseRef ?? null,
|
|
2768
|
-
aheadBehind: status.aheadBehind ?? null,
|
|
2769
|
-
aheadOfOrigin: status.aheadOfOrigin ?? null,
|
|
2770
|
-
behindOfOrigin: status.behindOfOrigin ?? null,
|
|
2771
|
-
hasUpstream: status.hasUpstream,
|
|
2772
|
-
upstreamBranch: status.upstreamBranch ?? null,
|
|
2773
|
-
hasRemote: status.hasRemote,
|
|
2774
|
-
remoteUrl: status.remoteUrl,
|
|
2775
|
-
isJunctionOwnedWorktree: false,
|
|
2776
|
-
error: null,
|
|
2891
|
+
...this.buildCheckoutStatusPayload(cwd, status),
|
|
2777
2892
|
requestId,
|
|
2778
2893
|
},
|
|
2779
2894
|
});
|
|
2780
2895
|
}
|
|
2781
2896
|
catch (error) {
|
|
2897
|
+
const payload = this.buildCheckoutStatusErrorPayload(cwd, error);
|
|
2782
2898
|
this.emit({
|
|
2783
2899
|
type: 'checkout_status_response',
|
|
2784
2900
|
payload: {
|
|
2785
|
-
|
|
2786
|
-
isGit: false,
|
|
2787
|
-
repoRoot: null,
|
|
2788
|
-
currentBranch: null,
|
|
2789
|
-
isDirty: null,
|
|
2790
|
-
baseRef: null,
|
|
2791
|
-
aheadBehind: null,
|
|
2792
|
-
aheadOfOrigin: null,
|
|
2793
|
-
behindOfOrigin: null,
|
|
2794
|
-
hasUpstream: false,
|
|
2795
|
-
upstreamBranch: null,
|
|
2796
|
-
hasRemote: false,
|
|
2797
|
-
remoteUrl: null,
|
|
2798
|
-
isJunctionOwnedWorktree: false,
|
|
2799
|
-
error: this.toCheckoutError(error),
|
|
2901
|
+
...payload,
|
|
2800
2902
|
requestId,
|
|
2801
2903
|
},
|
|
2802
2904
|
});
|
|
@@ -3114,6 +3216,384 @@ export class Session {
|
|
|
3114
3216
|
});
|
|
3115
3217
|
}
|
|
3116
3218
|
}
|
|
3219
|
+
buildWorkspaceStatusTargetKey(cwd, remoteName) {
|
|
3220
|
+
return JSON.stringify([cwd, remoteName ?? '']);
|
|
3221
|
+
}
|
|
3222
|
+
closeWorkspaceStatusWatchTarget(target) {
|
|
3223
|
+
if (target.debounceTimer) {
|
|
3224
|
+
clearTimeout(target.debounceTimer);
|
|
3225
|
+
target.debounceTimer = null;
|
|
3226
|
+
}
|
|
3227
|
+
if (target.gitRefreshInterval) {
|
|
3228
|
+
clearInterval(target.gitRefreshInterval);
|
|
3229
|
+
target.gitRefreshInterval = null;
|
|
3230
|
+
}
|
|
3231
|
+
if (target.prRefreshInterval) {
|
|
3232
|
+
clearInterval(target.prRefreshInterval);
|
|
3233
|
+
target.prRefreshInterval = null;
|
|
3234
|
+
}
|
|
3235
|
+
for (const watcher of target.watchers) {
|
|
3236
|
+
watcher.close();
|
|
3237
|
+
}
|
|
3238
|
+
target.watchers = [];
|
|
3239
|
+
}
|
|
3240
|
+
workspaceStatusHasActiveSubscribers(target) {
|
|
3241
|
+
for (const mode of target.subscriptions.values()) {
|
|
3242
|
+
if (mode === 'active') {
|
|
3243
|
+
return true;
|
|
3244
|
+
}
|
|
3245
|
+
}
|
|
3246
|
+
return false;
|
|
3247
|
+
}
|
|
3248
|
+
hasWorkspaceStatusTarget(target) {
|
|
3249
|
+
return this.workspaceStatusTargets.get(target.key) === target && target.subscriptions.size > 0;
|
|
3250
|
+
}
|
|
3251
|
+
workspaceStatusGitIdentityChanged(previousSnapshot, nextGit) {
|
|
3252
|
+
if (!previousSnapshot) {
|
|
3253
|
+
return false;
|
|
3254
|
+
}
|
|
3255
|
+
const previousGit = previousSnapshot.git;
|
|
3256
|
+
if (previousGit.isGit !== nextGit.isGit) {
|
|
3257
|
+
return true;
|
|
3258
|
+
}
|
|
3259
|
+
if (!previousGit.isGit || !nextGit.isGit) {
|
|
3260
|
+
return false;
|
|
3261
|
+
}
|
|
3262
|
+
return (previousGit.currentBranch !== nextGit.currentBranch
|
|
3263
|
+
|| previousGit.repoRoot !== nextGit.repoRoot
|
|
3264
|
+
|| previousGit.isJunctionOwnedWorktree !== nextGit.isJunctionOwnedWorktree
|
|
3265
|
+
|| ((previousGit.isJunctionOwnedWorktree ? previousGit.mainRepoRoot : null)
|
|
3266
|
+
!== (nextGit.isJunctionOwnedWorktree ? nextGit.mainRepoRoot : null)));
|
|
3267
|
+
}
|
|
3268
|
+
updateWorkspaceStatusPrPolling(target) {
|
|
3269
|
+
if (target.prRefreshInterval) {
|
|
3270
|
+
clearInterval(target.prRefreshInterval);
|
|
3271
|
+
target.prRefreshInterval = null;
|
|
3272
|
+
}
|
|
3273
|
+
if (target.subscriptions.size === 0) {
|
|
3274
|
+
return;
|
|
3275
|
+
}
|
|
3276
|
+
const intervalMs = this.workspaceStatusHasActiveSubscribers(target)
|
|
3277
|
+
? WORKSPACE_STATUS_PR_ACTIVE_REFRESH_MS
|
|
3278
|
+
: WORKSPACE_STATUS_PR_PASSIVE_REFRESH_MS;
|
|
3279
|
+
target.prRefreshInterval = setInterval(() => {
|
|
3280
|
+
this.scheduleWorkspaceStatusTargetRefresh(target, {
|
|
3281
|
+
includePr: true,
|
|
3282
|
+
debounce: false,
|
|
3283
|
+
});
|
|
3284
|
+
}, intervalMs);
|
|
3285
|
+
}
|
|
3286
|
+
updateWorkspaceStatusGitPolling(target) {
|
|
3287
|
+
if (target.gitRefreshInterval) {
|
|
3288
|
+
clearInterval(target.gitRefreshInterval);
|
|
3289
|
+
target.gitRefreshInterval = null;
|
|
3290
|
+
}
|
|
3291
|
+
if (!this.workspaceStatusHasActiveSubscribers(target)) {
|
|
3292
|
+
return;
|
|
3293
|
+
}
|
|
3294
|
+
target.gitRefreshInterval = setInterval(() => {
|
|
3295
|
+
this.scheduleWorkspaceStatusTargetRefresh(target, {
|
|
3296
|
+
includePr: false,
|
|
3297
|
+
debounce: false,
|
|
3298
|
+
});
|
|
3299
|
+
}, WORKSPACE_STATUS_GIT_REFRESH_MS);
|
|
3300
|
+
}
|
|
3301
|
+
removeWorkspaceStatusSubscription(subscriptionId) {
|
|
3302
|
+
const subscription = this.workspaceStatusSubscriptions.get(subscriptionId);
|
|
3303
|
+
if (!subscription) {
|
|
3304
|
+
return;
|
|
3305
|
+
}
|
|
3306
|
+
this.workspaceStatusSubscriptions.delete(subscriptionId);
|
|
3307
|
+
const target = this.workspaceStatusTargets.get(subscription.targetKey);
|
|
3308
|
+
if (!target) {
|
|
3309
|
+
return;
|
|
3310
|
+
}
|
|
3311
|
+
target.subscriptions.delete(subscriptionId);
|
|
3312
|
+
if (target.subscriptions.size === 0) {
|
|
3313
|
+
this.closeWorkspaceStatusWatchTarget(target);
|
|
3314
|
+
this.workspaceStatusTargets.delete(subscription.targetKey);
|
|
3315
|
+
return;
|
|
3316
|
+
}
|
|
3317
|
+
this.updateWorkspaceStatusGitPolling(target);
|
|
3318
|
+
this.updateWorkspaceStatusPrPolling(target);
|
|
3319
|
+
}
|
|
3320
|
+
scheduleWorkspaceStatusTargetRefresh(target, options) {
|
|
3321
|
+
const includePr = options?.includePr ?? false;
|
|
3322
|
+
const shouldDebounce = options?.debounce ?? true;
|
|
3323
|
+
if (!shouldDebounce) {
|
|
3324
|
+
void this.refreshWorkspaceStatusTarget(target, { includePr });
|
|
3325
|
+
return;
|
|
3326
|
+
}
|
|
3327
|
+
if (target.debounceTimer) {
|
|
3328
|
+
clearTimeout(target.debounceTimer);
|
|
3329
|
+
}
|
|
3330
|
+
if (includePr) {
|
|
3331
|
+
target.refreshIncludesPr = true;
|
|
3332
|
+
}
|
|
3333
|
+
target.debounceTimer = setTimeout(() => {
|
|
3334
|
+
target.debounceTimer = null;
|
|
3335
|
+
void this.refreshWorkspaceStatusTarget(target, {
|
|
3336
|
+
includePr: includePr || target.refreshIncludesPr,
|
|
3337
|
+
});
|
|
3338
|
+
}, WORKSPACE_STATUS_WATCH_DEBOUNCE_MS);
|
|
3339
|
+
}
|
|
3340
|
+
workspaceStatusSnapshotFingerprint(snapshot) {
|
|
3341
|
+
return JSON.stringify({
|
|
3342
|
+
cwd: snapshot.cwd,
|
|
3343
|
+
remoteName: snapshot.remoteName,
|
|
3344
|
+
git: snapshot.git,
|
|
3345
|
+
gitError: snapshot.gitError,
|
|
3346
|
+
pullRequest: snapshot.pullRequest,
|
|
3347
|
+
pullRequestError: snapshot.pullRequestError,
|
|
3348
|
+
githubFeaturesEnabled: snapshot.githubFeaturesEnabled,
|
|
3349
|
+
});
|
|
3350
|
+
}
|
|
3351
|
+
emitWorkspaceStatusChanged(_target, snapshot) {
|
|
3352
|
+
this.emit({
|
|
3353
|
+
type: 'workspace_status_changed',
|
|
3354
|
+
payload: snapshot,
|
|
3355
|
+
});
|
|
3356
|
+
}
|
|
3357
|
+
async computeWorkspaceStatusSnapshot(target, options) {
|
|
3358
|
+
const hasExplicitIncludePr = options != null && 'includePr' in options;
|
|
3359
|
+
const includePr = hasExplicitIncludePr ? Boolean(options?.includePr) : !target.latestPayload;
|
|
3360
|
+
const fullGit = options?.fullGit ?? this.workspaceStatusHasActiveSubscribers(target);
|
|
3361
|
+
const gitSnapshot = await this.resolveWorkspaceGitSnapshot(target.cwd, {
|
|
3362
|
+
lite: !fullGit,
|
|
3363
|
+
repoRoot: target.diffCwd || target.cwd,
|
|
3364
|
+
});
|
|
3365
|
+
const gitIdentityChanged = this.workspaceStatusGitIdentityChanged(target.latestPayload, gitSnapshot.git);
|
|
3366
|
+
let pullRequest = target.latestPayload?.pullRequest ?? null;
|
|
3367
|
+
let pullRequestError = target.latestPayload?.pullRequestError ?? null;
|
|
3368
|
+
let githubFeaturesEnabled = target.latestPayload?.githubFeaturesEnabled ?? false;
|
|
3369
|
+
if (!gitSnapshot.git.isGit) {
|
|
3370
|
+
pullRequest = null;
|
|
3371
|
+
pullRequestError = null;
|
|
3372
|
+
githubFeaturesEnabled = false;
|
|
3373
|
+
}
|
|
3374
|
+
else if (includePr) {
|
|
3375
|
+
const prSnapshot = await this.resolveWorkspacePullRequestSnapshot(target.cwd, target.remoteName);
|
|
3376
|
+
pullRequest = prSnapshot.pullRequest;
|
|
3377
|
+
pullRequestError = prSnapshot.pullRequestError;
|
|
3378
|
+
githubFeaturesEnabled = prSnapshot.githubFeaturesEnabled;
|
|
3379
|
+
}
|
|
3380
|
+
else if (gitIdentityChanged) {
|
|
3381
|
+
pullRequest = null;
|
|
3382
|
+
pullRequestError = null;
|
|
3383
|
+
githubFeaturesEnabled = false;
|
|
3384
|
+
}
|
|
3385
|
+
return {
|
|
3386
|
+
cwd: target.cwd,
|
|
3387
|
+
remoteName: target.remoteName,
|
|
3388
|
+
git: gitSnapshot.git,
|
|
3389
|
+
gitError: gitSnapshot.gitError,
|
|
3390
|
+
pullRequest,
|
|
3391
|
+
pullRequestError,
|
|
3392
|
+
githubFeaturesEnabled,
|
|
3393
|
+
refreshedAt: new Date().toISOString(),
|
|
3394
|
+
};
|
|
3395
|
+
}
|
|
3396
|
+
async refreshWorkspaceStatusTarget(target, options) {
|
|
3397
|
+
if (target.refreshPromise) {
|
|
3398
|
+
target.refreshQueued = true;
|
|
3399
|
+
target.refreshIncludesPr = target.refreshIncludesPr || Boolean(options?.includePr);
|
|
3400
|
+
return;
|
|
3401
|
+
}
|
|
3402
|
+
target.refreshPromise = (async () => {
|
|
3403
|
+
do {
|
|
3404
|
+
const hasExplicitIncludePr = options != null && 'includePr' in options;
|
|
3405
|
+
const fullGit = this.workspaceStatusHasActiveSubscribers(target);
|
|
3406
|
+
const previousHasLoadedPullRequest = target.hasLoadedPullRequest;
|
|
3407
|
+
const includePr = target.refreshIncludesPr
|
|
3408
|
+
|| (hasExplicitIncludePr ? Boolean(options?.includePr) : !target.latestPayload);
|
|
3409
|
+
target.refreshQueued = false;
|
|
3410
|
+
target.refreshIncludesPr = false;
|
|
3411
|
+
const snapshot = await this.computeWorkspaceStatusSnapshot(target, {
|
|
3412
|
+
includePr,
|
|
3413
|
+
fullGit,
|
|
3414
|
+
});
|
|
3415
|
+
if (!this.hasWorkspaceStatusTarget(target)) {
|
|
3416
|
+
return;
|
|
3417
|
+
}
|
|
3418
|
+
const activeSubscribersPresent = this.workspaceStatusHasActiveSubscribers(target);
|
|
3419
|
+
const gitIdentityChanged = this.workspaceStatusGitIdentityChanged(target.latestPayload, snapshot.git);
|
|
3420
|
+
const needsPrReplay = (!includePr && target.refreshIncludesPr)
|
|
3421
|
+
|| (!includePr && fullGit && activeSubscribersPresent && gitIdentityChanged);
|
|
3422
|
+
const needsFullGitReplay = !fullGit && activeSubscribersPresent;
|
|
3423
|
+
if (needsPrReplay
|
|
3424
|
+
|| needsFullGitReplay) {
|
|
3425
|
+
target.refreshQueued = true;
|
|
3426
|
+
target.refreshIncludesPr = target.refreshIncludesPr || needsPrReplay || needsFullGitReplay;
|
|
3427
|
+
continue;
|
|
3428
|
+
}
|
|
3429
|
+
target.latestPayload = snapshot;
|
|
3430
|
+
target.hasLoadedPullRequest =
|
|
3431
|
+
!snapshot.git.isGit
|
|
3432
|
+
|| includePr
|
|
3433
|
+
|| (previousHasLoadedPullRequest && !gitIdentityChanged);
|
|
3434
|
+
target.latestPayloadHasFullGitData = !snapshot.git.isGit || fullGit;
|
|
3435
|
+
const fingerprint = this.workspaceStatusSnapshotFingerprint(snapshot);
|
|
3436
|
+
if (fingerprint !== target.latestFingerprint) {
|
|
3437
|
+
target.latestFingerprint = fingerprint;
|
|
3438
|
+
this.emitWorkspaceStatusChanged(target, snapshot);
|
|
3439
|
+
}
|
|
3440
|
+
} while (target.refreshQueued);
|
|
3441
|
+
})();
|
|
3442
|
+
try {
|
|
3443
|
+
await target.refreshPromise;
|
|
3444
|
+
}
|
|
3445
|
+
finally {
|
|
3446
|
+
target.refreshPromise = null;
|
|
3447
|
+
}
|
|
3448
|
+
}
|
|
3449
|
+
async ensureWorkspaceStatusWatchTarget(cwd, remoteName) {
|
|
3450
|
+
const targetKey = this.buildWorkspaceStatusTargetKey(cwd, remoteName);
|
|
3451
|
+
const existing = this.workspaceStatusTargets.get(targetKey);
|
|
3452
|
+
if (existing) {
|
|
3453
|
+
return existing;
|
|
3454
|
+
}
|
|
3455
|
+
const watchRoot = await this.resolveCheckoutWatchRoot(cwd);
|
|
3456
|
+
const target = {
|
|
3457
|
+
key: targetKey,
|
|
3458
|
+
cwd,
|
|
3459
|
+
diffCwd: watchRoot ?? cwd,
|
|
3460
|
+
remoteName,
|
|
3461
|
+
subscriptions: new Map(),
|
|
3462
|
+
watchers: [],
|
|
3463
|
+
gitRefreshInterval: null,
|
|
3464
|
+
prRefreshInterval: null,
|
|
3465
|
+
debounceTimer: null,
|
|
3466
|
+
refreshPromise: null,
|
|
3467
|
+
refreshQueued: false,
|
|
3468
|
+
refreshIncludesPr: false,
|
|
3469
|
+
latestPayload: null,
|
|
3470
|
+
latestFingerprint: null,
|
|
3471
|
+
hasLoadedPullRequest: false,
|
|
3472
|
+
latestPayloadHasFullGitData: false,
|
|
3473
|
+
};
|
|
3474
|
+
const repoWatchPath = watchRoot ?? cwd;
|
|
3475
|
+
const watchPaths = new Set([repoWatchPath]);
|
|
3476
|
+
const gitDir = await this.resolveCheckoutGitDir(cwd);
|
|
3477
|
+
if (gitDir) {
|
|
3478
|
+
watchPaths.add(gitDir);
|
|
3479
|
+
}
|
|
3480
|
+
let hasRecursiveRepoCoverage = false;
|
|
3481
|
+
const allowRecursiveRepoWatch = process.platform !== 'linux';
|
|
3482
|
+
for (const watchPath of watchPaths) {
|
|
3483
|
+
const shouldTryRecursive = watchPath === repoWatchPath && allowRecursiveRepoWatch;
|
|
3484
|
+
const createWatcher = (recursive) => watch(watchPath, { recursive }, () => {
|
|
3485
|
+
this.scheduleWorkspaceStatusTargetRefresh(target);
|
|
3486
|
+
});
|
|
3487
|
+
let watcher = null;
|
|
3488
|
+
let watcherIsRecursive = false;
|
|
3489
|
+
try {
|
|
3490
|
+
if (shouldTryRecursive) {
|
|
3491
|
+
watcher = createWatcher(true);
|
|
3492
|
+
watcherIsRecursive = true;
|
|
3493
|
+
}
|
|
3494
|
+
else {
|
|
3495
|
+
watcher = createWatcher(false);
|
|
3496
|
+
}
|
|
3497
|
+
}
|
|
3498
|
+
catch (error) {
|
|
3499
|
+
if (shouldTryRecursive) {
|
|
3500
|
+
try {
|
|
3501
|
+
watcher = createWatcher(false);
|
|
3502
|
+
this.sessionLogger.warn({ err: error, watchPath, cwd, remoteName }, 'Workspace status recursive watch unavailable; using non-recursive fallback');
|
|
3503
|
+
}
|
|
3504
|
+
catch (fallbackError) {
|
|
3505
|
+
this.sessionLogger.warn({ err: fallbackError, watchPath, cwd, remoteName }, 'Failed to start workspace status watcher');
|
|
3506
|
+
}
|
|
3507
|
+
}
|
|
3508
|
+
else {
|
|
3509
|
+
this.sessionLogger.warn({ err: error, watchPath, cwd, remoteName }, 'Failed to start workspace status watcher');
|
|
3510
|
+
}
|
|
3511
|
+
}
|
|
3512
|
+
if (!watcher) {
|
|
3513
|
+
continue;
|
|
3514
|
+
}
|
|
3515
|
+
watcher.on('error', (error) => {
|
|
3516
|
+
this.sessionLogger.warn({ err: error, watchPath, cwd, remoteName }, 'Workspace status watcher error');
|
|
3517
|
+
});
|
|
3518
|
+
target.watchers.push(watcher);
|
|
3519
|
+
if (watchPath === repoWatchPath && watcherIsRecursive) {
|
|
3520
|
+
hasRecursiveRepoCoverage = true;
|
|
3521
|
+
}
|
|
3522
|
+
}
|
|
3523
|
+
if (target.watchers.length === 0 || !hasRecursiveRepoCoverage) {
|
|
3524
|
+
this.sessionLogger.warn({
|
|
3525
|
+
cwd,
|
|
3526
|
+
remoteName,
|
|
3527
|
+
reason: target.watchers.length === 0 ? 'no_watchers' : 'missing_recursive_repo_root_coverage',
|
|
3528
|
+
}, 'Workspace status watchers running with timed refresh support only');
|
|
3529
|
+
}
|
|
3530
|
+
this.workspaceStatusTargets.set(targetKey, target);
|
|
3531
|
+
return target;
|
|
3532
|
+
}
|
|
3533
|
+
async handleSubscribeWorkspaceStatusRequest(msg) {
|
|
3534
|
+
const cwd = expandTilde(msg.cwd);
|
|
3535
|
+
const remoteName = msg.remoteName?.trim() ? msg.remoteName.trim() : null;
|
|
3536
|
+
const mode = msg.mode ?? 'passive';
|
|
3537
|
+
if (remoteName) {
|
|
3538
|
+
this.assertSafeRemoteName(remoteName);
|
|
3539
|
+
}
|
|
3540
|
+
this.removeWorkspaceStatusSubscription(msg.subscriptionId);
|
|
3541
|
+
const target = await this.ensureWorkspaceStatusWatchTarget(cwd, remoteName);
|
|
3542
|
+
target.subscriptions.set(msg.subscriptionId, mode);
|
|
3543
|
+
this.workspaceStatusSubscriptions.set(msg.subscriptionId, {
|
|
3544
|
+
targetKey: target.key,
|
|
3545
|
+
});
|
|
3546
|
+
this.updateWorkspaceStatusGitPolling(target);
|
|
3547
|
+
this.updateWorkspaceStatusPrPolling(target);
|
|
3548
|
+
const fullGit = this.workspaceStatusHasActiveSubscribers(target);
|
|
3549
|
+
const includePr = fullGit;
|
|
3550
|
+
const previousFingerprint = target.latestFingerprint;
|
|
3551
|
+
const hadExistingSubscribers = target.subscriptions.size > 1;
|
|
3552
|
+
const snapshot = target.latestPayload
|
|
3553
|
+
&& (!includePr || target.hasLoadedPullRequest)
|
|
3554
|
+
&& (!fullGit || target.latestPayloadHasFullGitData)
|
|
3555
|
+
&& !(fullGit && target.latestPayload.gitError)
|
|
3556
|
+
? target.latestPayload
|
|
3557
|
+
: await this.computeWorkspaceStatusSnapshot(target, { includePr, fullGit });
|
|
3558
|
+
const hasLoadedPullRequest = target.hasLoadedPullRequest || includePr || !snapshot.git.isGit;
|
|
3559
|
+
target.latestPayload = snapshot;
|
|
3560
|
+
target.hasLoadedPullRequest = hasLoadedPullRequest;
|
|
3561
|
+
target.latestPayloadHasFullGitData = !snapshot.git.isGit || fullGit;
|
|
3562
|
+
const nextFingerprint = this.workspaceStatusSnapshotFingerprint(snapshot);
|
|
3563
|
+
target.latestFingerprint = nextFingerprint;
|
|
3564
|
+
this.emit({
|
|
3565
|
+
type: 'subscribe_workspace_status_response',
|
|
3566
|
+
payload: {
|
|
3567
|
+
subscriptionId: msg.subscriptionId,
|
|
3568
|
+
...snapshot,
|
|
3569
|
+
requestId: msg.requestId,
|
|
3570
|
+
},
|
|
3571
|
+
});
|
|
3572
|
+
if (hadExistingSubscribers && nextFingerprint !== previousFingerprint) {
|
|
3573
|
+
this.emitWorkspaceStatusChanged(target, snapshot);
|
|
3574
|
+
}
|
|
3575
|
+
if (!fullGit && snapshot.git.isGit && !hasLoadedPullRequest) {
|
|
3576
|
+
this.scheduleWorkspaceStatusTargetRefresh(target, {
|
|
3577
|
+
includePr: true,
|
|
3578
|
+
debounce: false,
|
|
3579
|
+
});
|
|
3580
|
+
}
|
|
3581
|
+
}
|
|
3582
|
+
handleUnsubscribeWorkspaceStatusRequest(msg) {
|
|
3583
|
+
this.removeWorkspaceStatusSubscription(msg.subscriptionId);
|
|
3584
|
+
}
|
|
3585
|
+
scheduleWorkspaceStatusRefreshForCwd(cwd, options) {
|
|
3586
|
+
const resolvedCwd = expandTilde(cwd);
|
|
3587
|
+
for (const target of this.workspaceStatusTargets.values()) {
|
|
3588
|
+
if (target.cwd !== resolvedCwd && target.diffCwd !== resolvedCwd) {
|
|
3589
|
+
continue;
|
|
3590
|
+
}
|
|
3591
|
+
this.scheduleWorkspaceStatusTargetRefresh(target, {
|
|
3592
|
+
includePr: options?.includePr,
|
|
3593
|
+
debounce: false,
|
|
3594
|
+
});
|
|
3595
|
+
}
|
|
3596
|
+
}
|
|
3117
3597
|
normalizeCheckoutDiffCompare(compare) {
|
|
3118
3598
|
if (compare.mode === 'uncommitted' || compare.mode === 'staged' || compare.mode === 'unstaged') {
|
|
3119
3599
|
return { mode: compare.mode };
|
|
@@ -3121,11 +3601,12 @@ export class Session {
|
|
|
3121
3601
|
const trimmedBaseRef = compare.baseRef?.trim();
|
|
3122
3602
|
return trimmedBaseRef ? { mode: 'base', baseRef: trimmedBaseRef } : { mode: 'base' };
|
|
3123
3603
|
}
|
|
3124
|
-
buildCheckoutDiffTargetKey(cwd, compare) {
|
|
3604
|
+
buildCheckoutDiffTargetKey(cwd, compare, detail) {
|
|
3125
3605
|
return JSON.stringify([
|
|
3126
3606
|
cwd,
|
|
3127
3607
|
compare.mode,
|
|
3128
3608
|
compare.mode === 'base' ? (compare.baseRef ?? '') : '',
|
|
3609
|
+
detail,
|
|
3129
3610
|
]);
|
|
3130
3611
|
}
|
|
3131
3612
|
closeCheckoutDiffWatchTarget(target) {
|
|
@@ -3212,13 +3693,19 @@ export class Session {
|
|
|
3212
3693
|
}
|
|
3213
3694
|
async computeCheckoutDiffSnapshot(cwd, compare, options) {
|
|
3214
3695
|
const diffCwd = options?.diffCwd ?? cwd;
|
|
3696
|
+
const detail = options?.detail ?? 'full';
|
|
3215
3697
|
try {
|
|
3216
3698
|
const diffResult = await getCheckoutDiff(diffCwd, {
|
|
3217
3699
|
mode: compare.mode,
|
|
3218
3700
|
baseRef: compare.baseRef,
|
|
3219
3701
|
includeStructured: true,
|
|
3220
3702
|
}, { junctionHome: this.junctionHome });
|
|
3221
|
-
const files = [...(diffResult.structured ?? [])]
|
|
3703
|
+
const files = [...(diffResult.structured ?? [])].map((file) => detail === 'summary'
|
|
3704
|
+
? {
|
|
3705
|
+
...file,
|
|
3706
|
+
hunks: [],
|
|
3707
|
+
}
|
|
3708
|
+
: file);
|
|
3222
3709
|
files.sort((a, b) => {
|
|
3223
3710
|
if (a.path === b.path)
|
|
3224
3711
|
return 0;
|
|
@@ -3248,6 +3735,7 @@ export class Session {
|
|
|
3248
3735
|
target.refreshQueued = false;
|
|
3249
3736
|
const snapshot = await this.computeCheckoutDiffSnapshot(target.cwd, target.compare, {
|
|
3250
3737
|
diffCwd: target.diffCwd,
|
|
3738
|
+
detail: target.detail,
|
|
3251
3739
|
});
|
|
3252
3740
|
target.latestPayload = snapshot;
|
|
3253
3741
|
const fingerprint = this.checkoutDiffSnapshotFingerprint(snapshot);
|
|
@@ -3264,8 +3752,8 @@ export class Session {
|
|
|
3264
3752
|
target.refreshPromise = null;
|
|
3265
3753
|
}
|
|
3266
3754
|
}
|
|
3267
|
-
async ensureCheckoutDiffWatchTarget(cwd, compare) {
|
|
3268
|
-
const targetKey = this.buildCheckoutDiffTargetKey(cwd, compare);
|
|
3755
|
+
async ensureCheckoutDiffWatchTarget(cwd, compare, detail) {
|
|
3756
|
+
const targetKey = this.buildCheckoutDiffTargetKey(cwd, compare, detail);
|
|
3269
3757
|
const existing = this.checkoutDiffTargets.get(targetKey);
|
|
3270
3758
|
if (existing) {
|
|
3271
3759
|
return existing;
|
|
@@ -3276,6 +3764,7 @@ export class Session {
|
|
|
3276
3764
|
cwd,
|
|
3277
3765
|
diffCwd: watchRoot ?? cwd,
|
|
3278
3766
|
compare,
|
|
3767
|
+
detail,
|
|
3279
3768
|
subscriptions: new Set(),
|
|
3280
3769
|
watchers: [],
|
|
3281
3770
|
fallbackRefreshInterval: null,
|
|
@@ -3352,8 +3841,9 @@ export class Session {
|
|
|
3352
3841
|
async handleSubscribeCheckoutDiffRequest(msg) {
|
|
3353
3842
|
const cwd = expandTilde(msg.cwd);
|
|
3354
3843
|
const compare = this.normalizeCheckoutDiffCompare(msg.compare);
|
|
3844
|
+
const detail = msg.detail ?? 'full';
|
|
3355
3845
|
this.removeCheckoutDiffSubscription(msg.subscriptionId);
|
|
3356
|
-
const target = await this.ensureCheckoutDiffWatchTarget(cwd, compare);
|
|
3846
|
+
const target = await this.ensureCheckoutDiffWatchTarget(cwd, compare, detail);
|
|
3357
3847
|
target.subscriptions.add(msg.subscriptionId);
|
|
3358
3848
|
this.checkoutDiffSubscriptions.set(msg.subscriptionId, {
|
|
3359
3849
|
targetKey: target.key,
|
|
@@ -3361,6 +3851,7 @@ export class Session {
|
|
|
3361
3851
|
const snapshot = target.latestPayload ??
|
|
3362
3852
|
(await this.computeCheckoutDiffSnapshot(cwd, compare, {
|
|
3363
3853
|
diffCwd: target.diffCwd,
|
|
3854
|
+
detail: target.detail,
|
|
3364
3855
|
}));
|
|
3365
3856
|
target.latestPayload = snapshot;
|
|
3366
3857
|
target.latestFingerprint = this.checkoutDiffSnapshotFingerprint(snapshot);
|
|
@@ -3400,6 +3891,7 @@ export class Session {
|
|
|
3400
3891
|
addAll: msg.addAll ?? true,
|
|
3401
3892
|
});
|
|
3402
3893
|
this.scheduleCheckoutDiffRefreshForCwd(cwd);
|
|
3894
|
+
this.scheduleWorkspaceStatusRefreshForCwd(cwd);
|
|
3403
3895
|
this.emit({
|
|
3404
3896
|
type: 'checkout_commit_response',
|
|
3405
3897
|
payload: {
|
|
@@ -3463,6 +3955,7 @@ export class Session {
|
|
|
3463
3955
|
mode: msg.strategy === 'squash' ? 'squash' : 'merge',
|
|
3464
3956
|
}, { junctionHome: this.junctionHome });
|
|
3465
3957
|
this.scheduleCheckoutDiffRefreshForCwd(cwd);
|
|
3958
|
+
this.scheduleWorkspaceStatusRefreshForCwd(cwd, { includePr: true });
|
|
3466
3959
|
this.emit({
|
|
3467
3960
|
type: 'checkout_merge_response',
|
|
3468
3961
|
payload: {
|
|
@@ -3503,6 +3996,7 @@ export class Session {
|
|
|
3503
3996
|
requireCleanTarget: msg.requireCleanTarget ?? true,
|
|
3504
3997
|
});
|
|
3505
3998
|
this.scheduleCheckoutDiffRefreshForCwd(cwd);
|
|
3999
|
+
this.scheduleWorkspaceStatusRefreshForCwd(cwd, { includePr: true });
|
|
3506
4000
|
this.emit({
|
|
3507
4001
|
type: 'checkout_merge_from_base_response',
|
|
3508
4002
|
payload: {
|
|
@@ -3529,6 +4023,7 @@ export class Session {
|
|
|
3529
4023
|
const { cwd, requestId } = msg;
|
|
3530
4024
|
try {
|
|
3531
4025
|
await pushCurrentBranch(cwd, { remoteName: msg.remoteName });
|
|
4026
|
+
this.scheduleWorkspaceStatusRefreshForCwd(cwd, { includePr: true });
|
|
3532
4027
|
this.emit({
|
|
3533
4028
|
type: 'checkout_push_response',
|
|
3534
4029
|
payload: {
|
|
@@ -3569,6 +4064,7 @@ export class Session {
|
|
|
3569
4064
|
base: msg.baseRef,
|
|
3570
4065
|
remoteName: msg.remoteName,
|
|
3571
4066
|
});
|
|
4067
|
+
this.scheduleWorkspaceStatusRefreshForCwd(cwd, { includePr: true });
|
|
3572
4068
|
this.emit({
|
|
3573
4069
|
type: 'checkout_pr_create_response',
|
|
3574
4070
|
payload: {
|
|
@@ -3689,6 +4185,7 @@ export class Session {
|
|
|
3689
4185
|
method: msg.method ?? 'squash',
|
|
3690
4186
|
remoteName: msg.remoteName,
|
|
3691
4187
|
});
|
|
4188
|
+
this.scheduleWorkspaceStatusRefreshForCwd(cwd, { includePr: true });
|
|
3692
4189
|
this.emit({
|
|
3693
4190
|
type: 'checkout_pr_merge_response',
|
|
3694
4191
|
payload: {
|
|
@@ -4049,6 +4546,7 @@ export class Session {
|
|
|
4049
4546
|
root,
|
|
4050
4547
|
relativePath: requestedPath,
|
|
4051
4548
|
ref,
|
|
4549
|
+
detail: request.detail ?? 'full',
|
|
4052
4550
|
});
|
|
4053
4551
|
this.emit({
|
|
4054
4552
|
type: 'workspace_file_explorer_response',
|
|
@@ -4978,6 +5476,11 @@ export class Session {
|
|
|
4978
5476
|
}
|
|
4979
5477
|
this.checkoutDiffTargets.clear();
|
|
4980
5478
|
this.checkoutDiffSubscriptions.clear();
|
|
5479
|
+
for (const target of this.workspaceStatusTargets.values()) {
|
|
5480
|
+
this.closeWorkspaceStatusWatchTarget(target);
|
|
5481
|
+
}
|
|
5482
|
+
this.workspaceStatusTargets.clear();
|
|
5483
|
+
this.workspaceStatusSubscriptions.clear();
|
|
4981
5484
|
}
|
|
4982
5485
|
// ============================================================================
|
|
4983
5486
|
// Terminal Handlers
|