| author | |
| committer | |
| log | c14bcca1035895edca5ebd8d65faea5fe788a825 |
| tree | 1c3bd5856859c8637cc7b25189c9c27b06c0ee08 |
| parent | 1fa315ea93f24e6f72455e234fa84a97de28492b |
| signature | Signed by PGP key B5690EEEBB952194 |
2 files changed, 39 insertions(+), 4 deletions(-)
apps/server/src/terminal/NodePtyAdapter.test.ts+30-2| ... | @@ -33,6 +33,7 @@ const testLayer = NodePtyAdapter.layer.pipe( | ... | @@ -33,6 +33,7 @@ const testLayer = NodePtyAdapter.layer.pipe( |
| 33 | 33 | ||
| 34 | it.effect("spawns through the public adapter with the provided host references", () => | 34 | it.effect("spawns through the public adapter with the provided host references", () => |
| 35 | Effect.gen(function* () { | 35 | Effect.gen(function* () { |
| 36 | spawn.mockClear(); | ||
| 36 | const adapter = yield* PtyAdapter.PtyAdapter; | 37 | const adapter = yield* PtyAdapter.PtyAdapter; |
| 37 | const process = yield* adapter.spawn({ | 38 | const process = yield* adapter.spawn({ |
| 38 | shell: "powershell.exe", | 39 | shell: "powershell.exe", |
| ... | @@ -52,8 +53,35 @@ it.effect("spawns through the public adapter with the provided host references", | ... | @@ -52,8 +53,35 @@ it.effect("spawns through the public adapter with the provided host references", |
| 52 | cwd: "C:\\workspace", | 53 | cwd: "C:\\workspace", |
| 53 | cols: 120, | 54 | cols: 120, |
| 54 | rows: 40, | 55 | rows: 40, |
| 55 | env: {}, | 56 | env: { TERM: "xterm-256color" }, |
| 56 | name: "xterm-color", | 57 | name: "xterm-256color", |
| 58 | }, | ||
| 59 | ]); | ||
| 60 | }).pipe(Effect.provide(testLayer)), | ||
| 61 | ); | ||
| 62 | |||
| 63 | it.effect("preserves a caller-provided TERM in the spawn env on win32", () => | ||
| 64 | Effect.gen(function* () { | ||
| 65 | spawn.mockClear(); | ||
| 66 | const adapter = yield* PtyAdapter.PtyAdapter; | ||
| 67 | yield* adapter.spawn({ | ||
| 68 | shell: "powershell.exe", | ||
| 69 | cwd: "C:\\workspace", | ||
| 70 | cols: 80, | ||
| 71 | rows: 24, | ||
| 72 | env: { TERM: "xterm-direct" }, | ||
| 73 | }); | ||
| 74 | |||
| 75 | assert.equal(spawn.mock.calls.length, 1); | ||
| 76 | assert.deepEqual(spawn.mock.calls[0], [ | ||
| 77 | "powershell.exe", | ||
| 78 | [], | ||
| 79 | { | ||
| 80 | cwd: "C:\\workspace", | ||
| 81 | cols: 80, | ||
| 82 | rows: 24, | ||
| 83 | env: { TERM: "xterm-direct" }, | ||
| 84 | name: "xterm-256color", | ||
| 57 | }, | 85 | }, |
| 58 | ]); | 86 | ]); |
| 59 | }).pipe(Effect.provide(testLayer)), | 87 | }).pipe(Effect.provide(testLayer)), |
apps/server/src/terminal/NodePtyAdapter.ts+9-2| ... | @@ -141,14 +141,21 @@ export const make = Effect.fn("NodePtyAdapter.make")(function* ( | ... | @@ -141,14 +141,21 @@ export const make = Effect.fn("NodePtyAdapter.make")(function* ( |
| 141 | return PtyAdapter.PtyAdapter.of({ | 141 | return PtyAdapter.PtyAdapter.of({ |
| 142 | spawn: Effect.fn("NodePtyAdapter.spawn")(function* (input) { | 142 | spawn: Effect.fn("NodePtyAdapter.spawn")(function* (input) { |
| 143 | yield* ensureNodePtySpawnHelperExecutableCached; | 143 | yield* ensureNodePtySpawnHelperExecutableCached; |
| 144 | // node-pty only writes `name` into the child's TERM on the Unix path; | ||
| 145 | // the ConPTY path leaves the environment untouched, so Windows children | ||
| 146 | // inherit a missing or 16-color TERM unless it is set here. | ||
| 147 | const env = | ||
| 148 | platform === "win32" && input.env["TERM"] === undefined | ||
| 149 | ? { ...input.env, TERM: "xterm-256color" } | ||
| 150 | : input.env; | ||
| 144 | const ptyProcess = yield* Effect.try({ | 151 | const ptyProcess = yield* Effect.try({ |
| 145 | try: () => | 152 | try: () => |
| 146 | nodePty.spawn(input.shell, input.args ?? [], { | 153 | nodePty.spawn(input.shell, input.args ?? [], { |
| 147 | cwd: input.cwd, | 154 | cwd: input.cwd, |
| 148 | cols: input.cols, | 155 | cols: input.cols, |
| 149 | rows: input.rows, | 156 | rows: input.rows, |
| 150 | env: input.env, | 157 | env, |
| 151 | name: platform === "win32" ? "xterm-color" : "xterm-256color", | 158 | name: "xterm-256color", |
| 152 | }), | 159 | }), |
| 153 | catch: (cause) => | 160 | catch: (cause) => |
| 154 | new PtyAdapter.PtySpawnError({ | 161 | new PtyAdapter.PtySpawnError({ |