4141# resource URI 中の ssh-remote authority ラベルを拾う ('+' は URL エンコードで %2B)。
4242_SSH_REMOTE_RE = re .compile (r"ssh-remote(?:\+|%2[Bb])([A-Za-z0-9._@-]+)" )
4343
44+ # ssh host 自動検出で探索する VS Code 系サーバーディレクトリ (DEVBASE_EDITOR で
45+ # code / code-insiders / cursor / vscodium 等を使い分けても拾えるよう横断する)。
46+ _SERVER_DIR_CANDIDATES = (
47+ "~/.vscode-server" ,
48+ "~/.vscode-server-insiders" ,
49+ "~/.cursor-server" ,
50+ "~/.vscodium-server" ,
51+ "~/.windsurf-server" ,
52+ )
53+
4454
4555@dataclass (frozen = True )
4656class EditorContext :
@@ -327,33 +337,36 @@ def resolve_workdir(environ=None, project_name: Optional[str] = None) -> str:
327337 return f"/work/{ repo } " if repo else "/work"
328338
329339
330- def _detect_ssh_host_from_vscode (vscode_server_dir : str ) -> Optional [str ]:
331- """``~/.vscode-server`` の File History から ssh-remote authority ラベルを推測する。
340+ def _detect_ssh_host_from_dirs (server_dirs ) -> Optional [str ]:
341+ """複数の VS Code 系サーバーディレクトリの File History を横断して ssh-remote
342+ authority ラベルを推測する。
332343
333344 Remote-SSH / attached-container 窓で開いたファイルの resource URI が
334- ``data/User/History/*/entries.json`` に ``ssh-remote%2B<host>`` (URL エンコード) /
335- ``ssh-remote+<host>`` 形で残るため、そこから ``<host>`` (= クライアントの接続ラベル。
336- 例 ``mac2``) を回収する。複数ホストが見つかった場合は **最後に使われた (entries.json
337- の mtime が最新の) ホスト**を返す。見つからなければ None。
345+ ``<server>/data/User/History/*/entries.json`` に ``ssh-remote%2B<host>`` (URL
346+ エンコード) / ``ssh-remote+<host>`` 形で残るため、そこから ``<host>`` (= クライアントの
347+ 接続ラベル。例 ``mac2``) を回収する。
348+
349+ 全ディレクトリの ``entries.json`` 候補を **mtime 降順**で集め、**新しい方から 1 ファイル
350+ ずつ読み、最初に ssh-remote ホストが見つかった時点で即 return** する (History が数千
351+ ファイルに膨れても全読み込みを避け、devbase up の遅延を防ぐ)。mtime 収集は stat のみで安価。
352+ 見つからなければ None。
338353
339354 .. note:: VS Code 内部データ依存のヒューリスティックで、バージョン差や multi-host 運用で
340355 外し得る。確実性が要る場合は ``DEVBASE_EDITOR_SSH_HOST`` を明示する (本関数より優先)。
341356 """
342- history = os .path .join (vscode_server_dir , "data" , "User" , "History" )
343- if not os .path .isdir (history ):
344- return None
345- # entries.json 候補を mtime 降順で集め、**新しい方から 1 ファイルずつ読み、最初に
346- # ssh-remote ホストが見つかった時点で即 return** する (History が数千ファイルに
347- # 膨れても全読み込みを避け、devbase up の遅延を防ぐ)。mtime 収集は stat のみで安価。
348- candidates = []
349- for root , _dirs , files in os .walk (history ):
350- if "entries.json" not in files : # resource authority は entries.json に載る
351- continue
352- path = os .path .join (root , "entries.json" )
353- try :
354- candidates .append ((os .path .getmtime (path ), path ))
355- except OSError :
357+ candidates = [] # (mtime, path)
358+ for base in server_dirs :
359+ history = os .path .join (base , "data" , "User" , "History" )
360+ if not os .path .isdir (history ):
356361 continue
362+ for root , _dirs , files in os .walk (history ):
363+ if "entries.json" not in files : # resource authority は entries.json に載る
364+ continue
365+ path = os .path .join (root , "entries.json" )
366+ try :
367+ candidates .append ((os .path .getmtime (path ), path ))
368+ except OSError :
369+ continue
357370 for _mtime , path in sorted (candidates , key = lambda t : t [0 ], reverse = True ):
358371 try :
359372 with open (path , encoding = "utf-8" , errors = "ignore" ) as f :
@@ -366,29 +379,40 @@ def _detect_ssh_host_from_vscode(vscode_server_dir: str) -> Optional[str]:
366379 return None
367380
368381
382+ def _detect_ssh_host_from_vscode (vscode_server_dir : str ) -> Optional [str ]:
383+ """単一サーバーディレクトリ版 (:func:`_detect_ssh_host_from_dirs` の薄ラッパ)。"""
384+ return _detect_ssh_host_from_dirs ([vscode_server_dir ])
385+
386+
369387def resolve_editor_ssh_host (environ = None ,
370388 vscode_server_dir : Optional [str ] = None ) -> Optional [str ]:
371389 """Remote-SSH ネスト URI 用の ssh ホスト名 (authority ラベル) を解決する。
372390
373391 優先順位:
374392
375393 1. ``DEVBASE_EDITOR_SSH_HOST`` 明示 (最優先・確実)
376- 2. ``~/.vscode-server`` の File History からの自動推測
377- (:func:`_detect_ssh_host_from_vscode`)
394+ 2. VS Code 系サーバーディレクトリ (``~/.vscode-server`` / ``~/.cursor-server`` /
395+ ``~/.vscode-server-insiders`` 等) の File History からの自動推測
396+ (:func:`_detect_ssh_host_from_dirs`)
378397
379398 ネスト attach は新規 ssh 接続を張らず **既存 Remote-SSH 接続 (ExecServer) の authority
380399 ラベルと完全一致**する必要がある (実機確認: IP / user@IP は "Parent authority found
381400 without ExecServer" で不可)。そのラベル (例 ``mac2``) はクライアント側の名前で SSH_CONNECTION
382401 等の env には現れない (IP のみ) ため、自動取得は VS Code が残す痕跡からの回収に頼る。
383402 どちらでも得られなければ None で :func:`build_attach_uri` はフラット URI に degrade する。
403+
404+ ``vscode_server_dir`` はテスト用の単一ディレクトリ差し替え口 (指定時はそれだけを探索)。
384405 """
385406 env = os .environ if environ is None else environ
386407 explicit = env .get ("DEVBASE_EDITOR_SSH_HOST" )
387408 if explicit and explicit .strip ():
388409 return explicit .strip ()
389- base = vscode_server_dir or os .path .expanduser ("~/.vscode-server" )
410+ if vscode_server_dir is not None :
411+ server_dirs = [vscode_server_dir ]
412+ else :
413+ server_dirs = [os .path .expanduser (d ) for d in _SERVER_DIR_CANDIDATES ]
390414 try :
391- return _detect_ssh_host_from_vscode ( base )
415+ return _detect_ssh_host_from_dirs ( server_dirs )
392416 except Exception : # noqa: BLE001 - 自動推測失敗で up を倒さない
393417 return None
394418
0 commit comments