Repository navigation
Fix desktop/server PATH resolution and startup check for codex #248
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -235,12 +235,10 @@ export const recordStartupHeartbeat = Effect.gen(function* () { | |
| }); | ||
| }); | ||
|
|
||
| const makeServerProgram = (input: CliInput) => | ||
| const makeServerProgram = () => | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| Effect.gen(function* () { | ||
| const cliConfig = yield* CliConfig; | ||
| const { start, stopSignal } = yield* Server; | ||
| const openDeps = yield* Open; | ||
| yield* cliConfig.fixPath; | ||
|
|
||
| const config = yield* ServerConfig; | ||
|
|
||
|
|
@@ -280,7 +278,7 @@ const makeServerProgram = (input: CliInput) => | |
| } | ||
|
|
||
| return yield* stopSignal; | ||
| }).pipe(Effect.provide(LayerLive(input))); | ||
| }); | ||
|
|
||
| /** | ||
| * These flags mirrors the environment variables and the config shape. | ||
|
|
@@ -343,5 +341,12 @@ export const t3Cli = Command.make("t3", { | |
| logWebSocketEvents: logWebSocketEventsFlag, | ||
| }).pipe( | ||
| Command.withDescription("Run the T3 Code server."), | ||
| Command.withHandler((input) => Effect.scoped(makeServerProgram(input))), | ||
| Command.withHandler((input) => | ||
| Effect.scoped( | ||
| Effect.gen(function* () { | ||
| yield* Effect.sync(fixPath); | ||
| return yield* makeServerProgram().pipe(Effect.provide(LayerLive(input))); | ||
| }), | ||
| ), | ||
| ), | ||
| ); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| import assert from "node:assert/strict"; | ||
|
|
||
| import { it } from "@effect/vitest"; | ||
|
|
||
| import { normalizeShellPathOutput } from "./shellPath"; | ||
|
|
||
| it("normalizes colon-delimited shell PATH output", () => { | ||
| assert.strictEqual( | ||
| normalizeShellPathOutput("/usr/local/bin:/opt/homebrew/bin:/usr/bin"), | ||
| "/usr/local/bin:/opt/homebrew/bin:/usr/bin", | ||
| ); | ||
| }); | ||
|
|
||
| it("normalizes fish-style whitespace-delimited PATH output", () => { | ||
| assert.strictEqual( | ||
| normalizeShellPathOutput("/usr/local/bin /opt/homebrew/bin /usr/bin"), | ||
| "/usr/local/bin:/opt/homebrew/bin:/usr/bin", | ||
| ); | ||
| }); | ||
|
|
||
| it("strips ANSI control sequences from shell PATH output", () => { | ||
| assert.strictEqual( | ||
| normalizeShellPathOutput("\u001b[6 q/usr/local/bin:/opt/homebrew/bin\u001b[2 q"), | ||
| "/usr/local/bin:/opt/homebrew/bin", | ||
| ); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| import { delimiter, basename } from "node:path"; | ||
| import { execFileSync } from "node:child_process"; | ||
|
|
||
| const ESCAPE_CHARACTER = String.fromCharCode(27); | ||
| const ANSI_ESCAPE_SEQUENCE = new RegExp(`${ESCAPE_CHARACTER}\\[[0-?]*[ -/]*[@-~]`, "g"); | ||
|
|
||
| function getShellProbe(shellPath: string): ReadonlyArray<string> { | ||
| const shellName = basename(shellPath).toLowerCase(); | ||
| if (shellName === "fish") { | ||
| return ["-ilc", "string join : $PATH"]; | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| } | ||
| return ["-ilc", 'printf "%s" "$PATH"']; | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| } | ||
|
|
||
| export function normalizeShellPathOutput(raw: string): string | undefined { | ||
| const stripped = raw.replace(ANSI_ESCAPE_SEQUENCE, "").trim(); | ||
| if (stripped.length === 0) return undefined; | ||
|
|
||
| const separator = stripped.includes(":") ? ":" : stripped.includes(";") ? ";" : undefined; | ||
| if (!separator) return undefined; | ||
|
|
||
| const segments = stripped | ||
| .split(separator) | ||
| .map((segment) => segment.trim()) | ||
| .filter((segment) => segment.length > 0); | ||
|
|
||
| if (segments.length === 0) return undefined; | ||
| return segments.join(delimiter); | ||
| } | ||
|
baggiiiie marked this conversation as resolved.
|
||
|
|
||
| export function resolveLoginShellPath(shellPath: string, env: NodeJS.ProcessEnv = process.env) { | ||
| const result = execFileSync(shellPath, [...getShellProbe(shellPath)], { | ||
| encoding: "utf8", | ||
| timeout: 5000, | ||
| env: { | ||
| ...env, | ||
| TERM: "dumb", | ||
| }, | ||
| }); | ||
|
|
||
| return normalizeShellPathOutput(result); | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this was what broke in my local machine:
fish -ilc 'echo -n $PATH'gives space separated list of paths