DevelopmentNodeEnvironment_MicrosoftVSCodeDependency_22NodeVersion_Bundle_Clean_Debug_ElectronProfile_EsbuildCompiler_Mountain/IPC/WindServiceHandlers/Terminal/SerializeTerminalState.rs
1//! Serialise all active terminals to the `ISerializedTerminalState[]` shape
2//! that VS Code's `ILocalPtyService.serializeTerminalProcesses` contract
3//! requires.
4//!
5//! VS Code calls this immediately before a window reload to snapshot running
6//! PTY state. The result is written to storage and later passed back via
7//! `localPty:reviveTerminalProcesses` so the workbench can restore the panel
8//! without the user losing their shell sessions.
9//!
10//! ## Output shape per terminal
11//! ```json
12//! {
13//! "id": 1,
14//! "shellLaunchConfig": { "name": "zsh", "executable": "/bin/zsh", "args": [] },
15//! "processDetails": { "cwd": "/...", "pid": 1234, "title": "zsh" },
16//! "orphanQuestionReply": false,
17//! "replayEvent": { "events": [] },
18//! "timestamp": 1716134400000
19//! }
20//! ```
21//!
22//! Runtime handles (`PTYMaster`, `PTYInputTransmitter`, task `JoinHandle`s)
23//! are `#[serde(skip)]` in `TerminalStateDTO` and are intentionally absent
24//! from the wire payload - only the configuration fields needed to respawn
25//! the shell are serialised.
26
27use std::sync::Arc;
28
29use serde_json::{Value, json};
30
31use crate::RunTime::ApplicationRunTime::ApplicationRunTime;
32
33pub async fn Fn(RunTime:Arc<ApplicationRunTime>) -> Result<Value, String> {
34 let Terminals = RunTime
35 .Environment
36 .ApplicationState
37 .Feature
38 .Terminals
39 .ActiveTerminals
40 .lock()
41 .map_err(|Error| format!("SerializeTerminalState: lock poisoned: {}", Error))?;
42
43 let NowMs = std::time::SystemTime::now()
44 .duration_since(std::time::UNIX_EPOCH)
45 .map(|D| D.as_millis() as u64)
46 .unwrap_or(0);
47
48 let Serialized:Vec<Value> = Terminals
49 .iter()
50 .filter_map(|(TerminalId, ArcState)| {
51 let State = ArcState.lock().ok()?;
52
53 let Cwd = State.GetWorkingDirectory();
54
55 let Pid = State.OSProcessIdentifier.unwrap_or(0) as u64;
56
57 Some(json!({
58 "id": TerminalId,
59 "shellLaunchConfig": {
60 "name": State.Name,
61 "executable": State.ShellPath,
62 "args": State.ShellArguments,
63 "cwd": Cwd,
64 },
65 "processDetails": {
66 "cwd": Cwd,
67 "pid": Pid,
68 "title": State.Name,
69 },
70 // False means the orphan-question dialog was NOT shown;
71 // revived terminals start fresh without a stale prompt.
72 "orphanQuestionReply": false,
73 // Empty replay - the xterm buffer will be restored from the
74 // output replay buffer separately via `sky:replay-events`.
75 "replayEvent": { "events": [] },
76 "timestamp": NowMs,
77 }))
78 })
79 .collect();
80
81 Ok(Value::Array(Serialized))
82}