| author | |
| committer | |
| log | 2fa37ec183e0b99ca2ea77efbcb615f11019da75 |
| tree | 5f9b229ed26c6b6fffb244af091a272d71bd6534 |
| parent | db27502aff1add34eb2af4ff12c606e99bdc3610 |
| signature | Signed by PGP key B5690EEEBB952194 |
Co-authored-by: codex <codex@users.noreply.github.com>71 files changed, 1205 insertions(+), 952 deletions(-)
.macroscope/check-run-agents/effect-service-conventions.md+1-1| ... | @@ -27,7 +27,7 @@ Review changed TypeScript and directly affected call sites for the conventions b | ... | @@ -27,7 +27,7 @@ Review changed TypeScript and directly affected call sites for the conventions b |
| 27 | 27 | ||
| 28 | - Import Effect library modules from their subpaths as namespaces, for example `import * as Effect from "effect/Effect"` and `import * as Layer from "effect/Layer"`. Flag consolidated named imports from `"effect"` in touched Effect service code. | 28 | - Import Effect library modules from their subpaths as namespaces, for example `import * as Effect from "effect/Effect"` and `import * as Layer from "effect/Layer"`. Flag consolidated named imports from `"effect"` in touched Effect service code. |
| 29 | - At a service boundary, import the local service module as a namespace and use its public module shape: `WorkspacePaths.WorkspacePaths`, `WorkspacePaths.make`, and `WorkspacePaths.layer`. Flag aliases such as `import { layer as workspacePathsLayer }` that erase the module namespace. | 29 | - At a service boundary, import the local service module as a namespace and use its public module shape: `WorkspacePaths.WorkspacePaths`, `WorkspacePaths.make`, and `WorkspacePaths.layer`. Flag aliases such as `import { layer as workspacePathsLayer }` that erase the module namespace. |
| 30 | - Namespace imports are not a blanket rule. Keep named imports for whole packages such as `@t3tools/contracts` and `electron`, and for modules used only for a pure helper, error, schema, config value, or standalone type. Do not request `import type * as Contracts`. | 30 | - Namespace imports are not a blanket rule. Keep named imports for whole packages such as `@t3tools/contracts`, and for modules used only for a pure helper, error, schema, config value, or standalone type. Do not request `import type * as Contracts`. |
| 31 | - A package subpath that is itself a service module may use a namespace import when callers access its service/tag, `make`, or `layer` members. | 31 | - A package subpath that is itself a service module may use a namespace import when callers access its service/tag, `make`, or `layer` members. |
| 32 | - When a barrel exposes an entire service module, prefer `export * as TokenStore from "./tokenStore.ts"` so consumers can use `TokenStore.TokenStore` and `TokenStore.layer`. Do not individually rename `make` and `layer` exports to simulate a namespace. | 32 | - When a barrel exposes an entire service module, prefer `export * as TokenStore from "./tokenStore.ts"` so consumers can use `TokenStore.TokenStore` and `TokenStore.layer`. Do not individually rename `make` and `layer` exports to simulate a namespace. |
| 33 | 33 |
apps/desktop/scripts/build-preview-annotation-css.mjs+16-16| ... | @@ -1,23 +1,23 @@ | ... | @@ -1,23 +1,23 @@ |
| 1 | import { readFile, writeFile } from "node:fs/promises"; | 1 | import * as NodeFSP from "node:fs/promises"; |
| 2 | import { createRequire } from "node:module"; | 2 | import * as NodeModule from "node:module"; |
| 3 | import { dirname, join } from "node:path"; | 3 | import * as NodePath from "node:path"; |
| 4 | import { fileURLToPath } from "node:url"; | 4 | import * as NodeURL from "node:url"; |
| 5 | 5 | ||
| 6 | import { compile } from "tailwindcss"; | 6 | import { compile } from "tailwindcss"; |
| 7 | 7 | ||
| 8 | const directory = dirname(fileURLToPath(import.meta.url)); | 8 | const directory = NodePath.dirname(NodeURL.fileURLToPath(import.meta.url)); |
| 9 | const appRoot = join(directory, ".."); | 9 | const appRoot = NodePath.join(directory, ".."); |
| 10 | const sourcePath = join(appRoot, "src", "preview", "Annotation.css"); | 10 | const sourcePath = NodePath.join(appRoot, "src", "preview", "Annotation.css"); |
| 11 | const preloadPath = join(appRoot, "src", "preview", "PickPreload.ts"); | 11 | const preloadPath = NodePath.join(appRoot, "src", "preview", "PickPreload.ts"); |
| 12 | const outputPath = join(appRoot, "src", "preview", "AnnotationStyles.generated.ts"); | 12 | const outputPath = NodePath.join(appRoot, "src", "preview", "AnnotationStyles.generated.ts"); |
| 13 | const require = createRequire(import.meta.url); | 13 | const require = NodeModule.createRequire(import.meta.url); |
| 14 | const tailwindRoot = dirname(require.resolve("tailwindcss/package.json")); | 14 | const tailwindRoot = NodePath.dirname(require.resolve("tailwindcss/package.json")); |
| 15 | 15 | ||
| 16 | const [annotationSource, preloadSource, themeSource, preflightSource] = await Promise.all([ | 16 | const [annotationSource, preloadSource, themeSource, preflightSource] = await Promise.all([ |
| 17 | readFile(sourcePath, "utf8"), | 17 | NodeFSP.readFile(sourcePath, "utf8"), |
| 18 | readFile(preloadPath, "utf8"), | 18 | NodeFSP.readFile(preloadPath, "utf8"), |
| 19 | readFile(join(tailwindRoot, "theme.css"), "utf8"), | 19 | NodeFSP.readFile(NodePath.join(tailwindRoot, "theme.css"), "utf8"), |
| 20 | readFile(join(tailwindRoot, "preflight.css"), "utf8"), | 20 | NodeFSP.readFile(NodePath.join(tailwindRoot, "preflight.css"), "utf8"), |
| 21 | ]); | 21 | ]); |
| 22 | 22 | ||
| 23 | const candidates = new Set( | 23 | const candidates = new Set( |
| ... | @@ -37,4 +37,4 @@ const encodedCss = `'${css | ... | @@ -37,4 +37,4 @@ const encodedCss = `'${css |
| 37 | .replaceAll("\n", "\\n")}'`; | 37 | .replaceAll("\n", "\\n")}'`; |
| 38 | const moduleSource = `// Generated by scripts/build-preview-annotation-css.mjs. Do not edit.\nexport const previewAnnotationStyles =\n ${encodedCss};\n`; | 38 | const moduleSource = `// Generated by scripts/build-preview-annotation-css.mjs. Do not edit.\nexport const previewAnnotationStyles =\n ${encodedCss};\n`; |
| 39 | 39 | ||
| 40 | await writeFile(outputPath, moduleSource); | 40 | await NodeFSP.writeFile(outputPath, moduleSource); |
apps/desktop/scripts/dev-electron.mjs+13-9| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | import { spawn, spawnSync } from "node:child_process"; | 1 | import * as NodeChildProcess from "node:child_process"; |
| 2 | import { watch } from "node:fs"; | 2 | import * as NodeFS from "node:fs"; |
| 3 | import * as NodeOS from "node:os"; | 3 | import * as NodeOS from "node:os"; |
| 4 | import { join } from "node:path"; | 4 | import * as NodePath from "node:path"; |
| 5 | 5 | ||
| 6 | import { | 6 | import { |
| 7 | desktopDir, | 7 | desktopDir, |
| ... | @@ -64,7 +64,7 @@ function killChildTreeByPid(pid, signal) { | ... | @@ -64,7 +64,7 @@ function killChildTreeByPid(pid, signal) { |
| 64 | return; | 64 | return; |
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | spawnSync("pkill", [`-${signal}`, "-P", String(pid)], { stdio: "ignore" }); | 67 | NodeChildProcess.spawnSync("pkill", [`-${signal}`, "-P", String(pid)], { stdio: "ignore" }); |
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | function cleanupStaleDevApps() { | 70 | function cleanupStaleDevApps() { |
| ... | @@ -72,7 +72,9 @@ function cleanupStaleDevApps() { | ... | @@ -72,7 +72,9 @@ function cleanupStaleDevApps() { |
| 72 | return; | 72 | return; |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | spawnSync("pkill", ["-f", "--", `--t3code-dev-root=${desktopDir}`], { stdio: "ignore" }); | 75 | NodeChildProcess.spawnSync("pkill", ["-f", "--", `--t3code-dev-root=${desktopDir}`], { |
| 76 | stdio: "ignore", | ||
| 77 | }); | ||
| 76 | } | 78 | } |
| 77 | 79 | ||
| 78 | function startApp() { | 80 | function startApp() { |
| ... | @@ -87,7 +89,7 @@ function startApp() { | ... | @@ -87,7 +89,7 @@ function startApp() { |
| 87 | ? electronArgs | 89 | ? electronArgs |
| 88 | : [...electronArgs, `--t3code-dev-root=${desktopDir}`, "dist-electron/main.cjs"]; | 90 | : [...electronArgs, `--t3code-dev-root=${desktopDir}`, "dist-electron/main.cjs"]; |
| 89 | const electronCommand = resolveElectronLaunchCommand(launchArgs); | 91 | const electronCommand = resolveElectronLaunchCommand(launchArgs); |
| 90 | const app = spawn(electronCommand.electronPath, electronCommand.args, { | 92 | const app = NodeChildProcess.spawn(electronCommand.electronPath, electronCommand.args, { |
| 91 | cwd: desktopDir, | 93 | cwd: desktopDir, |
| 92 | env: childEnv, | 94 | env: childEnv, |
| 93 | stdio: "inherit", | 95 | stdio: "inherit", |
| ... | @@ -180,8 +182,8 @@ function scheduleRestart() { | ... | @@ -180,8 +182,8 @@ function scheduleRestart() { |
| 180 | 182 | ||
| 181 | function startWatchers() { | 183 | function startWatchers() { |
| 182 | for (const { directory, files } of watchedDirectories) { | 184 | for (const { directory, files } of watchedDirectories) { |
| 183 | const watcher = watch( | 185 | const watcher = NodeFS.watch( |
| 184 | join(desktopDir, directory), | 186 | NodePath.join(desktopDir, directory), |
| 185 | { persistent: true }, | 187 | { persistent: true }, |
| 186 | (_eventType, filename) => { | 188 | (_eventType, filename) => { |
| 187 | if (typeof filename !== "string" || !files.has(filename)) { | 189 | if (typeof filename !== "string" || !files.has(filename)) { |
| ... | @@ -202,7 +204,9 @@ function killChildTree(signal) { | ... | @@ -202,7 +204,9 @@ function killChildTree(signal) { |
| 202 | } | 204 | } |
| 203 | 205 | ||
| 204 | // Kill direct children as a final fallback in case normal shutdown leaves stragglers. | 206 | // Kill direct children as a final fallback in case normal shutdown leaves stragglers. |
| 205 | spawnSync("pkill", [`-${signal}`, "-P", String(process.pid)], { stdio: "ignore" }); | 207 | NodeChildProcess.spawnSync("pkill", [`-${signal}`, "-P", String(process.pid)], { |
| 208 | stdio: "ignore", | ||
| 209 | }); | ||
| 206 | } | 210 | } |
| 207 | 211 | ||
| 208 | async function shutdown(exitCode) { | 212 | async function shutdown(exitCode) { |
apps/desktop/scripts/electron-launcher.mjs+89-73| ... | @@ -1,29 +1,18 @@ | ... | @@ -1,29 +1,18 @@ |
| 1 | // This file mostly exists because we want dev mode to say "T3 Code (Dev)" instead of "electron" | 1 | // This file mostly exists because we want dev mode to say "T3 Code (Dev)" instead of "electron" |
| 2 | 2 | ||
| 3 | import { spawnSync } from "node:child_process"; | 3 | import * as NodeChildProcess from "node:child_process"; |
| 4 | import { | 4 | import * as NodeFS from "node:fs"; |
| 5 | copyFileSync, | 5 | import * as NodeModule from "node:module"; |
| 6 | chmodSync, | ||
| 7 | cpSync, | ||
| 8 | existsSync, | ||
| 9 | mkdirSync, | ||
| 10 | mkdtempSync, | ||
| 11 | readFileSync, | ||
| 12 | rmSync, | ||
| 13 | statSync, | ||
| 14 | writeFileSync, | ||
| 15 | } from "node:fs"; | ||
| 16 | import { createRequire } from "node:module"; | ||
| 17 | import * as NodeOS from "node:os"; | 6 | import * as NodeOS from "node:os"; |
| 18 | import { basename, dirname, join, resolve } from "node:path"; | 7 | import * as NodePath from "node:path"; |
| 19 | import { fileURLToPath } from "node:url"; | 8 | import * as NodeURL from "node:url"; |
| 20 | import { ensureElectronRuntime } from "./ensure-electron-runtime.mjs"; | 9 | import { ensureElectronRuntime } from "./ensure-electron-runtime.mjs"; |
| 21 | 10 | ||
| 22 | const isDevelopment = Boolean(process.env.VITE_DEV_SERVER_URL); | 11 | const isDevelopment = Boolean(process.env.VITE_DEV_SERVER_URL); |
| 23 | const __dirname = dirname(fileURLToPath(import.meta.url)); | 12 | const __dirname = NodePath.dirname(NodeURL.fileURLToPath(import.meta.url)); |
| 24 | export const desktopDir = resolve(__dirname, ".."); | 13 | export const desktopDir = NodePath.resolve(__dirname, ".."); |
| 25 | const repoRoot = resolve(desktopDir, "..", ".."); | 14 | const repoRoot = NodePath.resolve(desktopDir, "..", ".."); |
| 26 | const devBundleIdSuffix = basename(repoRoot) | 15 | const devBundleIdSuffix = NodePath.basename(repoRoot) |
| 27 | .toLowerCase() | 16 | .toLowerCase() |
| 28 | .replaceAll(/[^a-z0-9]+/g, ""); | 17 | .replaceAll(/[^a-z0-9]+/g, ""); |
| 29 | export const APP_DISPLAY_NAME = isDevelopment ? "T3 Code (Dev)" : "T3 Code (Alpha)"; | 18 | export const APP_DISPLAY_NAME = isDevelopment ? "T3 Code (Dev)" : "T3 Code (Alpha)"; |
| ... | @@ -32,22 +21,35 @@ export const APP_BUNDLE_ID = isDevelopment | ... | @@ -32,22 +21,35 @@ export const APP_BUNDLE_ID = isDevelopment |
| 32 | : "com.t3tools.t3code"; | 21 | : "com.t3tools.t3code"; |
| 33 | const APP_PROTOCOL_SCHEMES = isDevelopment ? ["t3code-dev"] : ["t3code"]; | 22 | const APP_PROTOCOL_SCHEMES = isDevelopment ? ["t3code-dev"] : ["t3code"]; |
| 34 | const LAUNCHER_VERSION = 12; | 23 | const LAUNCHER_VERSION = 12; |
| 35 | const defaultIconPath = join(desktopDir, "resources", "icon.icns"); | 24 | const defaultIconPath = NodePath.join(desktopDir, "resources", "icon.icns"); |
| 36 | const developmentMacIconPngPath = join(repoRoot, "assets", "dev", "blueprint-macos-1024.png"); | 25 | const developmentMacIconPngPath = NodePath.join( |
| 26 | repoRoot, | ||
| 27 | "assets", | ||
| 28 | "dev", | ||
| 29 | "blueprint-macos-1024.png", | ||
| 30 | ); | ||
| 37 | // oxlint-disable-next-line t3code/no-global-process-runtime -- Standalone launcher script has no Effect runtime. | 31 | // oxlint-disable-next-line t3code/no-global-process-runtime -- Standalone launcher script has no Effect runtime. |
| 38 | const hostPlatform = NodeOS.platform(); | 32 | const hostPlatform = NodeOS.platform(); |
| 39 | 33 | ||
| 40 | function setPlistString(plistPath, key, value) { | 34 | function setPlistString(plistPath, key, value) { |
| 41 | const replaceResult = spawnSync("plutil", ["-replace", key, "-string", value, plistPath], { | 35 | const replaceResult = NodeChildProcess.spawnSync( |
| 42 | encoding: "utf8", | 36 | "plutil", |
| 43 | }); | 37 | ["-replace", key, "-string", value, plistPath], |
| 38 | { | ||
| 39 | encoding: "utf8", | ||
| 40 | }, | ||
| 41 | ); | ||
| 44 | if (replaceResult.status === 0) { | 42 | if (replaceResult.status === 0) { |
| 45 | return; | 43 | return; |
| 46 | } | 44 | } |
| 47 | 45 | ||
| 48 | const insertResult = spawnSync("plutil", ["-insert", key, "-string", value, plistPath], { | 46 | const insertResult = NodeChildProcess.spawnSync( |
| 49 | encoding: "utf8", | 47 | "plutil", |
| 50 | }); | 48 | ["-insert", key, "-string", value, plistPath], |
| 49 | { | ||
| 50 | encoding: "utf8", | ||
| 51 | }, | ||
| 52 | ); | ||
| 51 | if (insertResult.status === 0) { | 53 | if (insertResult.status === 0) { |
| 52 | return; | 54 | return; |
| 53 | } | 55 | } |
| ... | @@ -58,16 +60,24 @@ function setPlistString(plistPath, key, value) { | ... | @@ -58,16 +60,24 @@ function setPlistString(plistPath, key, value) { |
| 58 | 60 | ||
| 59 | function setPlistJson(plistPath, key, value) { | 61 | function setPlistJson(plistPath, key, value) { |
| 60 | const serialized = JSON.stringify(value); | 62 | const serialized = JSON.stringify(value); |
| 61 | const replaceResult = spawnSync("plutil", ["-replace", key, "-json", serialized, plistPath], { | 63 | const replaceResult = NodeChildProcess.spawnSync( |
| 62 | encoding: "utf8", | 64 | "plutil", |
| 63 | }); | 65 | ["-replace", key, "-json", serialized, plistPath], |
| 66 | { | ||
| 67 | encoding: "utf8", | ||
| 68 | }, | ||
| 69 | ); | ||
| 64 | if (replaceResult.status === 0) { | 70 | if (replaceResult.status === 0) { |
| 65 | return; | 71 | return; |
| 66 | } | 72 | } |
| 67 | 73 | ||
| 68 | const insertResult = spawnSync("plutil", ["-insert", key, "-json", serialized, plistPath], { | 74 | const insertResult = NodeChildProcess.spawnSync( |
| 69 | encoding: "utf8", | 75 | "plutil", |
| 70 | }); | 76 | ["-insert", key, "-json", serialized, plistPath], |
| 77 | { | ||
| 78 | encoding: "utf8", | ||
| 79 | }, | ||
| 80 | ); | ||
| 71 | if (insertResult.status === 0) { | 81 | if (insertResult.status === 0) { |
| 72 | return; | 82 | return; |
| 73 | } | 83 | } |
| ... | @@ -77,7 +87,7 @@ function setPlistJson(plistPath, key, value) { | ... | @@ -77,7 +87,7 @@ function setPlistJson(plistPath, key, value) { |
| 77 | } | 87 | } |
| 78 | 88 | ||
| 79 | function runChecked(command, args) { | 89 | function runChecked(command, args) { |
| 80 | const result = spawnSync(command, args, { encoding: "utf8" }); | 90 | const result = NodeChildProcess.spawnSync(command, args, { encoding: "utf8" }); |
| 81 | if (result.status === 0) { | 91 | if (result.status === 0) { |
| 82 | return; | 92 | return; |
| 83 | } | 93 | } |
| ... | @@ -91,7 +101,7 @@ function shellSingleQuote(value) { | ... | @@ -91,7 +101,7 @@ function shellSingleQuote(value) { |
| 91 | } | 101 | } |
| 92 | 102 | ||
| 93 | function writeDevelopmentLauncherScript(targetBinaryPath, electronBinaryPath) { | 103 | function writeDevelopmentLauncherScript(targetBinaryPath, electronBinaryPath) { |
| 94 | const mainEntryPath = join(desktopDir, "dist-electron", "main.cjs"); | 104 | const mainEntryPath = NodePath.join(desktopDir, "dist-electron", "main.cjs"); |
| 95 | const envEntries = [ | 105 | const envEntries = [ |
| 96 | ["VITE_DEV_SERVER_URL", process.env.VITE_DEV_SERVER_URL], | 106 | ["VITE_DEV_SERVER_URL", process.env.VITE_DEV_SERVER_URL], |
| 97 | ["T3CODE_PORT", process.env.T3CODE_PORT], | 107 | ["T3CODE_PORT", process.env.T3CODE_PORT], |
| ... | @@ -101,7 +111,7 @@ function writeDevelopmentLauncherScript(targetBinaryPath, electronBinaryPath) { | ... | @@ -101,7 +111,7 @@ function writeDevelopmentLauncherScript(targetBinaryPath, electronBinaryPath) { |
| 101 | ["T3CODE_OTLP_EXPORT_INTERVAL_MS", process.env.T3CODE_OTLP_EXPORT_INTERVAL_MS], | 111 | ["T3CODE_OTLP_EXPORT_INTERVAL_MS", process.env.T3CODE_OTLP_EXPORT_INTERVAL_MS], |
| 102 | ["T3CODE_DESKTOP_APP_USER_MODEL_ID", APP_BUNDLE_ID], | 112 | ["T3CODE_DESKTOP_APP_USER_MODEL_ID", APP_BUNDLE_ID], |
| 103 | ].filter((entry) => typeof entry[1] === "string" && entry[1].trim().length > 0); | 113 | ].filter((entry) => typeof entry[1] === "string" && entry[1].trim().length > 0); |
| 104 | writeFileSync( | 114 | NodeFS.writeFileSync( |
| 105 | targetBinaryPath, | 115 | targetBinaryPath, |
| 106 | [ | 116 | [ |
| 107 | "#!/bin/sh", | 117 | "#!/bin/sh", |
| ... | @@ -110,7 +120,7 @@ function writeDevelopmentLauncherScript(targetBinaryPath, electronBinaryPath) { | ... | @@ -110,7 +120,7 @@ function writeDevelopmentLauncherScript(targetBinaryPath, electronBinaryPath) { |
| 110 | "", | 120 | "", |
| 111 | ].join("\n"), | 121 | ].join("\n"), |
| 112 | ); | 122 | ); |
| 113 | chmodSync(targetBinaryPath, 0o755); | 123 | NodeFS.chmodSync(targetBinaryPath, 0o755); |
| 114 | } | 124 | } |
| 115 | 125 | ||
| 116 | function registerMacLauncherBundle(appBundlePath) { | 126 | function registerMacLauncherBundle(appBundlePath) { |
| ... | @@ -140,21 +150,24 @@ function registerMacLauncherBundle(appBundlePath) { | ... | @@ -140,21 +150,24 @@ function registerMacLauncherBundle(appBundlePath) { |
| 140 | } | 150 | } |
| 141 | 151 | ||
| 142 | function ensureDevelopmentIconIcns(runtimeDir) { | 152 | function ensureDevelopmentIconIcns(runtimeDir) { |
| 143 | const generatedIconPath = join(runtimeDir, "icon-dev.icns"); | 153 | const generatedIconPath = NodePath.join(runtimeDir, "icon-dev.icns"); |
| 144 | mkdirSync(runtimeDir, { recursive: true }); | 154 | NodeFS.mkdirSync(runtimeDir, { recursive: true }); |
| 145 | 155 | ||
| 146 | if (!existsSync(developmentMacIconPngPath)) { | 156 | if (!NodeFS.existsSync(developmentMacIconPngPath)) { |
| 147 | return defaultIconPath; | 157 | return defaultIconPath; |
| 148 | } | 158 | } |
| 149 | 159 | ||
| 150 | const sourceMtimeMs = statSync(developmentMacIconPngPath).mtimeMs; | 160 | const sourceMtimeMs = NodeFS.statSync(developmentMacIconPngPath).mtimeMs; |
| 151 | if (existsSync(generatedIconPath) && statSync(generatedIconPath).mtimeMs >= sourceMtimeMs) { | 161 | if ( |
| 162 | NodeFS.existsSync(generatedIconPath) && | ||
| 163 | NodeFS.statSync(generatedIconPath).mtimeMs >= sourceMtimeMs | ||
| 164 | ) { | ||
| 152 | return generatedIconPath; | 165 | return generatedIconPath; |
| 153 | } | 166 | } |
| 154 | 167 | ||
| 155 | const iconsetRoot = mkdtempSync(join(runtimeDir, "dev-iconset-")); | 168 | const iconsetRoot = NodeFS.mkdtempSync(NodePath.join(runtimeDir, "dev-iconset-")); |
| 156 | const iconsetDir = join(iconsetRoot, "icon.iconset"); | 169 | const iconsetDir = NodePath.join(iconsetRoot, "icon.iconset"); |
| 157 | mkdirSync(iconsetDir, { recursive: true }); | 170 | NodeFS.mkdirSync(iconsetDir, { recursive: true }); |
| 158 | 171 | ||
| 159 | try { | 172 | try { |
| 160 | for (const size of [16, 32, 128, 256, 512]) { | 173 | for (const size of [16, 32, 128, 256, 512]) { |
| ... | @@ -164,7 +177,7 @@ function ensureDevelopmentIconIcns(runtimeDir) { | ... | @@ -164,7 +177,7 @@ function ensureDevelopmentIconIcns(runtimeDir) { |
| 164 | String(size), | 177 | String(size), |
| 165 | developmentMacIconPngPath, | 178 | developmentMacIconPngPath, |
| 166 | "--out", | 179 | "--out", |
| 167 | join(iconsetDir, `icon_${size}x${size}.png`), | 180 | NodePath.join(iconsetDir, `icon_${size}x${size}.png`), |
| 168 | ]); | 181 | ]); |
| 169 | 182 | ||
| 170 | const retinaSize = size * 2; | 183 | const retinaSize = size * 2; |
| ... | @@ -174,7 +187,7 @@ function ensureDevelopmentIconIcns(runtimeDir) { | ... | @@ -174,7 +187,7 @@ function ensureDevelopmentIconIcns(runtimeDir) { |
| 174 | String(retinaSize), | 187 | String(retinaSize), |
| 175 | developmentMacIconPngPath, | 188 | developmentMacIconPngPath, |
| 176 | "--out", | 189 | "--out", |
| 177 | join(iconsetDir, `icon_${size}x${size}@2x.png`), | 190 | NodePath.join(iconsetDir, `icon_${size}x${size}@2x.png`), |
| 178 | ]); | 191 | ]); |
| 179 | } | 192 | } |
| 180 | 193 | ||
| ... | @@ -187,12 +200,12 @@ function ensureDevelopmentIconIcns(runtimeDir) { | ... | @@ -187,12 +200,12 @@ function ensureDevelopmentIconIcns(runtimeDir) { |
| 187 | ); | 200 | ); |
| 188 | return defaultIconPath; | 201 | return defaultIconPath; |
| 189 | } finally { | 202 | } finally { |
| 190 | rmSync(iconsetRoot, { recursive: true, force: true }); | 203 | NodeFS.rmSync(iconsetRoot, { recursive: true, force: true }); |
| 191 | } | 204 | } |
| 192 | } | 205 | } |
| 193 | 206 | ||
| 194 | function patchMainBundleInfoPlist(appBundlePath, iconPath) { | 207 | function patchMainBundleInfoPlist(appBundlePath, iconPath) { |
| 195 | const infoPlistPath = join(appBundlePath, "Contents", "Info.plist"); | 208 | const infoPlistPath = NodePath.join(appBundlePath, "Contents", "Info.plist"); |
| 196 | setPlistString(infoPlistPath, "CFBundleDisplayName", APP_DISPLAY_NAME); | 209 | setPlistString(infoPlistPath, "CFBundleDisplayName", APP_DISPLAY_NAME); |
| 197 | setPlistString(infoPlistPath, "CFBundleName", APP_DISPLAY_NAME); | 210 | setPlistString(infoPlistPath, "CFBundleName", APP_DISPLAY_NAME); |
| 198 | setPlistString(infoPlistPath, "CFBundleIdentifier", APP_BUNDLE_ID); | 211 | setPlistString(infoPlistPath, "CFBundleIdentifier", APP_BUNDLE_ID); |
| ... | @@ -204,9 +217,9 @@ function patchMainBundleInfoPlist(appBundlePath, iconPath) { | ... | @@ -204,9 +217,9 @@ function patchMainBundleInfoPlist(appBundlePath, iconPath) { |
| 204 | }, | 217 | }, |
| 205 | ]); | 218 | ]); |
| 206 | 219 | ||
| 207 | const resourcesDir = join(appBundlePath, "Contents", "Resources"); | 220 | const resourcesDir = NodePath.join(appBundlePath, "Contents", "Resources"); |
| 208 | copyFileSync(iconPath, join(resourcesDir, "icon.icns")); | 221 | NodeFS.copyFileSync(iconPath, NodePath.join(resourcesDir, "icon.icns")); |
| 209 | copyFileSync(iconPath, join(resourcesDir, "electron.icns")); | 222 | NodeFS.copyFileSync(iconPath, NodePath.join(resourcesDir, "electron.icns")); |
| 210 | } | 223 | } |
| 211 | 224 | ||
| 212 | function patchHelperBundleInfoPlists(appBundlePath) { | 225 | function patchHelperBundleInfoPlists(appBundlePath) { |
| ... | @@ -218,7 +231,7 @@ function patchHelperBundleInfoPlists(appBundlePath) { | ... | @@ -218,7 +231,7 @@ function patchHelperBundleInfoPlists(appBundlePath) { |
| 218 | ]; | 231 | ]; |
| 219 | 232 | ||
| 220 | for (const [bundleName, bundleIdentifierSuffix, bundleDisplayName] of helperBundleNames) { | 233 | for (const [bundleName, bundleIdentifierSuffix, bundleDisplayName] of helperBundleNames) { |
| 221 | const infoPlistPath = join( | 234 | const infoPlistPath = NodePath.join( |
| 222 | appBundlePath, | 235 | appBundlePath, |
| 223 | "Contents", | 236 | "Contents", |
| 224 | "Frameworks", | 237 | "Frameworks", |
| ... | @@ -226,7 +239,7 @@ function patchHelperBundleInfoPlists(appBundlePath) { | ... | @@ -226,7 +239,7 @@ function patchHelperBundleInfoPlists(appBundlePath) { |
| 226 | "Contents", | 239 | "Contents", |
| 227 | "Info.plist", | 240 | "Info.plist", |
| 228 | ); | 241 | ); |
| 229 | if (!existsSync(infoPlistPath)) { | 242 | if (!NodeFS.existsSync(infoPlistPath)) { |
| 230 | continue; | 243 | continue; |
| 231 | } | 244 | } |
| 232 | 245 | ||
| ... | @@ -242,34 +255,34 @@ function patchHelperBundleInfoPlists(appBundlePath) { | ... | @@ -242,34 +255,34 @@ function patchHelperBundleInfoPlists(appBundlePath) { |
| 242 | 255 | ||
| 243 | function readJson(path) { | 256 | function readJson(path) { |
| 244 | try { | 257 | try { |
| 245 | return JSON.parse(readFileSync(path, "utf8")); | 258 | return JSON.parse(NodeFS.readFileSync(path, "utf8")); |
| 246 | } catch { | 259 | } catch { |
| 247 | return null; | 260 | return null; |
| 248 | } | 261 | } |
| 249 | } | 262 | } |
| 250 | 263 | ||
| 251 | function buildMacLauncher(electronBinaryPath) { | 264 | function buildMacLauncher(electronBinaryPath) { |
| 252 | const sourceAppBundlePath = resolve(dirname(electronBinaryPath), "../.."); | 265 | const sourceAppBundlePath = NodePath.resolve(NodePath.dirname(electronBinaryPath), "../.."); |
| 253 | const runtimeDir = join(desktopDir, ".electron-runtime"); | 266 | const runtimeDir = NodePath.join(desktopDir, ".electron-runtime"); |
| 254 | const targetAppBundlePath = join(runtimeDir, `${APP_DISPLAY_NAME}.app`); | 267 | const targetAppBundlePath = NodePath.join(runtimeDir, `${APP_DISPLAY_NAME}.app`); |
| 255 | const targetBinaryPath = join(targetAppBundlePath, "Contents", "MacOS", "Electron"); | 268 | const targetBinaryPath = NodePath.join(targetAppBundlePath, "Contents", "MacOS", "Electron"); |
| 256 | const iconPath = isDevelopment ? ensureDevelopmentIconIcns(runtimeDir) : defaultIconPath; | 269 | const iconPath = isDevelopment ? ensureDevelopmentIconIcns(runtimeDir) : defaultIconPath; |
| 257 | const metadataPath = join(runtimeDir, "metadata.json"); | 270 | const metadataPath = NodePath.join(runtimeDir, "metadata.json"); |
| 258 | 271 | ||
| 259 | mkdirSync(runtimeDir, { recursive: true }); | 272 | NodeFS.mkdirSync(runtimeDir, { recursive: true }); |
| 260 | 273 | ||
| 261 | const expectedMetadata = { | 274 | const expectedMetadata = { |
| 262 | launcherVersion: LAUNCHER_VERSION, | 275 | launcherVersion: LAUNCHER_VERSION, |
| 263 | sourceAppBundlePath, | 276 | sourceAppBundlePath, |
| 264 | sourceAppMtimeMs: statSync(sourceAppBundlePath).mtimeMs, | 277 | sourceAppMtimeMs: NodeFS.statSync(sourceAppBundlePath).mtimeMs, |
| 265 | iconMtimeMs: statSync(iconPath).mtimeMs, | 278 | iconMtimeMs: NodeFS.statSync(iconPath).mtimeMs, |
| 266 | appBundleId: APP_BUNDLE_ID, | 279 | appBundleId: APP_BUNDLE_ID, |
| 267 | appProtocolSchemes: APP_PROTOCOL_SCHEMES, | 280 | appProtocolSchemes: APP_PROTOCOL_SCHEMES, |
| 268 | }; | 281 | }; |
| 269 | 282 | ||
| 270 | const currentMetadata = readJson(metadataPath); | 283 | const currentMetadata = readJson(metadataPath); |
| 271 | if ( | 284 | if ( |
| 272 | existsSync(targetBinaryPath) && | 285 | NodeFS.existsSync(targetBinaryPath) && |
| 273 | currentMetadata && | 286 | currentMetadata && |
| 274 | JSON.stringify(currentMetadata) === JSON.stringify(expectedMetadata) | 287 | JSON.stringify(currentMetadata) === JSON.stringify(expectedMetadata) |
| 275 | ) { | 288 | ) { |
| ... | @@ -277,18 +290,21 @@ function buildMacLauncher(electronBinaryPath) { | ... | @@ -277,18 +290,21 @@ function buildMacLauncher(electronBinaryPath) { |
| 277 | return targetBinaryPath; | 290 | return targetBinaryPath; |
| 278 | } | 291 | } |
| 279 | 292 | ||
| 280 | rmSync(targetAppBundlePath, { recursive: true, force: true }); | 293 | NodeFS.rmSync(targetAppBundlePath, { recursive: true, force: true }); |
| 281 | // verbatimSymlinks keeps the framework's relative symlinks intact | 294 | // verbatimSymlinks keeps the framework's relative symlinks intact |
| 282 | // (e.g. Resources -> Versions/Current/Resources). Without it cpSync | 295 | // (e.g. Resources -> Versions/Current/Resources). Without it cpSync |
| 283 | // rewrites them to absolute paths into node_modules, which escape the | 296 | // rewrites them to absolute paths into node_modules, which escape the |
| 284 | // bundle and crash sandboxed helper processes (icudtl.dat not found). | 297 | // bundle and crash sandboxed helper processes (icudtl.dat not found). |
| 285 | cpSync(sourceAppBundlePath, targetAppBundlePath, { recursive: true, verbatimSymlinks: true }); | 298 | NodeFS.cpSync(sourceAppBundlePath, targetAppBundlePath, { |
| 299 | recursive: true, | ||
| 300 | verbatimSymlinks: true, | ||
| 301 | }); | ||
| 286 | patchMainBundleInfoPlist(targetAppBundlePath, iconPath); | 302 | patchMainBundleInfoPlist(targetAppBundlePath, iconPath); |
| 287 | patchHelperBundleInfoPlists(targetAppBundlePath); | 303 | patchHelperBundleInfoPlists(targetAppBundlePath); |
| 288 | if (isDevelopment) { | 304 | if (isDevelopment) { |
| 289 | writeDevelopmentLauncherScript(targetBinaryPath, electronBinaryPath); | 305 | writeDevelopmentLauncherScript(targetBinaryPath, electronBinaryPath); |
| 290 | } | 306 | } |
| 291 | writeFileSync(metadataPath, `${JSON.stringify(expectedMetadata, null, 2)}\n`); | 307 | NodeFS.writeFileSync(metadataPath, `${JSON.stringify(expectedMetadata, null, 2)}\n`); |
| 292 | registerMacLauncherBundle(targetAppBundlePath); | 308 | registerMacLauncherBundle(targetAppBundlePath); |
| 293 | 309 | ||
| 294 | return targetBinaryPath; | 310 | return targetBinaryPath; |
| ... | @@ -299,9 +315,9 @@ function isLinuxSetuidSandboxConfigured(electronBinaryPath) { | ... | @@ -299,9 +315,9 @@ function isLinuxSetuidSandboxConfigured(electronBinaryPath) { |
| 299 | return true; | 315 | return true; |
| 300 | } | 316 | } |
| 301 | 317 | ||
| 302 | const sandboxPath = join(dirname(electronBinaryPath), "chrome-sandbox"); | 318 | const sandboxPath = NodePath.join(NodePath.dirname(electronBinaryPath), "chrome-sandbox"); |
| 303 | try { | 319 | try { |
| 304 | const sandboxStat = statSync(sandboxPath); | 320 | const sandboxStat = NodeFS.statSync(sandboxPath); |
| 305 | return sandboxStat.uid === 0 && (sandboxStat.mode & 0o4777) === 0o4755; | 321 | return sandboxStat.uid === 0 && (sandboxStat.mode & 0o4777) === 0o4755; |
| 306 | } catch { | 322 | } catch { |
| 307 | return false; | 323 | return false; |
| ... | @@ -322,7 +338,7 @@ function resolveLinuxSandboxArgs(electronBinaryPath) { | ... | @@ -322,7 +338,7 @@ function resolveLinuxSandboxArgs(electronBinaryPath) { |
| 322 | export function resolveElectronPath() { | 338 | export function resolveElectronPath() { |
| 323 | ensureElectronRuntime(); | 339 | ensureElectronRuntime(); |
| 324 | 340 | ||
| 325 | const require = createRequire(import.meta.url); | 341 | const require = NodeModule.createRequire(import.meta.url); |
| 326 | const electronBinaryPath = require("electron"); | 342 | const electronBinaryPath = require("electron"); |
| 327 | 343 | ||
| 328 | if (hostPlatform !== "darwin") { | 344 | if (hostPlatform !== "darwin") { |
| ... | @@ -345,11 +361,11 @@ export function resolveDevProtocolClient() { | ... | @@ -345,11 +361,11 @@ export function resolveDevProtocolClient() { |
| 345 | return null; | 361 | return null; |
| 346 | } | 362 | } |
| 347 | 363 | ||
| 348 | const require = createRequire(import.meta.url); | 364 | const require = NodeModule.createRequire(import.meta.url); |
| 349 | const electronBinaryPath = require("electron"); | 365 | const electronBinaryPath = require("electron"); |
| 350 | const launcherBinaryPath = buildMacLauncher(electronBinaryPath); | 366 | const launcherBinaryPath = buildMacLauncher(electronBinaryPath); |
| 351 | return { | 367 | return { |
| 352 | appBundlePath: resolve(launcherBinaryPath, "..", "..", ".."), | 368 | appBundlePath: NodePath.resolve(launcherBinaryPath, "..", "..", ".."), |
| 353 | appBundleId: APP_BUNDLE_ID, | 369 | appBundleId: APP_BUNDLE_ID, |
| 354 | }; | 370 | }; |
| 355 | } | 371 | } |
apps/desktop/scripts/ensure-electron-runtime.mjs+34-32| ... | @@ -1,14 +1,14 @@ | ... | @@ -1,14 +1,14 @@ |
| 1 | import { chmodSync, existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"; | 1 | import * as NodeFS from "node:fs"; |
| 2 | import { createRequire } from "node:module"; | 2 | import * as NodeModule from "node:module"; |
| 3 | import { arch, platform, tmpdir } from "node:os"; | 3 | import * as NodeOS from "node:os"; |
| 4 | import { dirname, join } from "node:path"; | 4 | import * as NodePath from "node:path"; |
| 5 | import { spawnSync } from "node:child_process"; | 5 | import * as NodeChildProcess from "node:child_process"; |
| 6 | 6 | ||
| 7 | const require = createRequire(import.meta.url); | 7 | const require = NodeModule.createRequire(import.meta.url); |
| 8 | // oxlint-disable-next-line t3code/no-global-process-runtime -- Standalone repair script has no Effect runtime. | 8 | // oxlint-disable-next-line t3code/no-global-process-runtime -- Standalone repair script has no Effect runtime. |
| 9 | const hostPlatform = platform(); | 9 | const hostPlatform = NodeOS.platform(); |
| 10 | // oxlint-disable-next-line t3code/no-global-process-runtime -- Standalone repair script has no Effect runtime. | 10 | // oxlint-disable-next-line t3code/no-global-process-runtime -- Standalone repair script has no Effect runtime. |
| 11 | const hostArch = arch(); | 11 | const hostArch = NodeOS.arch(); |
| 12 | 12 | ||
| 13 | function getPlatformPath() { | 13 | function getPlatformPath() { |
| 14 | switch (hostPlatform) { | 14 | switch (hostPlatform) { |
| ... | @@ -27,26 +27,28 @@ function getPlatformPath() { | ... | @@ -27,26 +27,28 @@ function getPlatformPath() { |
| 27 | 27 | ||
| 28 | function ensureExecutable(filePath) { | 28 | function ensureExecutable(filePath) { |
| 29 | if (hostPlatform !== "win32") { | 29 | if (hostPlatform !== "win32") { |
| 30 | chmodSync(filePath, 0o755); | 30 | NodeFS.chmodSync(filePath, 0o755); |
| 31 | } | 31 | } |
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | function repairPathFile(electronDir, platformPath) { | 34 | function repairPathFile(electronDir, platformPath) { |
| 35 | const pathFile = join(electronDir, "path.txt"); | 35 | const pathFile = NodePath.join(electronDir, "path.txt"); |
| 36 | const currentPath = existsSync(pathFile) ? readFileSync(pathFile, "utf8") : undefined; | 36 | const currentPath = NodeFS.existsSync(pathFile) |
| 37 | ? NodeFS.readFileSync(pathFile, "utf8") | ||
| 38 | : undefined; | ||
| 37 | 39 | ||
| 38 | if (currentPath !== platformPath) { | 40 | if (currentPath !== platformPath) { |
| 39 | writeFileSync(pathFile, platformPath); | 41 | NodeFS.writeFileSync(pathFile, platformPath); |
| 40 | } | 42 | } |
| 41 | } | 43 | } |
| 42 | 44 | ||
| 43 | function getRequiredRuntimePaths(electronDir, platformPath) { | 45 | function getRequiredRuntimePaths(electronDir, platformPath) { |
| 44 | const paths = [join(electronDir, "dist", platformPath)]; | 46 | const paths = [NodePath.join(electronDir, "dist", platformPath)]; |
| 45 | 47 | ||
| 46 | if (hostPlatform === "darwin") { | 48 | if (hostPlatform === "darwin") { |
| 47 | paths.push( | 49 | paths.push( |
| 48 | join(electronDir, "dist", "Electron.app", "Contents", "Info.plist"), | 50 | NodePath.join(electronDir, "dist", "Electron.app", "Contents", "Info.plist"), |
| 49 | join( | 51 | NodePath.join( |
| 50 | electronDir, | 52 | electronDir, |
| 51 | "dist", | 53 | "dist", |
| 52 | "Electron.app", | 54 | "Electron.app", |
| ... | @@ -66,7 +68,7 @@ function isMachO(filePath) { | ... | @@ -66,7 +68,7 @@ function isMachO(filePath) { |
| 66 | return true; | 68 | return true; |
| 67 | } | 69 | } |
| 68 | 70 | ||
| 69 | const result = spawnSync("file", ["-b", filePath], { | 71 | const result = NodeChildProcess.spawnSync("file", ["-b", filePath], { |
| 70 | encoding: "utf8", | 72 | encoding: "utf8", |
| 71 | }); | 73 | }); |
| 72 | 74 | ||
| ... | @@ -75,7 +77,7 @@ function isMachO(filePath) { | ... | @@ -75,7 +77,7 @@ function isMachO(filePath) { |
| 75 | 77 | ||
| 76 | function missingRuntimePaths(electronDir, platformPath) { | 78 | function missingRuntimePaths(electronDir, platformPath) { |
| 77 | return getRequiredRuntimePaths(electronDir, platformPath).filter((runtimePath) => { | 79 | return getRequiredRuntimePaths(electronDir, platformPath).filter((runtimePath) => { |
| 78 | return !existsSync(runtimePath); | 80 | return !NodeFS.existsSync(runtimePath); |
| 79 | }); | 81 | }); |
| 80 | } | 82 | } |
| 81 | 83 | ||
| ... | @@ -85,8 +87,8 @@ function invalidRuntimePaths(electronDir, platformPath) { | ... | @@ -85,8 +87,8 @@ function invalidRuntimePaths(electronDir, platformPath) { |
| 85 | } | 87 | } |
| 86 | 88 | ||
| 87 | return [ | 89 | return [ |
| 88 | join(electronDir, "dist", platformPath), | 90 | NodePath.join(electronDir, "dist", platformPath), |
| 89 | join( | 91 | NodePath.join( |
| 90 | electronDir, | 92 | electronDir, |
| 91 | "dist", | 93 | "dist", |
| 92 | "Electron.app", | 94 | "Electron.app", |
| ... | @@ -95,11 +97,11 @@ function invalidRuntimePaths(electronDir, platformPath) { | ... | @@ -95,11 +97,11 @@ function invalidRuntimePaths(electronDir, platformPath) { |
| 95 | "Electron Framework.framework", | 97 | "Electron Framework.framework", |
| 96 | "Electron Framework", | 98 | "Electron Framework", |
| 97 | ), | 99 | ), |
| 98 | ].filter((runtimePath) => existsSync(runtimePath) && !isMachO(runtimePath)); | 100 | ].filter((runtimePath) => NodeFS.existsSync(runtimePath) && !isMachO(runtimePath)); |
| 99 | } | 101 | } |
| 100 | 102 | ||
| 101 | function runChecked(command, args) { | 103 | function runChecked(command, args) { |
| 102 | const result = spawnSync(command, args, { | 104 | const result = NodeChildProcess.spawnSync(command, args, { |
| 103 | encoding: "utf8", | 105 | encoding: "utf8", |
| 104 | stdio: "inherit", | 106 | stdio: "inherit", |
| 105 | }); | 107 | }); |
| ... | @@ -114,8 +116,8 @@ function runChecked(command, args) { | ... | @@ -114,8 +116,8 @@ function runChecked(command, args) { |
| 114 | } | 116 | } |
| 115 | 117 | ||
| 116 | function installElectronRuntime(electronDir, version) { | 118 | function installElectronRuntime(electronDir, version) { |
| 117 | const tempDir = mkdtempSync(join(tmpdir(), "t3-electron-")); | 119 | const tempDir = NodeFS.mkdtempSync(NodePath.join(NodeOS.tmpdir(), "t3-electron-")); |
| 118 | const zipPath = join(tempDir, `electron-v${version}-${hostPlatform}-${hostArch}.zip`); | 120 | const zipPath = NodePath.join(tempDir, `electron-v${version}-${hostPlatform}-${hostArch}.zip`); |
| 119 | 121 | ||
| 120 | try { | 122 | try { |
| 121 | runChecked("curl", [ | 123 | runChecked("curl", [ |
| ... | @@ -125,34 +127,34 @@ function installElectronRuntime(electronDir, version) { | ... | @@ -125,34 +127,34 @@ function installElectronRuntime(electronDir, version) { |
| 125 | zipPath, | 127 | zipPath, |
| 126 | ]); | 128 | ]); |
| 127 | if (hostPlatform === "darwin") { | 129 | if (hostPlatform === "darwin") { |
| 128 | runChecked("ditto", ["-x", "-k", zipPath, join(electronDir, "dist")]); | 130 | runChecked("ditto", ["-x", "-k", zipPath, NodePath.join(electronDir, "dist")]); |
| 129 | } else { | 131 | } else { |
| 130 | runChecked("python3", [ | 132 | runChecked("python3", [ |
| 131 | "-c", | 133 | "-c", |
| 132 | "import os, sys, zipfile; os.makedirs(sys.argv[2], exist_ok=True); zipfile.ZipFile(sys.argv[1]).extractall(sys.argv[2])", | 134 | "import os, sys, zipfile; os.makedirs(sys.argv[2], exist_ok=True); zipfile.ZipFile(sys.argv[1]).extractall(sys.argv[2])", |
| 133 | zipPath, | 135 | zipPath, |
| 134 | join(electronDir, "dist"), | 136 | NodePath.join(electronDir, "dist"), |
| 135 | ]); | 137 | ]); |
| 136 | } | 138 | } |
| 137 | } finally { | 139 | } finally { |
| 138 | rmSync(tempDir, { recursive: true, force: true }); | 140 | NodeFS.rmSync(tempDir, { recursive: true, force: true }); |
| 139 | } | 141 | } |
| 140 | } | 142 | } |
| 141 | 143 | ||
| 142 | export function ensureElectronRuntime() { | 144 | export function ensureElectronRuntime() { |
| 143 | const electronPackageJsonPath = require.resolve("electron/package.json"); | 145 | const electronPackageJsonPath = require.resolve("electron/package.json"); |
| 144 | const electronPackageJson = JSON.parse(readFileSync(electronPackageJsonPath, "utf8")); | 146 | const electronPackageJson = JSON.parse(NodeFS.readFileSync(electronPackageJsonPath, "utf8")); |
| 145 | const electronDir = dirname(electronPackageJsonPath); | 147 | const electronDir = NodePath.dirname(electronPackageJsonPath); |
| 146 | const platformPath = getPlatformPath(); | 148 | const platformPath = getPlatformPath(); |
| 147 | const electronPath = join(electronDir, "dist", platformPath); | 149 | const electronPath = NodePath.join(electronDir, "dist", platformPath); |
| 148 | const missingBeforeInstall = missingRuntimePaths(electronDir, platformPath); | 150 | const missingBeforeInstall = missingRuntimePaths(electronDir, platformPath); |
| 149 | const invalidBeforeInstall = invalidRuntimePaths(electronDir, platformPath); | 151 | const invalidBeforeInstall = invalidRuntimePaths(electronDir, platformPath); |
| 150 | 152 | ||
| 151 | if (missingBeforeInstall.length > 0 || invalidBeforeInstall.length > 0) { | 153 | if (missingBeforeInstall.length > 0 || invalidBeforeInstall.length > 0) { |
| 152 | if (existsSync(join(electronDir, "dist"))) { | 154 | if (NodeFS.existsSync(NodePath.join(electronDir, "dist"))) { |
| 153 | rmSync(join(electronDir, "dist"), { recursive: true, force: true }); | 155 | NodeFS.rmSync(NodePath.join(electronDir, "dist"), { recursive: true, force: true }); |
| 154 | } | 156 | } |
| 155 | rmSync(join(electronDir, "path.txt"), { force: true }); | 157 | NodeFS.rmSync(NodePath.join(electronDir, "path.txt"), { force: true }); |
| 156 | installElectronRuntime(electronDir, electronPackageJson.version); | 158 | installElectronRuntime(electronDir, electronPackageJson.version); |
| 157 | } | 159 | } |
| 158 | 160 |
apps/desktop/scripts/smoke-test.mjs+7-7| ... | @@ -1,16 +1,16 @@ | ... | @@ -1,16 +1,16 @@ |
| 1 | import { spawn } from "node:child_process"; | 1 | import * as NodeChildProcess from "node:child_process"; |
| 2 | import { dirname, resolve } from "node:path"; | 2 | import * as NodePath from "node:path"; |
| 3 | import { fileURLToPath } from "node:url"; | 3 | import * as NodeURL from "node:url"; |
| 4 | import { resolveElectronLaunchCommand } from "./electron-launcher.mjs"; | 4 | import { resolveElectronLaunchCommand } from "./electron-launcher.mjs"; |
| 5 | 5 | ||
| 6 | const __dirname = dirname(fileURLToPath(import.meta.url)); | 6 | const __dirname = NodePath.dirname(NodeURL.fileURLToPath(import.meta.url)); |
| 7 | const desktopDir = resolve(__dirname, ".."); | 7 | const desktopDir = NodePath.resolve(__dirname, ".."); |
| 8 | const mainJs = resolve(desktopDir, "dist-electron/main.cjs"); | 8 | const mainJs = NodePath.resolve(desktopDir, "dist-electron/main.cjs"); |
| 9 | 9 | ||
| 10 | console.log("\nLaunching Electron smoke test..."); | 10 | console.log("\nLaunching Electron smoke test..."); |
| 11 | 11 | ||
| 12 | const electronCommand = resolveElectronLaunchCommand([mainJs]); | 12 | const electronCommand = resolveElectronLaunchCommand([mainJs]); |
| 13 | const child = spawn(electronCommand.electronPath, electronCommand.args, { | 13 | const child = NodeChildProcess.spawn(electronCommand.electronPath, electronCommand.args, { |
| 14 | stdio: ["pipe", "pipe", "pipe"], | 14 | stdio: ["pipe", "pipe", "pipe"], |
| 15 | env: { | 15 | env: { |
| 16 | ...process.env, | 16 | ...process.env, |
apps/desktop/scripts/start-electron.mjs+2-2| ... | @@ -1,4 +1,4 @@ | ... | @@ -1,4 +1,4 @@ |
| 1 | import { spawn } from "node:child_process"; | 1 | import * as NodeChildProcess from "node:child_process"; |
| 2 | 2 | ||
| 3 | import { desktopDir, resolveElectronLaunchCommand } from "./electron-launcher.mjs"; | 3 | import { desktopDir, resolveElectronLaunchCommand } from "./electron-launcher.mjs"; |
| 4 | 4 | ||
| ... | @@ -6,7 +6,7 @@ const childEnv = { ...process.env }; | ... | @@ -6,7 +6,7 @@ const childEnv = { ...process.env }; |
| 6 | delete childEnv.ELECTRON_RUN_AS_NODE; | 6 | delete childEnv.ELECTRON_RUN_AS_NODE; |
| 7 | 7 | ||
| 8 | const electronCommand = resolveElectronLaunchCommand(["dist-electron/main.cjs"]); | 8 | const electronCommand = resolveElectronLaunchCommand(["dist-electron/main.cjs"]); |
| 9 | const child = spawn(electronCommand.electronPath, electronCommand.args, { | 9 | const child = NodeChildProcess.spawn(electronCommand.electronPath, electronCommand.args, { |
| 10 | stdio: "inherit", | 10 | stdio: "inherit", |
| 11 | cwd: desktopDir, | 11 | cwd: desktopDir, |
| 12 | env: childEnv, | 12 | env: childEnv, |
apps/desktop/scripts/wait-for-resources.mjs+8-8| ... | @@ -1,13 +1,13 @@ | ... | @@ -1,13 +1,13 @@ |
| 1 | import * as FileSystem from "node:fs/promises"; | 1 | import * as NodeFSP from "node:fs/promises"; |
| 2 | import * as Net from "node:net"; | 2 | import * as NodeNet from "node:net"; |
| 3 | import * as Path from "node:path"; | 3 | import * as NodePath from "node:path"; |
| 4 | import * as Timers from "node:timers/promises"; | 4 | import * as NodeTimersPromises from "node:timers/promises"; |
| 5 | 5 | ||
| 6 | const defaultTcpHosts = ["127.0.0.1", "localhost", "::1"]; | 6 | const defaultTcpHosts = ["127.0.0.1", "localhost", "::1"]; |
| 7 | 7 | ||
| 8 | async function fileExists(filePath) { | 8 | async function fileExists(filePath) { |
| 9 | try { | 9 | try { |
| 10 | await FileSystem.access(filePath); | 10 | await NodeFSP.access(filePath); |
| 11 | return true; | 11 | return true; |
| 12 | } catch { | 12 | } catch { |
| 13 | return false; | 13 | return false; |
| ... | @@ -16,7 +16,7 @@ async function fileExists(filePath) { | ... | @@ -16,7 +16,7 @@ async function fileExists(filePath) { |
| 16 | 16 | ||
| 17 | function tcpPortIsReady({ host, port, connectTimeoutMs = 500 }) { | 17 | function tcpPortIsReady({ host, port, connectTimeoutMs = 500 }) { |
| 18 | return new Promise((resolveReady) => { | 18 | return new Promise((resolveReady) => { |
| 19 | const socket = Net.createConnection({ host, port }); | 19 | const socket = NodeNet.createConnection({ host, port }); |
| 20 | let settled = false; | 20 | let settled = false; |
| 21 | 21 | ||
| 22 | const finish = (ready) => { | 22 | const finish = (ready) => { |
| ... | @@ -47,7 +47,7 @@ async function resolvePendingResources({ baseDir, files, tcpPort, tcpHosts, conn | ... | @@ -47,7 +47,7 @@ async function resolvePendingResources({ baseDir, files, tcpPort, tcpHosts, conn |
| 47 | const pendingFiles = []; | 47 | const pendingFiles = []; |
| 48 | 48 | ||
| 49 | for (const relativeFilePath of files) { | 49 | for (const relativeFilePath of files) { |
| 50 | const ready = await fileExists(Path.resolve(baseDir, relativeFilePath)); | 50 | const ready = await fileExists(NodePath.resolve(baseDir, relativeFilePath)); |
| 51 | if (!ready) { | 51 | if (!ready) { |
| 52 | pendingFiles.push(relativeFilePath); | 52 | pendingFiles.push(relativeFilePath); |
| 53 | } | 53 | } |
| ... | @@ -114,6 +114,6 @@ export async function waitForResources({ | ... | @@ -114,6 +114,6 @@ export async function waitForResources({ |
| 114 | ); | 114 | ); |
| 115 | } | 115 | } |
| 116 | 116 | ||
| 117 | await Timers.setTimeout(intervalMs); | 117 | await NodeTimersPromises.setTimeout(intervalMs); |
| 118 | } | 118 | } |
| 119 | } | 119 | } |
apps/desktop/src/backend/DesktopNetworkInterfaces.ts+2-2| ... | @@ -1,4 +1,4 @@ | ... | @@ -1,4 +1,4 @@ |
| 1 | import { networkInterfaces } from "node:os"; | 1 | import * as NodeOS from "node:os"; |
| 2 | 2 | ||
| 3 | import * as Context from "effect/Context"; | 3 | import * as Context from "effect/Context"; |
| 4 | import * as Effect from "effect/Effect"; | 4 | import * as Effect from "effect/Effect"; |
| ... | @@ -27,7 +27,7 @@ export class DesktopNetworkInterfaces extends Context.Service< | ... | @@ -27,7 +27,7 @@ export class DesktopNetworkInterfaces extends Context.Service< |
| 27 | 27 | ||
| 28 | export const make = (): DesktopNetworkInterfaces["Service"] => | 28 | export const make = (): DesktopNetworkInterfaces["Service"] => |
| 29 | DesktopNetworkInterfaces.of({ | 29 | DesktopNetworkInterfaces.of({ |
| 30 | read: Effect.sync(() => networkInterfaces()), | 30 | read: Effect.sync(() => NodeOS.networkInterfaces()), |
| 31 | }); | 31 | }); |
| 32 | 32 | ||
| 33 | export const layer = Layer.succeed(DesktopNetworkInterfaces, make()); | 33 | export const layer = Layer.succeed(DesktopNetworkInterfaces, make()); |
apps/desktop/src/ipc/methods/preview.ts+2-2| ... | @@ -22,7 +22,7 @@ import { | ... | @@ -22,7 +22,7 @@ import { |
| 22 | import { BrowserWindow } from "electron"; | 22 | import { BrowserWindow } from "electron"; |
| 23 | import * as Effect from "effect/Effect"; | 23 | import * as Effect from "effect/Effect"; |
| 24 | import * as Schema from "effect/Schema"; | 24 | import * as Schema from "effect/Schema"; |
| 25 | import { pathToFileURL } from "node:url"; | 25 | import * as NodeURL from "node:url"; |
| 26 | 26 | ||
| 27 | import * as PreviewManager from "../../preview/Manager.ts"; | 27 | import * as PreviewManager from "../../preview/Manager.ts"; |
| 28 | import { PREVIEW_WEBVIEW_PREFERENCES } from "../../preview/WebviewPreferences.ts"; | 28 | import { PREVIEW_WEBVIEW_PREFERENCES } from "../../preview/WebviewPreferences.ts"; |
| ... | @@ -196,7 +196,7 @@ export const getPreviewConfig = DesktopIpc.makeIpcMethod({ | ... | @@ -196,7 +196,7 @@ export const getPreviewConfig = DesktopIpc.makeIpcMethod({ |
| 196 | return { | 196 | return { |
| 197 | partition: yield* manager.getBrowserPartition(environmentId), | 197 | partition: yield* manager.getBrowserPartition(environmentId), |
| 198 | webPreferences: PREVIEW_WEBVIEW_PREFERENCES, | 198 | webPreferences: PREVIEW_WEBVIEW_PREFERENCES, |
| 199 | preloadUrl: pathToFileURL(`${__dirname}/preview-pick-preload.cjs`).href, | 199 | preloadUrl: NodeURL.pathToFileURL(`${__dirname}/preview-pick-preload.cjs`).href, |
| 200 | }; | 200 | }; |
| 201 | }), | 201 | }), |
| 202 | }); | 202 | }); |
apps/desktop/src/preview/PlaywrightInjectedRuntime.ts+11-7| ... | @@ -1,14 +1,14 @@ | ... | @@ -1,14 +1,14 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off - Extracts Playwright's installed Node bundle for browser injection. | 1 | // @effect-diagnostics nodeBuiltinImport:off - Extracts Playwright's installed Node bundle for browser injection. |
| 2 | import { readFile } from "node:fs/promises"; | 2 | import * as NodeFSP from "node:fs/promises"; |
| 3 | import { createRequire } from "node:module"; | 3 | import * as NodeModule from "node:module"; |
| 4 | import { dirname, join } from "node:path"; | 4 | import * as NodePath from "node:path"; |
| 5 | import { runInNewContext } from "node:vm"; | 5 | import * as NodeVM from "node:vm"; |
| 6 | 6 | ||
| 7 | import * as Data from "effect/Data"; | 7 | import * as Data from "effect/Data"; |
| 8 | import * as Effect from "effect/Effect"; | 8 | import * as Effect from "effect/Effect"; |
| 9 | import * as Schema from "effect/Schema"; | 9 | import * as Schema from "effect/Schema"; |
| 10 | 10 | ||
| 11 | const require = createRequire(import.meta.url); | 11 | const require = NodeModule.createRequire(import.meta.url); |
| 12 | const encodeUnknownJson = Schema.encodeUnknownEffect(Schema.UnknownFromJsonString); | 12 | const encodeUnknownJson = Schema.encodeUnknownEffect(Schema.UnknownFromJsonString); |
| 13 | 13 | ||
| 14 | export class PlaywrightInjectedRuntimeError extends Data.TaggedError( | 14 | export class PlaywrightInjectedRuntimeError extends Data.TaggedError( |
| ... | @@ -32,7 +32,11 @@ export const playwrightInjectedRuntimeSource = Effect.fn("PlaywrightInjectedRunt | ... | @@ -32,7 +32,11 @@ export const playwrightInjectedRuntimeSource = Effect.fn("PlaywrightInjectedRunt |
| 32 | catch: (cause) => fail("resolvePackage", cause), | 32 | catch: (cause) => fail("resolvePackage", cause), |
| 33 | }); | 33 | }); |
| 34 | const coreBundle = yield* Effect.tryPromise({ | 34 | const coreBundle = yield* Effect.tryPromise({ |
| 35 | try: () => readFile(join(dirname(packageJsonPath), "lib/coreBundle.js"), "utf8"), | 35 | try: () => |
| 36 | NodeFSP.readFile( | ||
| 37 | NodePath.join(NodePath.dirname(packageJsonPath), "lib/coreBundle.js"), | ||
| 38 | "utf8", | ||
| 39 | ), | ||
| 36 | catch: (cause) => fail("readCoreBundle", cause), | 40 | catch: (cause) => fail("readCoreBundle", cause), |
| 37 | }); | 41 | }); |
| 38 | const marker = "source3 = "; | 42 | const marker = "source3 = "; |
| ... | @@ -53,7 +57,7 @@ export const playwrightInjectedRuntimeSource = Effect.fn("PlaywrightInjectedRunt | ... | @@ -53,7 +57,7 @@ export const playwrightInjectedRuntimeSource = Effect.fn("PlaywrightInjectedRunt |
| 53 | } | 57 | } |
| 54 | const literal = coreBundle.slice(literalStart, literalEnd); | 58 | const literal = coreBundle.slice(literalStart, literalEnd); |
| 55 | const source = yield* Effect.try({ | 59 | const source = yield* Effect.try({ |
| 56 | try: () => runInNewContext(literal, Object.create(null), { timeout: 1_000 }), | 60 | try: () => NodeVM.runInNewContext(literal, Object.create(null), { timeout: 1_000 }), |
| 57 | catch: (cause) => fail("evaluateSourceLiteral", cause), | 61 | catch: (cause) => fail("evaluateSourceLiteral", cause), |
| 58 | }); | 62 | }); |
| 59 | if (typeof source !== "string" || source.length < 100_000) { | 63 | if (typeof source !== "string" || source.length < 100_000) { |
apps/mobile/modules/t3-markdown-text/scripts/sync-pierre-file-icons.mjs+21-18| ... | @@ -1,16 +1,19 @@ | ... | @@ -1,16 +1,19 @@ |
| 1 | import { execFileSync } from "node:child_process"; | 1 | import * as NodeChildProcess from "node:child_process"; |
| 2 | import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs"; | 2 | import * as NodeFS from "node:fs"; |
| 3 | import { dirname, join, resolve } from "node:path"; | 3 | import * as NodePath from "node:path"; |
| 4 | import { fileURLToPath } from "node:url"; | 4 | import * as NodeURL from "node:url"; |
| 5 | 5 | ||
| 6 | import { getBuiltInSpriteSheet } from "@pierre/trees"; | 6 | import { getBuiltInSpriteSheet } from "@pierre/trees"; |
| 7 | 7 | ||
| 8 | const scriptDirectory = dirname(fileURLToPath(import.meta.url)); | 8 | const scriptDirectory = NodePath.dirname(NodeURL.fileURLToPath(import.meta.url)); |
| 9 | const moduleDirectory = resolve(scriptDirectory, ".."); | 9 | const moduleDirectory = NodePath.resolve(scriptDirectory, ".."); |
| 10 | const repositoryRoot = resolve(moduleDirectory, "../../../.."); | 10 | const repositoryRoot = NodePath.resolve(moduleDirectory, "../../../.."); |
| 11 | const outputDirectory = join(moduleDirectory, "assets/file-icons"); | 11 | const outputDirectory = NodePath.join(moduleDirectory, "assets/file-icons"); |
| 12 | const generatedModulePath = join(moduleDirectory, "src/markdownFileIcons.generated.ts"); | 12 | const generatedModulePath = NodePath.join(moduleDirectory, "src/markdownFileIcons.generated.ts"); |
| 13 | const webIconSource = readFileSync(join(repositoryRoot, "apps/web/src/pierre-icons.ts"), "utf8"); | 13 | const webIconSource = NodeFS.readFileSync( |
| 14 | NodePath.join(repositoryRoot, "apps/web/src/pierre-icons.ts"), | ||
| 15 | "utf8", | ||
| 16 | ); | ||
| 14 | const customSprite = webIconSource.match(/const T3_FILE_ICON_SPRITE = `([\s\S]*?)`;/)?.[1]; | 17 | const customSprite = webIconSource.match(/const T3_FILE_ICON_SPRITE = `([\s\S]*?)`;/)?.[1]; |
| 15 | 18 | ||
| 16 | if (!customSprite) { | 19 | if (!customSprite) { |
| ... | @@ -95,20 +98,20 @@ function symbolFromSprite(sprite, id) { | ... | @@ -95,20 +98,20 @@ function symbolFromSprite(sprite, id) { |
| 95 | } | 98 | } |
| 96 | 99 | ||
| 97 | function renderIcon(token, symbol, color) { | 100 | function renderIcon(token, symbol, color) { |
| 98 | const svgPath = join(outputDirectory, `.pierre-${token}.svg`); | 101 | const svgPath = NodePath.join(outputDirectory, `.pierre-${token}.svg`); |
| 99 | const pngPath = join(outputDirectory, `pierre_${token}.png`); | 102 | const pngPath = NodePath.join(outputDirectory, `pierre_${token}.png`); |
| 100 | writeFileSync( | 103 | NodeFS.writeFileSync( |
| 101 | svgPath, | 104 | svgPath, |
| 102 | `<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="${symbol.viewBox}" style="color:${color}">${symbol.body}</svg>`, | 105 | `<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="${symbol.viewBox}" style="color:${color}">${symbol.body}</svg>`, |
| 103 | ); | 106 | ); |
| 104 | execFileSync("sips", ["-s", "format", "png", svgPath, "--out", pngPath], { | 107 | NodeChildProcess.execFileSync("sips", ["-s", "format", "png", svgPath, "--out", pngPath], { |
| 105 | stdio: "ignore", | 108 | stdio: "ignore", |
| 106 | }); | 109 | }); |
| 107 | rmSync(svgPath); | 110 | NodeFS.rmSync(svgPath); |
| 108 | } | 111 | } |
| 109 | 112 | ||
| 110 | rmSync(outputDirectory, { recursive: true, force: true }); | 113 | NodeFS.rmSync(outputDirectory, { recursive: true, force: true }); |
| 111 | mkdirSync(outputDirectory, { recursive: true }); | 114 | NodeFS.mkdirSync(outputDirectory, { recursive: true }); |
| 112 | 115 | ||
| 113 | const builtInSprite = getBuiltInSpriteSheet("complete"); | 116 | const builtInSprite = getBuiltInSpriteSheet("complete"); |
| 114 | const builtInTokens = [...builtInSprite.matchAll(/<symbol id="file-tree-builtin-([^"]+)"/g)] | 117 | const builtInTokens = [...builtInSprite.matchAll(/<symbol id="file-tree-builtin-([^"]+)"/g)] |
| ... | @@ -130,4 +133,4 @@ const tokens = [...new Set([...builtInTokens, ...Object.keys(customIcons)])].sor | ... | @@ -130,4 +133,4 @@ const tokens = [...new Set([...builtInTokens, ...Object.keys(customIcons)])].sor |
| 130 | const generatedSource = `import type { ImageSourcePropType } from "react-native";\n\nexport const MARKDOWN_FILE_ICON_SOURCES = {\n${tokens | 133 | const generatedSource = `import type { ImageSourcePropType } from "react-native";\n\nexport const MARKDOWN_FILE_ICON_SOURCES = {\n${tokens |
| 131 | .map((token) => ` ${token}: require("../assets/file-icons/pierre_${token}.png"),`) | 134 | .map((token) => ` ${token}: require("../assets/file-icons/pierre_${token}.png"),`) |
| 132 | .join("\n")}\n} as const satisfies Readonly<Record<string, ImageSourcePropType>>;\n`; | 135 | .join("\n")}\n} as const satisfies Readonly<Record<string, ImageSourcePropType>>;\n`; |
| 133 | writeFileSync(generatedModulePath, generatedSource); | 136 | NodeFS.writeFileSync(generatedModulePath, generatedSource); |
apps/server/integration/OrchestrationEngineHarness.integration.ts+2-2| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off | 1 | // @effect-diagnostics nodeBuiltinImport:off |
| 2 | import { execFileSync } from "node:child_process"; | 2 | import * as NodeChildProcess from "node:child_process"; |
| 3 | 3 | ||
| 4 | import * as NodeServices from "@effect/platform-node/NodeServices"; | 4 | import * as NodeServices from "@effect/platform-node/NodeServices"; |
| 5 | import { | 5 | import { |
| ... | @@ -82,7 +82,7 @@ import * as AgentAwarenessRelay from "../src/relay/AgentAwarenessRelay.ts"; | ... | @@ -82,7 +82,7 @@ import * as AgentAwarenessRelay from "../src/relay/AgentAwarenessRelay.ts"; |
| 82 | const decodeCodexSettings = Schema.decodeEffect(CodexSettings); | 82 | const decodeCodexSettings = Schema.decodeEffect(CodexSettings); |
| 83 | 83 | ||
| 84 | function runGit(cwd: string, args: ReadonlyArray<string>) { | 84 | function runGit(cwd: string, args: ReadonlyArray<string>) { |
| 85 | return execFileSync("git", args, { | 85 | return NodeChildProcess.execFileSync("git", args, { |
| 86 | cwd, | 86 | cwd, |
| 87 | stdio: ["ignore", "pipe", "pipe"], | 87 | stdio: ["ignore", "pipe", "pipe"], |
| 88 | encoding: "utf8", | 88 | encoding: "utf8", |
apps/server/integration/orchestrationEngine.integration.test.ts+12-9| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off | 1 | // @effect-diagnostics nodeBuiltinImport:off |
| 2 | import fs from "node:fs"; | 2 | import * as NodeFS from "node:fs"; |
| 3 | import path from "node:path"; | 3 | import * as NodePath from "node:path"; |
| 4 | 4 | ||
| 5 | import { | 5 | import { |
| 6 | ApprovalRequestId, | 6 | ApprovalRequestId, |
| ... | @@ -409,7 +409,7 @@ it.live("runs multi-turn file edits and persists checkpoint diffs", () => | ... | @@ -409,7 +409,7 @@ it.live("runs multi-turn file edits and persists checkpoint diffs", () => |
| 409 | ], | 409 | ], |
| 410 | mutateWorkspace: ({ cwd }) => | 410 | mutateWorkspace: ({ cwd }) => |
| 411 | Effect.sync(() => { | 411 | Effect.sync(() => { |
| 412 | fs.writeFileSync(path.join(cwd, "README.md"), "v2\n", "utf8"); | 412 | NodeFS.writeFileSync(NodePath.join(cwd, "README.md"), "v2\n", "utf8"); |
| 413 | }), | 413 | }), |
| 414 | }); | 414 | }); |
| 415 | 415 | ||
| ... | @@ -456,7 +456,7 @@ it.live("runs multi-turn file edits and persists checkpoint diffs", () => | ... | @@ -456,7 +456,7 @@ it.live("runs multi-turn file edits and persists checkpoint diffs", () => |
| 456 | ], | 456 | ], |
| 457 | mutateWorkspace: ({ cwd }) => | 457 | mutateWorkspace: ({ cwd }) => |
| 458 | Effect.sync(() => { | 458 | Effect.sync(() => { |
| 459 | fs.writeFileSync(path.join(cwd, "README.md"), "v3\n", "utf8"); | 459 | NodeFS.writeFileSync(NodePath.join(cwd, "README.md"), "v3\n", "utf8"); |
| 460 | }), | 460 | }), |
| 461 | }); | 461 | }); |
| 462 | 462 | ||
| ... | @@ -752,7 +752,7 @@ it.live("reverts to an earlier checkpoint and trims checkpoint projections + git | ... | @@ -752,7 +752,7 @@ it.live("reverts to an earlier checkpoint and trims checkpoint projections + git |
| 752 | ], | 752 | ], |
| 753 | mutateWorkspace: ({ cwd }) => | 753 | mutateWorkspace: ({ cwd }) => |
| 754 | Effect.sync(() => { | 754 | Effect.sync(() => { |
| 755 | fs.writeFileSync(path.join(cwd, "README.md"), "v2\n", "utf8"); | 755 | NodeFS.writeFileSync(NodePath.join(cwd, "README.md"), "v2\n", "utf8"); |
| 756 | }), | 756 | }), |
| 757 | }); | 757 | }); |
| 758 | yield* startTurn({ | 758 | yield* startTurn({ |
| ... | @@ -811,7 +811,7 @@ it.live("reverts to an earlier checkpoint and trims checkpoint projections + git | ... | @@ -811,7 +811,7 @@ it.live("reverts to an earlier checkpoint and trims checkpoint projections + git |
| 811 | ], | 811 | ], |
| 812 | mutateWorkspace: ({ cwd }) => | 812 | mutateWorkspace: ({ cwd }) => |
| 813 | Effect.sync(() => { | 813 | Effect.sync(() => { |
| 814 | fs.writeFileSync(path.join(cwd, "README.md"), "v3\n", "utf8"); | 814 | NodeFS.writeFileSync(NodePath.join(cwd, "README.md"), "v3\n", "utf8"); |
| 815 | }), | 815 | }), |
| 816 | }); | 816 | }); |
| 817 | yield* startTurn({ | 817 | yield* startTurn({ |
| ... | @@ -869,7 +869,10 @@ it.live("reverts to an earlier checkpoint and trims checkpoint projections + git | ... | @@ -869,7 +869,10 @@ it.live("reverts to an earlier checkpoint and trims checkpoint projections + git |
| 869 | ), | 869 | ), |
| 870 | true, | 870 | true, |
| 871 | ); | 871 | ); |
| 872 | assert.equal(fs.readFileSync(path.join(harness.workspaceDir, "README.md"), "utf8"), "v2\n"); | 872 | assert.equal( |
| 873 | NodeFS.readFileSync(NodePath.join(harness.workspaceDir, "README.md"), "utf8"), | ||
| 874 | "v2\n", | ||
| 875 | ); | ||
| 873 | assert.equal( | 876 | assert.equal( |
| 874 | gitRefExists(harness.workspaceDir, checkpointRefForThreadTurn(THREAD_ID, 2)), | 877 | gitRefExists(harness.workspaceDir, checkpointRefForThreadTurn(THREAD_ID, 2)), |
| 875 | false, | 878 | false, |
| ... | @@ -1332,7 +1335,7 @@ it.live("reverts claudeAgent turns and rolls back provider conversation state", | ... | @@ -1332,7 +1335,7 @@ it.live("reverts claudeAgent turns and rolls back provider conversation state", |
| 1332 | ], | 1335 | ], |
| 1333 | mutateWorkspace: ({ cwd }) => | 1336 | mutateWorkspace: ({ cwd }) => |
| 1334 | Effect.sync(() => { | 1337 | Effect.sync(() => { |
| 1335 | fs.writeFileSync(path.join(cwd, "README.md"), "v2\n", "utf8"); | 1338 | NodeFS.writeFileSync(NodePath.join(cwd, "README.md"), "v2\n", "utf8"); |
| 1336 | }), | 1339 | }), |
| 1337 | }); | 1340 | }); |
| 1338 | 1341 | ||
| ... | @@ -1390,7 +1393,7 @@ it.live("reverts claudeAgent turns and rolls back provider conversation state", | ... | @@ -1390,7 +1393,7 @@ it.live("reverts claudeAgent turns and rolls back provider conversation state", |
| 1390 | ], | 1393 | ], |
| 1391 | mutateWorkspace: ({ cwd }) => | 1394 | mutateWorkspace: ({ cwd }) => |
| 1392 | Effect.sync(() => { | 1395 | Effect.sync(() => { |
| 1393 | fs.writeFileSync(path.join(cwd, "README.md"), "v3\n", "utf8"); | 1396 | NodeFS.writeFileSync(NodePath.join(cwd, "README.md"), "v3\n", "utf8"); |
| 1394 | }), | 1397 | }), |
| 1395 | }); | 1398 | }); |
| 1396 | 1399 |
apps/server/scripts/acp-mock-agent.ts+3-3| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | #!/usr/bin/env node | 1 | #!/usr/bin/env node |
| 2 | // @effect-diagnostics nodeBuiltinImport:off | 2 | // @effect-diagnostics nodeBuiltinImport:off |
| 3 | import { appendFileSync } from "node:fs"; | 3 | import * as NodeFS from "node:fs"; |
| 4 | 4 | ||
| 5 | import * as Effect from "effect/Effect"; | 5 | import * as Effect from "effect/Effect"; |
| 6 | 6 | ||
| ... | @@ -42,7 +42,7 @@ function logExit(reason: string): void { | ... | @@ -42,7 +42,7 @@ function logExit(reason: string): void { |
| 42 | if (!exitLogPath) { | 42 | if (!exitLogPath) { |
| 43 | return; | 43 | return; |
| 44 | } | 44 | } |
| 45 | appendFileSync(exitLogPath, `${reason}\n`, "utf8"); | 45 | NodeFS.appendFileSync(exitLogPath, `${reason}\n`, "utf8"); |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | process.once("SIGTERM", () => { | 48 | process.once("SIGTERM", () => { |
| ... | @@ -693,7 +693,7 @@ const program = Effect.gen(function* () { | ... | @@ -693,7 +693,7 @@ const program = Effect.gen(function* () { |
| 693 | } | 693 | } |
| 694 | const payload = event.payload; | 694 | const payload = event.payload; |
| 695 | return Effect.sync(() => { | 695 | return Effect.sync(() => { |
| 696 | appendFileSync( | 696 | NodeFS.appendFileSync( |
| 697 | requestLogPath, | 697 | requestLogPath, |
| 698 | payload.endsWith("\n") ? payload : `${payload}\n`, | 698 | payload.endsWith("\n") ? payload : `${payload}\n`, |
| 699 | "utf8", | 699 | "utf8", |
apps/server/scripts/cursor-acp-model-mismatch-probe.ts+24-24| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off | 1 | // @effect-diagnostics nodeBuiltinImport:off |
| 2 | import { spawn, type ChildProcessWithoutNullStreams } from "node:child_process"; | 2 | import * as NodeChildProcess from "node:child_process"; |
| 3 | import process from "node:process"; | 3 | import * as NodeProcess from "node:process"; |
| 4 | import readline from "node:readline"; | 4 | import * as NodeReadline from "node:readline"; |
| 5 | import * as NodeTimers from "node:timers"; | 5 | import * as NodeTimers from "node:timers"; |
| 6 | import { resolveSpawnCommand } from "@t3tools/shared/shell"; | 6 | import { resolveSpawnCommand } from "@t3tools/shared/shell"; |
| 7 | import * as Effect from "effect/Effect"; | 7 | import * as Effect from "effect/Effect"; |
| ... | @@ -56,19 +56,19 @@ type PendingRequest = { | ... | @@ -56,19 +56,19 @@ type PendingRequest = { |
| 56 | reject: (error: Error) => void; | 56 | reject: (error: Error) => void; |
| 57 | }; | 57 | }; |
| 58 | 58 | ||
| 59 | const targetCwd = process.argv[2] ?? process.cwd(); | 59 | const targetCwd = NodeProcess.argv[2] ?? NodeProcess.cwd(); |
| 60 | const targetModel = process.argv[3] ?? "gpt-5.4"; | 60 | const targetModel = NodeProcess.argv[3] ?? "gpt-5.4"; |
| 61 | const promptText = process.argv[4] ?? "helo"; | 61 | const promptText = NodeProcess.argv[4] ?? "helo"; |
| 62 | const targetReasoning = process.env.CURSOR_REASONING ?? ""; | 62 | const targetReasoning = NodeProcess.env.CURSOR_REASONING ?? ""; |
| 63 | const targetContext = process.env.CURSOR_CONTEXT ?? ""; | 63 | const targetContext = NodeProcess.env.CURSOR_CONTEXT ?? ""; |
| 64 | const targetFast = process.env.CURSOR_FAST ?? ""; | 64 | const targetFast = NodeProcess.env.CURSOR_FAST ?? ""; |
| 65 | const agentBin = process.env.CURSOR_AGENT_BIN ?? "agent"; | 65 | const agentBin = NodeProcess.env.CURSOR_AGENT_BIN ?? "agent"; |
| 66 | const promptWaitMs = Number(process.env.CURSOR_PROMPT_WAIT_MS ?? "4000"); | 66 | const promptWaitMs = Number(NodeProcess.env.CURSOR_PROMPT_WAIT_MS ?? "4000"); |
| 67 | const requestTimeoutMs = Number(process.env.CURSOR_REQUEST_TIMEOUT_MS ?? "20000"); | 67 | const requestTimeoutMs = Number(NodeProcess.env.CURSOR_REQUEST_TIMEOUT_MS ?? "20000"); |
| 68 | 68 | ||
| 69 | function logSection(title: string, value: unknown) { | 69 | function logSection(title: string, value: unknown) { |
| 70 | process.stdout.write(`\n=== ${title} ===\n`); | 70 | NodeProcess.stdout.write(`\n=== ${title} ===\n`); |
| 71 | process.stdout.write(`${JSON.stringify(value, null, 2)}\n`); | 71 | NodeProcess.stdout.write(`${JSON.stringify(value, null, 2)}\n`); |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | function fail(message: string): never { | 74 | function fail(message: string): never { |
| ... | @@ -124,18 +124,18 @@ function sleep(ms: number) { | ... | @@ -124,18 +124,18 @@ function sleep(ms: number) { |
| 124 | } | 124 | } |
| 125 | 125 | ||
| 126 | class JsonRpcChild { | 126 | class JsonRpcChild { |
| 127 | readonly child: ChildProcessWithoutNullStreams; | 127 | readonly child: NodeChildProcess.ChildProcessWithoutNullStreams; |
| 128 | readonly pending = new Map<JsonRpcId, PendingRequest>(); | 128 | readonly pending = new Map<JsonRpcId, PendingRequest>(); |
| 129 | nextId = 1; | 129 | nextId = 1; |
| 130 | closed = false; | 130 | closed = false; |
| 131 | 131 | ||
| 132 | constructor(bin: string, args: string[], cwd: string) { | 132 | constructor(bin: string, args: string[], cwd: string) { |
| 133 | const spawnCommand = Effect.runSync(resolveSpawnCommand(bin, args)); | 133 | const spawnCommand = Effect.runSync(resolveSpawnCommand(bin, args)); |
| 134 | this.child = spawn(spawnCommand.command, spawnCommand.args, { | 134 | this.child = NodeChildProcess.spawn(spawnCommand.command, spawnCommand.args, { |
| 135 | cwd, | 135 | cwd, |
| 136 | shell: spawnCommand.shell, | 136 | shell: spawnCommand.shell, |
| 137 | stdio: ["pipe", "pipe", "pipe"], | 137 | stdio: ["pipe", "pipe", "pipe"], |
| 138 | env: process.env, | 138 | env: NodeProcess.env, |
| 139 | }); | 139 | }); |
| 140 | 140 | ||
| 141 | this.child.on("exit", (code, signal) => { | 141 | this.child.on("exit", (code, signal) => { |
| ... | @@ -155,14 +155,14 @@ class JsonRpcChild { | ... | @@ -155,14 +155,14 @@ class JsonRpcChild { |
| 155 | this.pending.clear(); | 155 | this.pending.clear(); |
| 156 | }); | 156 | }); |
| 157 | 157 | ||
| 158 | const stdout = readline.createInterface({ input: this.child.stdout }); | 158 | const stdout = NodeReadline.createInterface({ input: this.child.stdout }); |
| 159 | stdout.on("line", (line) => { | 159 | stdout.on("line", (line) => { |
| 160 | void this.handleStdoutLine(line); | 160 | void this.handleStdoutLine(line); |
| 161 | }); | 161 | }); |
| 162 | 162 | ||
| 163 | const stderr = readline.createInterface({ input: this.child.stderr }); | 163 | const stderr = NodeReadline.createInterface({ input: this.child.stderr }); |
| 164 | stderr.on("line", (line) => { | 164 | stderr.on("line", (line) => { |
| 165 | process.stdout.write(`[stderr] ${line}\n`); | 165 | NodeProcess.stdout.write(`[stderr] ${line}\n`); |
| 166 | }); | 166 | }); |
| 167 | } | 167 | } |
| 168 | 168 | ||
| ... | @@ -175,7 +175,7 @@ class JsonRpcChild { | ... | @@ -175,7 +175,7 @@ class JsonRpcChild { |
| 175 | headers: [], | 175 | headers: [], |
| 176 | ...message, | 176 | ...message, |
| 177 | }); | 177 | }); |
| 178 | process.stdout.write(`>>> ${payload}\n`); | 178 | NodeProcess.stdout.write(`>>> ${payload}\n`); |
| 179 | this.child.stdin.write(`${payload}\n`); | 179 | this.child.stdin.write(`${payload}\n`); |
| 180 | } | 180 | } |
| 181 | 181 | ||
| ... | @@ -240,13 +240,13 @@ class JsonRpcChild { | ... | @@ -240,13 +240,13 @@ class JsonRpcChild { |
| 240 | return; | 240 | return; |
| 241 | } | 241 | } |
| 242 | 242 | ||
| 243 | process.stdout.write(`<<< ${line}\n`); | 243 | NodeProcess.stdout.write(`<<< ${line}\n`); |
| 244 | 244 | ||
| 245 | let message: JsonRpcMessage; | 245 | let message: JsonRpcMessage; |
| 246 | try { | 246 | try { |
| 247 | message = JSON.parse(line) as JsonRpcMessage; | 247 | message = JSON.parse(line) as JsonRpcMessage; |
| 248 | } catch (error) { | 248 | } catch (error) { |
| 249 | process.stdout.write(`[parse-error] ${(error as Error).message}\n`); | 249 | NodeProcess.stdout.write(`[parse-error] ${(error as Error).message}\n`); |
| 250 | return; | 250 | return; |
| 251 | } | 251 | } |
| 252 | 252 | ||
| ... | @@ -435,7 +435,7 @@ async function main() { | ... | @@ -435,7 +435,7 @@ async function main() { |
| 435 | } | 435 | } |
| 436 | 436 | ||
| 437 | void main().catch((error: unknown) => { | 437 | void main().catch((error: unknown) => { |
| 438 | process.stderr.write( | 438 | NodeProcess.stderr.write( |
| 439 | `${error instanceof Error ? (error.stack ?? error.message) : String(error)}\n`, | 439 | `${error instanceof Error ? (error.stack ?? error.message) : String(error)}\n`, |
| 440 | ); | 440 | ); |
| 441 | process.exitCode = 1; | 441 | process.exitCode = 1; |
apps/server/src/attachmentPaths.ts+1-1| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off | 1 | // @effect-diagnostics nodeBuiltinImport:off |
| 2 | import NodePath from "node:path"; | 2 | import * as NodePath from "node:path"; |
| 3 | 3 | ||
| 4 | export function normalizeAttachmentRelativePath(rawRelativePath: string): string | null { | 4 | export function normalizeAttachmentRelativePath(rawRelativePath: string): string | null { |
| 5 | const normalized = NodePath.normalize(rawRelativePath).replace(/^[/\\]+/, ""); | 5 | const normalized = NodePath.normalize(rawRelativePath).replace(/^[/\\]+/, ""); |
apps/server/src/attachmentStore.test.ts+13-9| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off | 1 | // @effect-diagnostics nodeBuiltinImport:off |
| 2 | import fs from "node:fs"; | 2 | import * as NodeFS from "node:fs"; |
| 3 | import os from "node:os"; | 3 | import * as NodeOS from "node:os"; |
| 4 | import path from "node:path"; | 4 | import * as NodePath from "node:path"; |
| 5 | 5 | ||
| 6 | import { describe, expect, it } from "vite-plus/test"; | 6 | import { describe, expect, it } from "vite-plus/test"; |
| 7 | 7 | ||
| ... | @@ -45,11 +45,13 @@ describe("attachmentStore", () => { | ... | @@ -45,11 +45,13 @@ describe("attachmentStore", () => { |
| 45 | }); | 45 | }); |
| 46 | 46 | ||
| 47 | it("resolves attachment path by id using the extension that exists on disk", () => { | 47 | it("resolves attachment path by id using the extension that exists on disk", () => { |
| 48 | const attachmentsDir = fs.mkdtempSync(path.join(os.tmpdir(), "t3code-attachment-store-")); | 48 | const attachmentsDir = NodeFS.mkdtempSync( |
| 49 | NodePath.join(NodeOS.tmpdir(), "t3code-attachment-store-"), | ||
| 50 | ); | ||
| 49 | try { | 51 | try { |
| 50 | const attachmentId = "thread-1-attachment"; | 52 | const attachmentId = "thread-1-attachment"; |
| 51 | const pngPath = path.join(attachmentsDir, `${attachmentId}.png`); | 53 | const pngPath = NodePath.join(attachmentsDir, `${attachmentId}.png`); |
| 52 | fs.writeFileSync(pngPath, Buffer.from("hello")); | 54 | NodeFS.writeFileSync(pngPath, Buffer.from("hello")); |
| 53 | 55 | ||
| 54 | const resolved = resolveAttachmentPathById({ | 56 | const resolved = resolveAttachmentPathById({ |
| 55 | attachmentsDir, | 57 | attachmentsDir, |
| ... | @@ -57,12 +59,14 @@ describe("attachmentStore", () => { | ... | @@ -57,12 +59,14 @@ describe("attachmentStore", () => { |
| 57 | }); | 59 | }); |
| 58 | expect(resolved).toBe(pngPath); | 60 | expect(resolved).toBe(pngPath); |
| 59 | } finally { | 61 | } finally { |
| 60 | fs.rmSync(attachmentsDir, { recursive: true, force: true }); | 62 | NodeFS.rmSync(attachmentsDir, { recursive: true, force: true }); |
| 61 | } | 63 | } |
| 62 | }); | 64 | }); |
| 63 | 65 | ||
| 64 | it("returns null when no attachment file exists for the id", () => { | 66 | it("returns null when no attachment file exists for the id", () => { |
| 65 | const attachmentsDir = fs.mkdtempSync(path.join(os.tmpdir(), "t3code-attachment-store-")); | 67 | const attachmentsDir = NodeFS.mkdtempSync( |
| 68 | NodePath.join(NodeOS.tmpdir(), "t3code-attachment-store-"), | ||
| 69 | ); | ||
| 66 | try { | 70 | try { |
| 67 | const resolved = resolveAttachmentPathById({ | 71 | const resolved = resolveAttachmentPathById({ |
| 68 | attachmentsDir, | 72 | attachmentsDir, |
| ... | @@ -70,7 +74,7 @@ describe("attachmentStore", () => { | ... | @@ -70,7 +74,7 @@ describe("attachmentStore", () => { |
| 70 | }); | 74 | }); |
| 71 | expect(resolved).toBeNull(); | 75 | expect(resolved).toBeNull(); |
| 72 | } finally { | 76 | } finally { |
| 73 | fs.rmSync(attachmentsDir, { recursive: true, force: true }); | 77 | NodeFS.rmSync(attachmentsDir, { recursive: true, force: true }); |
| 74 | } | 78 | } |
| 75 | }); | 79 | }); |
| 76 | }); | 80 | }); |
apps/server/src/attachmentStore.ts+4-4| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off | 1 | // @effect-diagnostics nodeBuiltinImport:off |
| 2 | import { randomUUID } from "node:crypto"; | 2 | import * as NodeCrypto from "node:crypto"; |
| 3 | import { existsSync } from "node:fs"; | 3 | import * as NodeFS from "node:fs"; |
| 4 | 4 | ||
| 5 | import type { ChatAttachment } from "@t3tools/contracts"; | 5 | import type { ChatAttachment } from "@t3tools/contracts"; |
| 6 | 6 | ||
| ... | @@ -39,7 +39,7 @@ export function createAttachmentId(threadId: string): string | null { | ... | @@ -39,7 +39,7 @@ export function createAttachmentId(threadId: string): string | null { |
| 39 | if (!threadSegment) { | 39 | if (!threadSegment) { |
| 40 | return null; | 40 | return null; |
| 41 | } | 41 | } |
| 42 | return `${threadSegment}-${randomUUID()}`; | 42 | return `${threadSegment}-${NodeCrypto.randomUUID()}`; |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | export function parseThreadSegmentFromAttachmentId(attachmentId: string): string | null { | 45 | export function parseThreadSegmentFromAttachmentId(attachmentId: string): string | null { |
| ... | @@ -89,7 +89,7 @@ export function resolveAttachmentPathById(input: { | ... | @@ -89,7 +89,7 @@ export function resolveAttachmentPathById(input: { |
| 89 | attachmentsDir: input.attachmentsDir, | 89 | attachmentsDir: input.attachmentsDir, |
| 90 | relativePath: `${normalizedId}${extension}`, | 90 | relativePath: `${normalizedId}${extension}`, |
| 91 | }); | 91 | }); |
| 92 | if (maybePath && existsSync(maybePath)) { | 92 | if (maybePath && NodeFS.existsSync(maybePath)) { |
| 93 | return maybePath; | 93 | return maybePath; |
| 94 | } | 94 | } |
| 95 | } | 95 | } |
apps/server/src/auth/utils.ts+3-3| ... | @@ -4,7 +4,7 @@ import type { | ... | @@ -4,7 +4,7 @@ import type { |
| 4 | AuthClientPresentationMetadata, | 4 | AuthClientPresentationMetadata, |
| 5 | } from "@t3tools/contracts"; | 5 | } from "@t3tools/contracts"; |
| 6 | import type * as HttpServerRequest from "effect/unstable/http/HttpServerRequest"; | 6 | import type * as HttpServerRequest from "effect/unstable/http/HttpServerRequest"; |
| 7 | import * as Crypto from "node:crypto"; | 7 | import * as NodeCrypto from "node:crypto"; |
| 8 | import * as Encoding from "effect/Encoding"; | 8 | import * as Encoding from "effect/Encoding"; |
| 9 | import * as Result from "effect/Result"; | 9 | import * as Result from "effect/Result"; |
| 10 | 10 | ||
| ... | @@ -32,7 +32,7 @@ export function base64UrlDecodeUtf8(input: string): string { | ... | @@ -32,7 +32,7 @@ export function base64UrlDecodeUtf8(input: string): string { |
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | export function signPayload(payload: string, secret: Uint8Array): string { | 34 | export function signPayload(payload: string, secret: Uint8Array): string { |
| 35 | return Crypto.createHmac("sha256", Buffer.from(secret)).update(payload).digest("base64url"); | 35 | return NodeCrypto.createHmac("sha256", Buffer.from(secret)).update(payload).digest("base64url"); |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | export function timingSafeEqualBase64Url(left: string, right: string): boolean { | 38 | export function timingSafeEqualBase64Url(left: string, right: string): boolean { |
| ... | @@ -41,7 +41,7 @@ export function timingSafeEqualBase64Url(left: string, right: string): boolean { | ... | @@ -41,7 +41,7 @@ export function timingSafeEqualBase64Url(left: string, right: string): boolean { |
| 41 | if (leftBuffer.length !== rightBuffer.length) { | 41 | if (leftBuffer.length !== rightBuffer.length) { |
| 42 | return false; | 42 | return false; |
| 43 | } | 43 | } |
| 44 | return Crypto.timingSafeEqual(leftBuffer, rightBuffer); | 44 | return NodeCrypto.timingSafeEqual(leftBuffer, rightBuffer); |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | function normalizeNonEmptyString(value: string | null | undefined): string | undefined { | 47 | function normalizeNonEmptyString(value: string | null | undefined): string | undefined { |
apps/server/src/bin.test.ts+47-25| ... | @@ -1,8 +1,8 @@ | ... | @@ -1,8 +1,8 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off - CLI integration exercises Node HTTP and filesystem boundaries. | 1 | // @effect-diagnostics nodeBuiltinImport:off - CLI integration exercises Node HTTP and filesystem boundaries. |
| 2 | import { createServer } from "node:http"; | 2 | import * as NodeHttp from "node:http"; |
| 3 | import { existsSync, mkdirSync, mkdtempSync, writeFileSync } from "node:fs"; | 3 | import * as NodeFS from "node:fs"; |
| 4 | import { tmpdir } from "node:os"; | 4 | import * as NodeOS from "node:os"; |
| 5 | import { join } from "node:path"; | 5 | import * as NodePath from "node:path"; |
| 6 | 6 | ||
| 7 | import * as NodeHttpServer from "@effect/platform-node/NodeHttpServer"; | 7 | import * as NodeHttpServer from "@effect/platform-node/NodeHttpServer"; |
| 8 | import * as NodeServices from "@effect/platform-node/NodeServices"; | 8 | import * as NodeServices from "@effect/platform-node/NodeServices"; |
| ... | @@ -124,7 +124,7 @@ const withLiveProjectCliServer = <A, E, R>(baseDir: string, run: () => Effect.Ef | ... | @@ -124,7 +124,7 @@ const withLiveProjectCliServer = <A, E, R>(baseDir: string, run: () => Effect.Ef |
| 124 | ), | 124 | ), |
| 125 | Layer.provideMerge(makeProjectPersistenceLayer(config)), | 125 | Layer.provideMerge(makeProjectPersistenceLayer(config)), |
| 126 | Layer.provideMerge( | 126 | Layer.provideMerge( |
| 127 | NodeHttpServer.layer(createServer, { | 127 | NodeHttpServer.layer(NodeHttp.createServer, { |
| 128 | host: "127.0.0.1", | 128 | host: "127.0.0.1", |
| 129 | port: 0, | 129 | port: 0, |
| 130 | }), | 130 | }), |
| ... | @@ -197,7 +197,9 @@ it.layer(NodeServices.layer)("bin cli parsing", (it) => { | ... | @@ -197,7 +197,9 @@ it.layer(NodeServices.layer)("bin cli parsing", (it) => { |
| 197 | 197 | ||
| 198 | it.effect("reports fresh headless connect state without requiring local configuration", () => | 198 | it.effect("reports fresh headless connect state without requiring local configuration", () => |
| 199 | Effect.gen(function* () { | 199 | Effect.gen(function* () { |
| 200 | const baseDir = mkdtempSync(join(tmpdir(), "t3-cli-cloud-status-test-")); | 200 | const baseDir = NodeFS.mkdtempSync( |
| 201 | NodePath.join(NodeOS.tmpdir(), "t3-cli-cloud-status-test-"), | ||
| 202 | ); | ||
| 201 | const { output } = yield* captureStdout( | 203 | const { output } = yield* captureStdout( |
| 202 | runConnectCli(["connect", "status", "--base-dir", baseDir, "--json"]), | 204 | runConnectCli(["connect", "status", "--base-dir", baseDir, "--json"]), |
| 203 | ); | 205 | ); |
| ... | @@ -220,7 +222,9 @@ it.layer(NodeServices.layer)("bin cli parsing", (it) => { | ... | @@ -220,7 +222,9 @@ it.layer(NodeServices.layer)("bin cli parsing", (it) => { |
| 220 | 222 | ||
| 221 | it.effect("reports actionable human-readable headless connect state", () => | 223 | it.effect("reports actionable human-readable headless connect state", () => |
| 222 | Effect.gen(function* () { | 224 | Effect.gen(function* () { |
| 223 | const baseDir = mkdtempSync(join(tmpdir(), "t3-cli-cloud-status-human-test-")); | 225 | const baseDir = NodeFS.mkdtempSync( |
| 226 | NodePath.join(NodeOS.tmpdir(), "t3-cli-cloud-status-human-test-"), | ||
| 227 | ); | ||
| 224 | const { output } = yield* captureStdout( | 228 | const { output } = yield* captureStdout( |
| 225 | runConnectCli(["connect", "status", "--base-dir", baseDir]), | 229 | runConnectCli(["connect", "status", "--base-dir", baseDir]), |
| 226 | ); | 230 | ); |
| ... | @@ -234,11 +238,13 @@ it.layer(NodeServices.layer)("bin cli parsing", (it) => { | ... | @@ -234,11 +238,13 @@ it.layer(NodeServices.layer)("bin cli parsing", (it) => { |
| 234 | 238 | ||
| 235 | it.effect("logs in to headless connect without enabling access", () => | 239 | it.effect("logs in to headless connect without enabling access", () => |
| 236 | Effect.gen(function* () { | 240 | Effect.gen(function* () { |
| 237 | const baseDir = mkdtempSync(join(tmpdir(), "t3-cli-cloud-login-test-")); | 241 | const baseDir = NodeFS.mkdtempSync( |
| 242 | NodePath.join(NodeOS.tmpdir(), "t3-cli-cloud-login-test-"), | ||
| 243 | ); | ||
| 238 | const { secretsDir } = yield* ServerConfig.deriveServerPaths(baseDir, undefined); | 244 | const { secretsDir } = yield* ServerConfig.deriveServerPaths(baseDir, undefined); |
| 239 | mkdirSync(secretsDir, { recursive: true }); | 245 | NodeFS.mkdirSync(secretsDir, { recursive: true }); |
| 240 | writeFileSync( | 246 | NodeFS.writeFileSync( |
| 241 | join(secretsDir, "cloud-cli-oauth-token.bin"), | 247 | NodePath.join(secretsDir, "cloud-cli-oauth-token.bin"), |
| 242 | // @effect-diagnostics-next-line preferSchemaOverJson:off - Test fixture matches the persisted CLI token representation. | 248 | // @effect-diagnostics-next-line preferSchemaOverJson:off - Test fixture matches the persisted CLI token representation. |
| 243 | JSON.stringify({ | 249 | JSON.stringify({ |
| 244 | accessToken: "access-token", | 250 | accessToken: "access-token", |
| ... | @@ -267,7 +273,9 @@ it.layer(NodeServices.layer)("bin cli parsing", (it) => { | ... | @@ -267,7 +273,9 @@ it.layer(NodeServices.layer)("bin cli parsing", (it) => { |
| 267 | 273 | ||
| 268 | it.effect("disables headless connect without a running server", () => | 274 | it.effect("disables headless connect without a running server", () => |
| 269 | Effect.gen(function* () { | 275 | Effect.gen(function* () { |
| 270 | const baseDir = mkdtempSync(join(tmpdir(), "t3-cli-cloud-unlink-test-")); | 276 | const baseDir = NodeFS.mkdtempSync( |
| 277 | NodePath.join(NodeOS.tmpdir(), "t3-cli-cloud-unlink-test-"), | ||
| 278 | ); | ||
| 271 | const { output } = yield* captureStdout( | 279 | const { output } = yield* captureStdout( |
| 272 | runConnectCli(["connect", "unlink", "--base-dir", baseDir]), | 280 | runConnectCli(["connect", "unlink", "--base-dir", baseDir]), |
| 273 | ); | 281 | ); |
| ... | @@ -278,24 +286,28 @@ it.layer(NodeServices.layer)("bin cli parsing", (it) => { | ... | @@ -278,24 +286,28 @@ it.layer(NodeServices.layer)("bin cli parsing", (it) => { |
| 278 | 286 | ||
| 279 | it.effect("logs out of headless connect and removes the stored CLI authorization", () => | 287 | it.effect("logs out of headless connect and removes the stored CLI authorization", () => |
| 280 | Effect.gen(function* () { | 288 | Effect.gen(function* () { |
| 281 | const baseDir = mkdtempSync(join(tmpdir(), "t3-cli-cloud-logout-test-")); | 289 | const baseDir = NodeFS.mkdtempSync( |
| 290 | NodePath.join(NodeOS.tmpdir(), "t3-cli-cloud-logout-test-"), | ||
| 291 | ); | ||
| 282 | const { secretsDir } = yield* ServerConfig.deriveServerPaths(baseDir, undefined); | 292 | const { secretsDir } = yield* ServerConfig.deriveServerPaths(baseDir, undefined); |
| 283 | const tokenPath = join(secretsDir, "cloud-cli-oauth-token.bin"); | 293 | const tokenPath = NodePath.join(secretsDir, "cloud-cli-oauth-token.bin"); |
| 284 | mkdirSync(secretsDir, { recursive: true }); | 294 | NodeFS.mkdirSync(secretsDir, { recursive: true }); |
| 285 | writeFileSync(tokenPath, "invalid persisted token"); | 295 | NodeFS.writeFileSync(tokenPath, "invalid persisted token"); |
| 286 | 296 | ||
| 287 | const { output } = yield* captureStdout( | 297 | const { output } = yield* captureStdout( |
| 288 | runConnectCli(["connect", "logout", "--base-dir", baseDir]), | 298 | runConnectCli(["connect", "logout", "--base-dir", baseDir]), |
| 289 | ); | 299 | ); |
| 290 | 300 | ||
| 291 | assert.equal(output, "Signed out of T3 Connect locally."); | 301 | assert.equal(output, "Signed out of T3 Connect locally."); |
| 292 | assert.isFalse(existsSync(tokenPath)); | 302 | assert.isFalse(NodeFS.existsSync(tokenPath)); |
| 293 | }), | 303 | }), |
| 294 | ); | 304 | ); |
| 295 | 305 | ||
| 296 | it.effect("executes auth pairing subcommands and redacts secrets from list output", () => | 306 | it.effect("executes auth pairing subcommands and redacts secrets from list output", () => |
| 297 | Effect.gen(function* () { | 307 | Effect.gen(function* () { |
| 298 | const baseDir = mkdtempSync(join(tmpdir(), "t3-cli-auth-pairing-test-")); | 308 | const baseDir = NodeFS.mkdtempSync( |
| 309 | NodePath.join(NodeOS.tmpdir(), "t3-cli-auth-pairing-test-"), | ||
| 310 | ); | ||
| 299 | 311 | ||
| 300 | const createdOutput = yield* captureStdout( | 312 | const createdOutput = yield* captureStdout( |
| 301 | runCli(["auth", "pairing", "create", "--base-dir", baseDir, "--json"]), | 313 | runCli(["auth", "pairing", "create", "--base-dir", baseDir, "--json"]), |
| ... | @@ -325,7 +337,9 @@ it.layer(NodeServices.layer)("bin cli parsing", (it) => { | ... | @@ -325,7 +337,9 @@ it.layer(NodeServices.layer)("bin cli parsing", (it) => { |
| 325 | 337 | ||
| 326 | it.effect("executes auth session subcommands and redacts secrets from list output", () => | 338 | it.effect("executes auth session subcommands and redacts secrets from list output", () => |
| 327 | Effect.gen(function* () { | 339 | Effect.gen(function* () { |
| 328 | const baseDir = mkdtempSync(join(tmpdir(), "t3-cli-auth-session-test-")); | 340 | const baseDir = NodeFS.mkdtempSync( |
| 341 | NodePath.join(NodeOS.tmpdir(), "t3-cli-auth-session-test-"), | ||
| 342 | ); | ||
| 329 | 343 | ||
| 330 | const issuedOutput = yield* captureStdout( | 344 | const issuedOutput = yield* captureStdout( |
| 331 | runCli(["auth", "session", "issue", "--base-dir", baseDir, "--json"]), | 345 | runCli(["auth", "session", "issue", "--base-dir", baseDir, "--json"]), |
| ... | @@ -400,8 +414,12 @@ it.layer(NodeServices.layer)("bin cli parsing", (it) => { | ... | @@ -400,8 +414,12 @@ it.layer(NodeServices.layer)("bin cli parsing", (it) => { |
| 400 | 414 | ||
| 401 | it.effect("adds, renames, and removes projects offline through the orchestration engine", () => | 415 | it.effect("adds, renames, and removes projects offline through the orchestration engine", () => |
| 402 | Effect.gen(function* () { | 416 | Effect.gen(function* () { |
| 403 | const baseDir = mkdtempSync(join(tmpdir(), "t3-cli-projects-offline-test-")); | 417 | const baseDir = NodeFS.mkdtempSync( |
| 404 | const workspaceRoot = mkdtempSync(join(tmpdir(), "t3-cli-projects-workspace-")); | 418 | NodePath.join(NodeOS.tmpdir(), "t3-cli-projects-offline-test-"), |
| 419 | ); | ||
| 420 | const workspaceRoot = NodeFS.mkdtempSync( | ||
| 421 | NodePath.join(NodeOS.tmpdir(), "t3-cli-projects-workspace-"), | ||
| 422 | ); | ||
| 405 | 423 | ||
| 406 | yield* runCliWithRuntime([ | 424 | yield* runCliWithRuntime([ |
| 407 | "project", | 425 | "project", |
| ... | @@ -444,8 +462,12 @@ it.layer(NodeServices.layer)("bin cli parsing", (it) => { | ... | @@ -444,8 +462,12 @@ it.layer(NodeServices.layer)("bin cli parsing", (it) => { |
| 444 | 462 | ||
| 445 | it.effect("routes project commands through a running server when runtime state is present", () => | 463 | it.effect("routes project commands through a running server when runtime state is present", () => |
| 446 | Effect.gen(function* () { | 464 | Effect.gen(function* () { |
| 447 | const baseDir = mkdtempSync(join(tmpdir(), "t3-cli-projects-live-test-")); | 465 | const baseDir = NodeFS.mkdtempSync( |
| 448 | const workspaceRoot = mkdtempSync(join(tmpdir(), "t3-cli-projects-live-workspace-")); | 466 | NodePath.join(NodeOS.tmpdir(), "t3-cli-projects-live-test-"), |
| 467 | ); | ||
| 468 | const workspaceRoot = NodeFS.mkdtempSync( | ||
| 469 | NodePath.join(NodeOS.tmpdir(), "t3-cli-projects-live-workspace-"), | ||
| 470 | ); | ||
| 449 | 471 | ||
| 450 | yield* withLiveProjectCliServer(baseDir, () => | 472 | yield* withLiveProjectCliServer(baseDir, () => |
| 451 | Effect.gen(function* () { | 473 | Effect.gen(function* () { |
| ... | @@ -472,8 +494,8 @@ it.layer(NodeServices.layer)("bin cli parsing", (it) => { | ... | @@ -472,8 +494,8 @@ it.layer(NodeServices.layer)("bin cli parsing", (it) => { |
| 472 | 494 | ||
| 473 | it.effect("rejects dev-url on project commands", () => | 495 | it.effect("rejects dev-url on project commands", () => |
| 474 | Effect.gen(function* () { | 496 | Effect.gen(function* () { |
| 475 | const workspaceRoot = mkdtempSync( | 497 | const workspaceRoot = NodeFS.mkdtempSync( |
| 476 | join(tmpdir(), "t3-cli-projects-unknown-option-workspace-"), | 498 | NodePath.join(NodeOS.tmpdir(), "t3-cli-projects-unknown-option-workspace-"), |
| 477 | ); | 499 | ); |
| 478 | const error = yield* runCliWithRuntime([ | 500 | const error = yield* runCliWithRuntime([ |
| 479 | "project", | 501 | "project", |
apps/server/src/bootstrap.test.ts+13-13| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off | 1 | // @effect-diagnostics nodeBuiltinImport:off |
| 2 | import * as NFS from "node:fs"; | 2 | import * as NodeFS from "node:fs"; |
| 3 | import * as path from "node:path"; | 3 | import * as NodePath from "node:path"; |
| 4 | import { execFileSync, spawn } from "node:child_process"; | 4 | import * as NodeChildProcess from "node:child_process"; |
| 5 | import * as NodeServices from "@effect/platform-node/NodeServices"; | 5 | import * as NodeServices from "@effect/platform-node/NodeServices"; |
| 6 | import { it } from "@effect/vitest"; | 6 | import { it } from "@effect/vitest"; |
| 7 | import * as FileSystem from "effect/FileSystem"; | 7 | import * as FileSystem from "effect/FileSystem"; |
| ... | @@ -53,8 +53,8 @@ it.layer(NodeServices.layer)("readBootstrapEnvelope", (it) => { | ... | @@ -53,8 +53,8 @@ it.layer(NodeServices.layer)("readBootstrapEnvelope", (it) => { |
| 53 | ); | 53 | ); |
| 54 | 54 | ||
| 55 | const fd = yield* Effect.acquireRelease( | 55 | const fd = yield* Effect.acquireRelease( |
| 56 | Effect.sync(() => NFS.openSync(filePath, "r")), | 56 | Effect.sync(() => NodeFS.openSync(filePath, "r")), |
| 57 | (fd) => Effect.sync(() => NFS.closeSync(fd)), | 57 | (fd) => Effect.sync(() => NodeFS.closeSync(fd)), |
| 58 | ); | 58 | ); |
| 59 | 59 | ||
| 60 | const payload = yield* readBootstrapEnvelope(TestEnvelopeSchema, fd, { timeoutMs: 100 }); | 60 | const payload = yield* readBootstrapEnvelope(TestEnvelopeSchema, fd, { timeoutMs: 100 }); |
| ... | @@ -78,7 +78,7 @@ it.layer(NodeServices.layer)("readBootstrapEnvelope", (it) => { | ... | @@ -78,7 +78,7 @@ it.layer(NodeServices.layer)("readBootstrapEnvelope", (it) => { |
| 78 | // so the stream owns the fd lifecycle and closes it asynchronously on end. | 78 | // so the stream owns the fd lifecycle and closes it asynchronously on end. |
| 79 | // Attempting to also close it synchronously in a finalizer races with the | 79 | // Attempting to also close it synchronously in a finalizer races with the |
| 80 | // stream's async close and produces an uncaught EBADF. | 80 | // stream's async close and produces an uncaught EBADF. |
| 81 | const fd = NFS.openSync(filePath, "r"); | 81 | const fd = NodeFS.openSync(filePath, "r"); |
| 82 | 82 | ||
| 83 | openSyncInterceptor.failPath = `/proc/self/fd/${fd}`; | 83 | openSyncInterceptor.failPath = `/proc/self/fd/${fd}`; |
| 84 | try { | 84 | try { |
| ... | @@ -96,8 +96,8 @@ it.layer(NodeServices.layer)("readBootstrapEnvelope", (it) => { | ... | @@ -96,8 +96,8 @@ it.layer(NodeServices.layer)("readBootstrapEnvelope", (it) => { |
| 96 | 96 | ||
| 97 | it.effect("returns none when the fd is unavailable", () => | 97 | it.effect("returns none when the fd is unavailable", () => |
| 98 | Effect.gen(function* () { | 98 | Effect.gen(function* () { |
| 99 | const fd = NFS.openSync("/dev/null", "r"); | 99 | const fd = NodeFS.openSync("/dev/null", "r"); |
| 100 | NFS.closeSync(fd); | 100 | NodeFS.closeSync(fd); |
| 101 | 101 | ||
| 102 | const payload = yield* readBootstrapEnvelope(TestEnvelopeSchema, fd, { timeoutMs: 100 }); | 102 | const payload = yield* readBootstrapEnvelope(TestEnvelopeSchema, fd, { timeoutMs: 100 }); |
| 103 | assertNone(payload); | 103 | assertNone(payload); |
| ... | @@ -108,13 +108,13 @@ it.layer(NodeServices.layer)("readBootstrapEnvelope", (it) => { | ... | @@ -108,13 +108,13 @@ it.layer(NodeServices.layer)("readBootstrapEnvelope", (it) => { |
| 108 | Effect.gen(function* () { | 108 | Effect.gen(function* () { |
| 109 | const fs = yield* FileSystem.FileSystem; | 109 | const fs = yield* FileSystem.FileSystem; |
| 110 | const tempDir = yield* fs.makeTempDirectoryScoped({ prefix: "t3-bootstrap-" }); | 110 | const tempDir = yield* fs.makeTempDirectoryScoped({ prefix: "t3-bootstrap-" }); |
| 111 | const fifoPath = path.join(tempDir, "bootstrap.pipe"); | 111 | const fifoPath = NodePath.join(tempDir, "bootstrap.pipe"); |
| 112 | 112 | ||
| 113 | yield* Effect.sync(() => execFileSync("mkfifo", [fifoPath])); | 113 | yield* Effect.sync(() => NodeChildProcess.execFileSync("mkfifo", [fifoPath])); |
| 114 | 114 | ||
| 115 | const _writer = yield* Effect.acquireRelease( | 115 | const _writer = yield* Effect.acquireRelease( |
| 116 | Effect.sync(() => | 116 | Effect.sync(() => |
| 117 | spawn("sh", ["-c", 'exec 3>"$1"; sleep 60', "sh", fifoPath], { | 117 | NodeChildProcess.spawn("sh", ["-c", 'exec 3>"$1"; sleep 60', "sh", fifoPath], { |
| 118 | stdio: ["ignore", "ignore", "ignore"], | 118 | stdio: ["ignore", "ignore", "ignore"], |
| 119 | }), | 119 | }), |
| 120 | ), | 120 | ), |
| ... | @@ -125,8 +125,8 @@ it.layer(NodeServices.layer)("readBootstrapEnvelope", (it) => { | ... | @@ -125,8 +125,8 @@ it.layer(NodeServices.layer)("readBootstrapEnvelope", (it) => { |
| 125 | ); | 125 | ); |
| 126 | 126 | ||
| 127 | const fd = yield* Effect.acquireRelease( | 127 | const fd = yield* Effect.acquireRelease( |
| 128 | Effect.sync(() => NFS.openSync(fifoPath, "r")), | 128 | Effect.sync(() => NodeFS.openSync(fifoPath, "r")), |
| 129 | (fd) => Effect.sync(() => NFS.closeSync(fd)), | 129 | (fd) => Effect.sync(() => NodeFS.closeSync(fd)), |
| 130 | ); | 130 | ); |
| 131 | 131 | ||
| 132 | const fiber = yield* readBootstrapEnvelope(TestEnvelopeSchema, fd, { | 132 | const fiber = yield* readBootstrapEnvelope(TestEnvelopeSchema, fd, { |
apps/server/src/bootstrap.ts+13-13| ... | @@ -1,8 +1,8 @@ | ... | @@ -1,8 +1,8 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off | 1 | // @effect-diagnostics nodeBuiltinImport:off |
| 2 | import * as NFS from "node:fs"; | 2 | import * as NodeFS from "node:fs"; |
| 3 | import * as Net from "node:net"; | 3 | import * as NodeNet from "node:net"; |
| 4 | import * as readline from "node:readline"; | 4 | import * as NodeReadline from "node:readline"; |
| 5 | import type { Readable } from "node:stream"; | 5 | import type * as NodeStream from "node:stream"; |
| 6 | 6 | ||
| 7 | import * as Data from "effect/Data"; | 7 | import * as Data from "effect/Data"; |
| 8 | import * as Effect from "effect/Effect"; | 8 | import * as Effect from "effect/Effect"; |
| ... | @@ -33,7 +33,7 @@ export const readBootstrapEnvelope = Effect.fn("readBootstrapEnvelope")(function | ... | @@ -33,7 +33,7 @@ export const readBootstrapEnvelope = Effect.fn("readBootstrapEnvelope")(function |
| 33 | const timeoutMs = options?.timeoutMs ?? 1000; | 33 | const timeoutMs = options?.timeoutMs ?? 1000; |
| 34 | 34 | ||
| 35 | return yield* Effect.callback<Option.Option<A>, BootstrapError>((resume) => { | 35 | return yield* Effect.callback<Option.Option<A>, BootstrapError>((resume) => { |
| 36 | const input = readline.createInterface({ | 36 | const input = NodeReadline.createInterface({ |
| 37 | input: stream, | 37 | input: stream, |
| 38 | crlfDelay: Infinity, | 38 | crlfDelay: Infinity, |
| 39 | }); | 39 | }); |
| ... | @@ -96,7 +96,7 @@ const isUnavailableBootstrapFdError = Predicate.compose( | ... | @@ -96,7 +96,7 @@ const isUnavailableBootstrapFdError = Predicate.compose( |
| 96 | 96 | ||
| 97 | const isFdReady = (fd: number) => | 97 | const isFdReady = (fd: number) => |
| 98 | Effect.try({ | 98 | Effect.try({ |
| 99 | try: () => NFS.fstatSync(fd), | 99 | try: () => NodeFS.fstatSync(fd), |
| 100 | catch: (error) => | 100 | catch: (error) => |
| 101 | new BootstrapError({ | 101 | new BootstrapError({ |
| 102 | message: "Failed to stat bootstrap fd.", | 102 | message: "Failed to stat bootstrap fd.", |
| ... | @@ -113,7 +113,7 @@ const isFdReady = (fd: number) => | ... | @@ -113,7 +113,7 @@ const isFdReady = (fd: number) => |
| 113 | const makeBootstrapInputStream = (fd: number) => | 113 | const makeBootstrapInputStream = (fd: number) => |
| 114 | Effect.gen(function* () { | 114 | Effect.gen(function* () { |
| 115 | const platform = yield* HostProcessPlatform; | 115 | const platform = yield* HostProcessPlatform; |
| 116 | return yield* Effect.try<Readable, BootstrapError>({ | 116 | return yield* Effect.try<NodeStream.Readable, BootstrapError>({ |
| 117 | try: () => { | 117 | try: () => { |
| 118 | const fdPath = resolveFdPath(fd, platform); | 118 | const fdPath = resolveFdPath(fd, platform); |
| 119 | if (fdPath === undefined) { | 119 | if (fdPath === undefined) { |
| ... | @@ -122,8 +122,8 @@ const makeBootstrapInputStream = (fd: number) => | ... | @@ -122,8 +122,8 @@ const makeBootstrapInputStream = (fd: number) => |
| 122 | 122 | ||
| 123 | let streamFd: number | undefined; | 123 | let streamFd: number | undefined; |
| 124 | try { | 124 | try { |
| 125 | streamFd = NFS.openSync(fdPath, "r"); | 125 | streamFd = NodeFS.openSync(fdPath, "r"); |
| 126 | return NFS.createReadStream("", { | 126 | return NodeFS.createReadStream("", { |
| 127 | fd: streamFd, | 127 | fd: streamFd, |
| 128 | encoding: "utf8", | 128 | encoding: "utf8", |
| 129 | autoClose: true, | 129 | autoClose: true, |
| ... | @@ -131,7 +131,7 @@ const makeBootstrapInputStream = (fd: number) => | ... | @@ -131,7 +131,7 @@ const makeBootstrapInputStream = (fd: number) => |
| 131 | } catch (error) { | 131 | } catch (error) { |
| 132 | if (isBootstrapFdPathDuplicationError(error)) { | 132 | if (isBootstrapFdPathDuplicationError(error)) { |
| 133 | if (streamFd !== undefined) { | 133 | if (streamFd !== undefined) { |
| 134 | NFS.closeSync(streamFd); | 134 | NodeFS.closeSync(streamFd); |
| 135 | } | 135 | } |
| 136 | return makeDirectBootstrapStream(fd); | 136 | return makeDirectBootstrapStream(fd); |
| 137 | } | 137 | } |
| ... | @@ -146,15 +146,15 @@ const makeBootstrapInputStream = (fd: number) => | ... | @@ -146,15 +146,15 @@ const makeBootstrapInputStream = (fd: number) => |
| 146 | }); | 146 | }); |
| 147 | }); | 147 | }); |
| 148 | 148 | ||
| 149 | const makeDirectBootstrapStream = (fd: number): Readable => { | 149 | const makeDirectBootstrapStream = (fd: number): NodeStream.Readable => { |
| 150 | try { | 150 | try { |
| 151 | return NFS.createReadStream("", { | 151 | return NodeFS.createReadStream("", { |
| 152 | fd, | 152 | fd, |
| 153 | encoding: "utf8", | 153 | encoding: "utf8", |
| 154 | autoClose: true, | 154 | autoClose: true, |
| 155 | }); | 155 | }); |
| 156 | } catch { | 156 | } catch { |
| 157 | const stream = new Net.Socket({ | 157 | const stream = new NodeNet.Socket({ |
| 158 | fd, | 158 | fd, |
| 159 | readable: true, | 159 | readable: true, |
| 160 | writable: false, | 160 | writable: false, |
apps/server/src/checkpointing/CheckpointStore.test.ts+4-4| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off | 1 | // @effect-diagnostics nodeBuiltinImport:off |
| 2 | import path from "node:path"; | 2 | import * as NodePath from "node:path"; |
| 3 | 3 | ||
| 4 | import * as NodeServices from "@effect/platform-node/NodeServices"; | 4 | import * as NodeServices from "@effect/platform-node/NodeServices"; |
| 5 | import { it } from "@effect/vitest"; | 5 | import { it } from "@effect/vitest"; |
| ... | @@ -80,7 +80,7 @@ function initRepoWithCommit( | ... | @@ -80,7 +80,7 @@ function initRepoWithCommit( |
| 80 | yield* git(cwd, ["init"]); | 80 | yield* git(cwd, ["init"]); |
| 81 | yield* git(cwd, ["config", "user.email", "test@test.com"]); | 81 | yield* git(cwd, ["config", "user.email", "test@test.com"]); |
| 82 | yield* git(cwd, ["config", "user.name", "Test"]); | 82 | yield* git(cwd, ["config", "user.name", "Test"]); |
| 83 | yield* writeTextFile(path.join(cwd, "README.md"), "# test\n"); | 83 | yield* writeTextFile(NodePath.join(cwd, "README.md"), "# test\n"); |
| 84 | yield* git(cwd, ["add", "."]); | 84 | yield* git(cwd, ["add", "."]); |
| 85 | yield* git(cwd, ["commit", "-m", "initial commit"]); | 85 | yield* git(cwd, ["commit", "-m", "initial commit"]); |
| 86 | }); | 86 | }); |
| ... | @@ -107,7 +107,7 @@ it.layer(TestLayer)("CheckpointStore.layer", (it) => { | ... | @@ -107,7 +107,7 @@ it.layer(TestLayer)("CheckpointStore.layer", (it) => { |
| 107 | cwd: tmp, | 107 | cwd: tmp, |
| 108 | checkpointRef: fromCheckpointRef, | 108 | checkpointRef: fromCheckpointRef, |
| 109 | }); | 109 | }); |
| 110 | yield* writeTextFile(path.join(tmp, "README.md"), buildLargeText()); | 110 | yield* writeTextFile(NodePath.join(tmp, "README.md"), buildLargeText()); |
| 111 | yield* checkpointStore.captureCheckpoint({ | 111 | yield* checkpointStore.captureCheckpoint({ |
| 112 | cwd: tmp, | 112 | cwd: tmp, |
| 113 | checkpointRef: toCheckpointRef, | 113 | checkpointRef: toCheckpointRef, |
| ... | @@ -135,7 +135,7 @@ it.layer(TestLayer)("CheckpointStore.layer", (it) => { | ... | @@ -135,7 +135,7 @@ it.layer(TestLayer)("CheckpointStore.layer", (it) => { |
| 135 | const fromCheckpointRef = checkpointRefForThreadTurn(threadId, 0); | 135 | const fromCheckpointRef = checkpointRefForThreadTurn(threadId, 0); |
| 136 | const toCheckpointRef = checkpointRefForThreadTurn(threadId, 1); | 136 | const toCheckpointRef = checkpointRefForThreadTurn(threadId, 1); |
| 137 | 137 | ||
| 138 | const componentPath = path.join(tmp, "Component.tsx"); | 138 | const componentPath = NodePath.join(tmp, "Component.tsx"); |
| 139 | yield* writeTextFile( | 139 | yield* writeTextFile( |
| 140 | componentPath, | 140 | componentPath, |
| 141 | [ | 141 | [ |
apps/server/src/cloud/CliTokenManager.ts+2-2| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off - The CLI loopback OAuth callback is a Node HTTP boundary. | 1 | // @effect-diagnostics nodeBuiltinImport:off - The CLI loopback OAuth callback is a Node HTTP boundary. |
| 2 | import { createServer } from "node:http"; | 2 | import * as NodeHttp from "node:http"; |
| 3 | 3 | ||
| 4 | import * as NodeHttpServer from "@effect/platform-node/NodeHttpServer"; | 4 | import * as NodeHttpServer from "@effect/platform-node/NodeHttpServer"; |
| 5 | import * as Clock from "effect/Clock"; | 5 | import * as Clock from "effect/Clock"; |
| ... | @@ -206,7 +206,7 @@ export const make = Effect.gen(function* () { | ... | @@ -206,7 +206,7 @@ export const make = Effect.gen(function* () { |
| 206 | disableLogger: true, | 206 | disableLogger: true, |
| 207 | }).pipe( | 207 | }).pipe( |
| 208 | Layer.provide( | 208 | Layer.provide( |
| 209 | NodeHttpServer.layer(createServer, { | 209 | NodeHttpServer.layer(NodeHttp.createServer, { |
| 210 | host: "127.0.0.1", | 210 | host: "127.0.0.1", |
| 211 | port: 34338, | 211 | port: 34338, |
| 212 | disablePreemptiveShutdown: true, | 212 | disablePreemptiveShutdown: true, |
apps/server/src/cloud/http.ts+2-2| ... | @@ -1,4 +1,4 @@ | ... | @@ -1,4 +1,4 @@ |
| 1 | import { createPublicKey } from "node:crypto"; | 1 | import * as NodeCrypto from "node:crypto"; |
| 2 | import { | 2 | import { |
| 3 | AuthRelayReadScope, | 3 | AuthRelayReadScope, |
| 4 | AuthRelayWriteScope, | 4 | AuthRelayWriteScope, |
| ... | @@ -152,7 +152,7 @@ function validateCloudMintPublicKey( | ... | @@ -152,7 +152,7 @@ function validateCloudMintPublicKey( |
| 152 | publicKey: string, | 152 | publicKey: string, |
| 153 | ): Effect.Effect<void, EnvironmentHttpBadRequestError> { | 153 | ): Effect.Effect<void, EnvironmentHttpBadRequestError> { |
| 154 | return Effect.try({ | 154 | return Effect.try({ |
| 155 | try: () => createPublicKey(publicKey.replace(/\\n/g, "\n")), | 155 | try: () => NodeCrypto.createPublicKey(publicKey.replace(/\\n/g, "\n")), |
| 156 | catch: () => | 156 | catch: () => |
| 157 | new EnvironmentHttpBadRequestError({ | 157 | new EnvironmentHttpBadRequestError({ |
| 158 | message: "Cloud mint public key must be a valid Ed25519 public key.", | 158 | message: "Cloud mint public key must be a valid Ed25519 public key.", |
apps/server/src/environment/ServerEnvironment.test.ts+2-2| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off | 1 | // @effect-diagnostics nodeBuiltinImport:off |
| 2 | import { dirname } from "node:path"; | 2 | import * as NodePath from "node:path"; |
| 3 | import * as NodeServices from "@effect/platform-node/NodeServices"; | 3 | import * as NodeServices from "@effect/platform-node/NodeServices"; |
| 4 | import { expect, it } from "@effect/vitest"; | 4 | import { expect, it } from "@effect/vitest"; |
| 5 | import * as Effect from "effect/Effect"; | 5 | import * as Effect from "effect/Effect"; |
| ... | @@ -76,7 +76,7 @@ it.layer(NodeServices.layer)("ServerEnvironmentLive", (it) => { | ... | @@ -76,7 +76,7 @@ it.layer(NodeServices.layer)("ServerEnvironmentLive", (it) => { |
| 76 | }); | 76 | }); |
| 77 | const serverConfig = yield* makeServerConfig(baseDir); | 77 | const serverConfig = yield* makeServerConfig(baseDir); |
| 78 | const environmentIdPath = serverConfig.environmentIdPath; | 78 | const environmentIdPath = serverConfig.environmentIdPath; |
| 79 | yield* fileSystem.makeDirectory(dirname(environmentIdPath), { recursive: true }); | 79 | yield* fileSystem.makeDirectory(NodePath.dirname(environmentIdPath), { recursive: true }); |
| 80 | yield* fileSystem.writeFileString(environmentIdPath, "persisted-environment-id\n"); | 80 | yield* fileSystem.writeFileString(environmentIdPath, "persisted-environment-id\n"); |
| 81 | const writeAttempts: string[] = []; | 81 | const writeAttempts: string[] = []; |
| 82 | const failingFileSystemLayer = FileSystem.layerNoop({ | 82 | const failingFileSystemLayer = FileSystem.layerNoop({ |
apps/server/src/git/GitManager.test.ts+64-56| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off | 1 | // @effect-diagnostics nodeBuiltinImport:off |
| 2 | import fs from "node:fs"; | 2 | import * as NodeFS from "node:fs"; |
| 3 | import path from "node:path"; | 3 | import * as NodePath from "node:path"; |
| 4 | import { spawnSync } from "node:child_process"; | 4 | import * as NodeChildProcess from "node:child_process"; |
| 5 | 5 | ||
| 6 | import * as NodeServices from "@effect/platform-node/NodeServices"; | 6 | import * as NodeServices from "@effect/platform-node/NodeServices"; |
| 7 | import { it } from "@effect/vitest"; | 7 | import { it } from "@effect/vitest"; |
| ... | @@ -164,7 +164,7 @@ function normalizeFakePullRequestSummary(raw: unknown): GitHubCli.GitHubPullRequ | ... | @@ -164,7 +164,7 @@ function normalizeFakePullRequestSummary(raw: unknown): GitHubCli.GitHubPullRequ |
| 164 | } | 164 | } |
| 165 | 165 | ||
| 166 | function runGitSyncForFakeGh(cwd: string, args: readonly string[]): void { | 166 | function runGitSyncForFakeGh(cwd: string, args: readonly string[]): void { |
| 167 | const result = spawnSync("git", args, { | 167 | const result = NodeChildProcess.spawnSync("git", args, { |
| 168 | cwd, | 168 | cwd, |
| 169 | encoding: "utf8", | 169 | encoding: "utf8", |
| 170 | }); | 170 | }); |
| ... | @@ -254,7 +254,7 @@ function initRepo( | ... | @@ -254,7 +254,7 @@ function initRepo( |
| 254 | yield* runGit(cwd, ["init", "--initial-branch=main"]); | 254 | yield* runGit(cwd, ["init", "--initial-branch=main"]); |
| 255 | yield* runGit(cwd, ["config", "user.email", "test@example.com"]); | 255 | yield* runGit(cwd, ["config", "user.email", "test@example.com"]); |
| 256 | yield* runGit(cwd, ["config", "user.name", "Test User"]); | 256 | yield* runGit(cwd, ["config", "user.name", "Test User"]); |
| 257 | yield* fs.writeFileString(path.join(cwd, "README.md"), "hello\n"); | 257 | yield* fs.writeFileString(NodePath.join(cwd, "README.md"), "hello\n"); |
| 258 | yield* runGit(cwd, ["add", "README.md"]); | 258 | yield* runGit(cwd, ["add", "README.md"]); |
| 259 | yield* runGit(cwd, ["commit", "-m", "Initial commit"]); | 259 | yield* runGit(cwd, ["commit", "-m", "Initial commit"]); |
| 260 | }); | 260 | }); |
| ... | @@ -459,7 +459,7 @@ function createGitHubCliWithFakeGh(scenario: FakeGhScenario = {}): { | ... | @@ -459,7 +459,7 @@ function createGitHubCliWithFakeGh(scenario: FakeGhScenario = {}): { |
| 459 | try: () => { | 459 | try: () => { |
| 460 | const headBranch = scenario.pullRequest?.headRefName; | 460 | const headBranch = scenario.pullRequest?.headRefName; |
| 461 | if (headBranch) { | 461 | if (headBranch) { |
| 462 | const existingBranch = spawnSync( | 462 | const existingBranch = NodeChildProcess.spawnSync( |
| 463 | "git", | 463 | "git", |
| 464 | ["show-ref", "--verify", "--quiet", `refs/heads/${headBranch}`], | 464 | ["show-ref", "--verify", "--quiet", `refs/heads/${headBranch}`], |
| 465 | { | 465 | { |
| ... | @@ -916,7 +916,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -916,7 +916,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 916 | it.effect("status returns an explicit non-repo result for deleted directories", () => | 916 | it.effect("status returns an explicit non-repo result for deleted directories", () => |
| 917 | Effect.gen(function* () { | 917 | Effect.gen(function* () { |
| 918 | const rootDir = yield* makeTempDir("t3code-git-manager-missing-dir-"); | 918 | const rootDir = yield* makeTempDir("t3code-git-manager-missing-dir-"); |
| 919 | const cwd = path.join(rootDir, "deleted-repo"); | 919 | const cwd = NodePath.join(rootDir, "deleted-repo"); |
| 920 | yield* makeDirectory(cwd); | 920 | yield* makeDirectory(cwd); |
| 921 | yield* removePath(cwd); | 921 | yield* removePath(cwd); |
| 922 | const { manager } = yield* makeManager(); | 922 | const { manager } = yield* makeManager(); |
| ... | @@ -1026,7 +1026,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -1026,7 +1026,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 1026 | const forkDir = yield* createBareRemote(); | 1026 | const forkDir = yield* createBareRemote(); |
| 1027 | yield* runGit(repoDir, ["remote", "add", "fork-seed", forkDir]); | 1027 | yield* runGit(repoDir, ["remote", "add", "fork-seed", forkDir]); |
| 1028 | yield* runGit(repoDir, ["checkout", "-b", "statemachine"]); | 1028 | yield* runGit(repoDir, ["checkout", "-b", "statemachine"]); |
| 1029 | fs.writeFileSync(path.join(repoDir, "fork-pr.txt"), "fork pr\n"); | 1029 | NodeFS.writeFileSync(NodePath.join(repoDir, "fork-pr.txt"), "fork pr\n"); |
| 1030 | yield* runGit(repoDir, ["add", "fork-pr.txt"]); | 1030 | yield* runGit(repoDir, ["add", "fork-pr.txt"]); |
| 1031 | yield* runGit(repoDir, ["commit", "-m", "Fork PR branch"]); | 1031 | yield* runGit(repoDir, ["commit", "-m", "Fork PR branch"]); |
| 1032 | yield* runGit(repoDir, ["push", "-u", "fork-seed", "statemachine"]); | 1032 | yield* runGit(repoDir, ["push", "-u", "fork-seed", "statemachine"]); |
| ... | @@ -1348,7 +1348,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -1348,7 +1348,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 1348 | Effect.gen(function* () { | 1348 | Effect.gen(function* () { |
| 1349 | const repoDir = yield* makeTempDir("t3code-git-manager-"); | 1349 | const repoDir = yield* makeTempDir("t3code-git-manager-"); |
| 1350 | yield* initRepo(repoDir); | 1350 | yield* initRepo(repoDir); |
| 1351 | fs.writeFileSync(path.join(repoDir, "README.md"), "hello\nworld\n"); | 1351 | NodeFS.writeFileSync(NodePath.join(repoDir, "README.md"), "hello\nworld\n"); |
| 1352 | 1352 | ||
| 1353 | const { manager } = yield* makeManager(); | 1353 | const { manager } = yield* makeManager(); |
| 1354 | const result = yield* runStackedAction(manager, { | 1354 | const result = yield* runStackedAction(manager, { |
| ... | @@ -1383,7 +1383,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -1383,7 +1383,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 1383 | Effect.gen(function* () { | 1383 | Effect.gen(function* () { |
| 1384 | const repoDir = yield* makeTempDir("t3code-git-manager-"); | 1384 | const repoDir = yield* makeTempDir("t3code-git-manager-"); |
| 1385 | yield* initRepo(repoDir); | 1385 | yield* initRepo(repoDir); |
| 1386 | fs.writeFileSync(path.join(repoDir, "README.md"), "hello\ncustom\n"); | 1386 | NodeFS.writeFileSync(NodePath.join(repoDir, "README.md"), "hello\ncustom\n"); |
| 1387 | let generatedCount = 0; | 1387 | let generatedCount = 0; |
| 1388 | 1388 | ||
| 1389 | const { manager } = yield* makeManager({ | 1389 | const { manager } = yield* makeManager({ |
| ... | @@ -1426,8 +1426,8 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -1426,8 +1426,8 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 1426 | Effect.gen(function* () { | 1426 | Effect.gen(function* () { |
| 1427 | const repoDir = yield* makeTempDir("t3code-git-manager-"); | 1427 | const repoDir = yield* makeTempDir("t3code-git-manager-"); |
| 1428 | yield* initRepo(repoDir); | 1428 | yield* initRepo(repoDir); |
| 1429 | fs.writeFileSync(path.join(repoDir, "a.txt"), "file a\n"); | 1429 | NodeFS.writeFileSync(NodePath.join(repoDir, "a.txt"), "file a\n"); |
| 1430 | fs.writeFileSync(path.join(repoDir, "b.txt"), "file b\n"); | 1430 | NodeFS.writeFileSync(NodePath.join(repoDir, "b.txt"), "file b\n"); |
| 1431 | 1431 | ||
| 1432 | const { manager } = yield* makeManager(); | 1432 | const { manager } = yield* makeManager(); |
| 1433 | const result = yield* runStackedAction(manager, { | 1433 | const result = yield* runStackedAction(manager, { |
| ... | @@ -1454,7 +1454,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -1454,7 +1454,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 1454 | const remoteDir = yield* createBareRemote(); | 1454 | const remoteDir = yield* createBareRemote(); |
| 1455 | yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); | 1455 | yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); |
| 1456 | yield* runGit(repoDir, ["push", "-u", "origin", "main"]); | 1456 | yield* runGit(repoDir, ["push", "-u", "origin", "main"]); |
| 1457 | fs.writeFileSync(path.join(repoDir, "README.md"), "hello\nfeature-branch\n"); | 1457 | NodeFS.writeFileSync(NodePath.join(repoDir, "README.md"), "hello\nfeature-branch\n"); |
| 1458 | let generatedCount = 0; | 1458 | let generatedCount = 0; |
| 1459 | 1459 | ||
| 1460 | const { manager } = yield* makeManager({ | 1460 | const { manager } = yield* makeManager({ |
| ... | @@ -1514,7 +1514,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -1514,7 +1514,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 1514 | Effect.gen(function* () { | 1514 | Effect.gen(function* () { |
| 1515 | const repoDir = yield* makeTempDir("t3code-git-manager-"); | 1515 | const repoDir = yield* makeTempDir("t3code-git-manager-"); |
| 1516 | yield* initRepo(repoDir); | 1516 | yield* initRepo(repoDir); |
| 1517 | fs.writeFileSync(path.join(repoDir, "README.md"), "hello\ncustom-feature\n"); | 1517 | NodeFS.writeFileSync(NodePath.join(repoDir, "README.md"), "hello\ncustom-feature\n"); |
| 1518 | let generatedCount = 0; | 1518 | let generatedCount = 0; |
| 1519 | 1519 | ||
| 1520 | const { manager } = yield* makeManager({ | 1520 | const { manager } = yield* makeManager({ |
| ... | @@ -1597,7 +1597,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -1597,7 +1597,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 1597 | yield* runGit(repoDir, ["checkout", "-b", "feature/stacked-flow"]); | 1597 | yield* runGit(repoDir, ["checkout", "-b", "feature/stacked-flow"]); |
| 1598 | const remoteDir = yield* createBareRemote(); | 1598 | const remoteDir = yield* createBareRemote(); |
| 1599 | yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); | 1599 | yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); |
| 1600 | fs.writeFileSync(path.join(repoDir, "feature.txt"), "feature\n"); | 1600 | NodeFS.writeFileSync(NodePath.join(repoDir, "feature.txt"), "feature\n"); |
| 1601 | 1601 | ||
| 1602 | const { manager } = yield* makeManager(); | 1602 | const { manager } = yield* makeManager(); |
| 1603 | const result = yield* runStackedAction(manager, { | 1603 | const result = yield* runStackedAction(manager, { |
| ... | @@ -1626,7 +1626,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -1626,7 +1626,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 1626 | yield* runGit(repoDir, ["checkout", "-b", "feature/no-upstream-pr"]); | 1626 | yield* runGit(repoDir, ["checkout", "-b", "feature/no-upstream-pr"]); |
| 1627 | const remoteDir = yield* createBareRemote(); | 1627 | const remoteDir = yield* createBareRemote(); |
| 1628 | yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); | 1628 | yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); |
| 1629 | fs.writeFileSync(path.join(repoDir, "feature.txt"), "feature\n"); | 1629 | NodeFS.writeFileSync(NodePath.join(repoDir, "feature.txt"), "feature\n"); |
| 1630 | 1630 | ||
| 1631 | const { manager, ghCalls } = yield* makeManager({ | 1631 | const { manager, ghCalls } = yield* makeManager({ |
| 1632 | ghScenario: { | 1632 | ghScenario: { |
| ... | @@ -1697,7 +1697,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -1697,7 +1697,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 1697 | yield* runGit(repoDir, ["checkout", "-b", "feature/push-only"]); | 1697 | yield* runGit(repoDir, ["checkout", "-b", "feature/push-only"]); |
| 1698 | const remoteDir = yield* createBareRemote(); | 1698 | const remoteDir = yield* createBareRemote(); |
| 1699 | yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); | 1699 | yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); |
| 1700 | fs.writeFileSync(path.join(repoDir, "push-only.txt"), "push only\n"); | 1700 | NodeFS.writeFileSync(NodePath.join(repoDir, "push-only.txt"), "push only\n"); |
| 1701 | yield* runGit(repoDir, ["add", "push-only.txt"]); | 1701 | yield* runGit(repoDir, ["add", "push-only.txt"]); |
| 1702 | yield* runGit(repoDir, ["commit", "-m", "Push only branch"]); | 1702 | yield* runGit(repoDir, ["commit", "-m", "Push only branch"]); |
| 1703 | 1703 | ||
| ... | @@ -1725,11 +1725,11 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -1725,11 +1725,11 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 1725 | yield* runGit(repoDir, ["checkout", "-b", "feature/push-dirty"]); | 1725 | yield* runGit(repoDir, ["checkout", "-b", "feature/push-dirty"]); |
| 1726 | const remoteDir = yield* createBareRemote(); | 1726 | const remoteDir = yield* createBareRemote(); |
| 1727 | yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); | 1727 | yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); |
| 1728 | fs.writeFileSync(path.join(repoDir, "push-dirty.txt"), "push dirty\n"); | 1728 | NodeFS.writeFileSync(NodePath.join(repoDir, "push-dirty.txt"), "push dirty\n"); |
| 1729 | yield* runGit(repoDir, ["add", "push-dirty.txt"]); | 1729 | yield* runGit(repoDir, ["add", "push-dirty.txt"]); |
| 1730 | yield* runGit(repoDir, ["commit", "-m", "Push dirty branch"]); | 1730 | yield* runGit(repoDir, ["commit", "-m", "Push dirty branch"]); |
| 1731 | fs.mkdirSync(path.join(repoDir, ".vercel")); | 1731 | NodeFS.mkdirSync(NodePath.join(repoDir, ".vercel")); |
| 1732 | fs.writeFileSync(path.join(repoDir, ".vercel", "project.json"), "{}\n"); | 1732 | NodeFS.writeFileSync(NodePath.join(repoDir, ".vercel", "project.json"), "{}\n"); |
| 1733 | 1733 | ||
| 1734 | const { manager } = yield* makeManager(); | 1734 | const { manager } = yield* makeManager(); |
| 1735 | const result = yield* runStackedAction(manager, { | 1735 | const result = yield* runStackedAction(manager, { |
| ... | @@ -1760,7 +1760,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -1760,7 +1760,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 1760 | yield* runGit(repoDir, ["checkout", "-b", "feature/create-pr-only"]); | 1760 | yield* runGit(repoDir, ["checkout", "-b", "feature/create-pr-only"]); |
| 1761 | const remoteDir = yield* createBareRemote(); | 1761 | const remoteDir = yield* createBareRemote(); |
| 1762 | yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); | 1762 | yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); |
| 1763 | fs.writeFileSync(path.join(repoDir, "create-pr-only.txt"), "create pr\n"); | 1763 | NodeFS.writeFileSync(NodePath.join(repoDir, "create-pr-only.txt"), "create pr\n"); |
| 1764 | yield* runGit(repoDir, ["add", "create-pr-only.txt"]); | 1764 | yield* runGit(repoDir, ["add", "create-pr-only.txt"]); |
| 1765 | yield* runGit(repoDir, ["commit", "-m", "Create PR only branch"]); | 1765 | yield* runGit(repoDir, ["commit", "-m", "Create PR only branch"]); |
| 1766 | 1766 | ||
| ... | @@ -1805,7 +1805,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -1805,7 +1805,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 1805 | const repoDir = yield* makeTempDir("t3code-git-manager-"); | 1805 | const repoDir = yield* makeTempDir("t3code-git-manager-"); |
| 1806 | yield* initRepo(repoDir); | 1806 | yield* initRepo(repoDir); |
| 1807 | yield* runGit(repoDir, ["checkout", "-b", "feature/provider-fallback"]); | 1807 | yield* runGit(repoDir, ["checkout", "-b", "feature/provider-fallback"]); |
| 1808 | fs.writeFileSync(path.join(repoDir, "provider-fallback.txt"), "fallback\n"); | 1808 | NodeFS.writeFileSync(NodePath.join(repoDir, "provider-fallback.txt"), "fallback\n"); |
| 1809 | yield* runGit(repoDir, ["add", "provider-fallback.txt"]); | 1809 | yield* runGit(repoDir, ["add", "provider-fallback.txt"]); |
| 1810 | yield* runGit(repoDir, ["commit", "-m", "Provider fallback"]); | 1810 | yield* runGit(repoDir, ["commit", "-m", "Provider fallback"]); |
| 1811 | const remoteDir = yield* createBareRemote(); | 1811 | const remoteDir = yield* createBareRemote(); |
| ... | @@ -1982,7 +1982,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -1982,7 +1982,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 1982 | yield* runGit(repoDir, ["checkout", "main"]); | 1982 | yield* runGit(repoDir, ["checkout", "main"]); |
| 1983 | yield* runGit(repoDir, ["branch", "-D", "effect-atom"]); | 1983 | yield* runGit(repoDir, ["branch", "-D", "effect-atom"]); |
| 1984 | yield* runGit(repoDir, ["checkout", "--track", "my-org/upstream/effect-atom"]); | 1984 | yield* runGit(repoDir, ["checkout", "--track", "my-org/upstream/effect-atom"]); |
| 1985 | fs.writeFileSync(path.join(repoDir, "changes.txt"), "change\n"); | 1985 | NodeFS.writeFileSync(NodePath.join(repoDir, "changes.txt"), "change\n"); |
| 1986 | yield* runGit(repoDir, ["add", "changes.txt"]); | 1986 | yield* runGit(repoDir, ["add", "changes.txt"]); |
| 1987 | yield* runGit(repoDir, ["commit", "-m", "Feature commit"]); | 1987 | yield* runGit(repoDir, ["commit", "-m", "Feature commit"]); |
| 1988 | 1988 | ||
| ... | @@ -2200,7 +2200,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -2200,7 +2200,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 2200 | yield* runGit(repoDir, ["checkout", "-b", "feature-create-pr"]); | 2200 | yield* runGit(repoDir, ["checkout", "-b", "feature-create-pr"]); |
| 2201 | const remoteDir = yield* createBareRemote(); | 2201 | const remoteDir = yield* createBareRemote(); |
| 2202 | yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); | 2202 | yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); |
| 2203 | fs.writeFileSync(path.join(repoDir, "changes.txt"), "change\n"); | 2203 | NodeFS.writeFileSync(NodePath.join(repoDir, "changes.txt"), "change\n"); |
| 2204 | yield* runGit(repoDir, ["add", "changes.txt"]); | 2204 | yield* runGit(repoDir, ["add", "changes.txt"]); |
| 2205 | yield* runGit(repoDir, ["commit", "-m", "Feature commit"]); | 2205 | yield* runGit(repoDir, ["commit", "-m", "Feature commit"]); |
| 2206 | yield* runGit(repoDir, ["push", "-u", "origin", "feature-create-pr"]); | 2206 | yield* runGit(repoDir, ["push", "-u", "origin", "feature-create-pr"]); |
| ... | @@ -2252,7 +2252,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -2252,7 +2252,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 2252 | yield* runGit(peerDir, ["clone", remoteDir, "."]); | 2252 | yield* runGit(peerDir, ["clone", remoteDir, "."]); |
| 2253 | yield* runGit(peerDir, ["config", "user.email", "peer@example.com"]); | 2253 | yield* runGit(peerDir, ["config", "user.email", "peer@example.com"]); |
| 2254 | yield* runGit(peerDir, ["config", "user.name", "Peer User"]); | 2254 | yield* runGit(peerDir, ["config", "user.name", "Peer User"]); |
| 2255 | fs.writeFileSync(path.join(peerDir, "remote.txt"), "remote\n"); | 2255 | NodeFS.writeFileSync(NodePath.join(peerDir, "remote.txt"), "remote\n"); |
| 2256 | yield* runGit(peerDir, ["add", "remote.txt"]); | 2256 | yield* runGit(peerDir, ["add", "remote.txt"]); |
| 2257 | yield* runGit(peerDir, ["commit", "-m", "Remote base commit"]); | 2257 | yield* runGit(peerDir, ["commit", "-m", "Remote base commit"]); |
| 2258 | yield* runGit(peerDir, ["push", "origin", "main"]); | 2258 | yield* runGit(peerDir, ["push", "origin", "main"]); |
| ... | @@ -2265,7 +2265,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -2265,7 +2265,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 2265 | "feature/remote-base", | 2265 | "feature/remote-base", |
| 2266 | "origin/main", | 2266 | "origin/main", |
| 2267 | ]); | 2267 | ]); |
| 2268 | fs.writeFileSync(path.join(repoDir, "feature.txt"), "feature\n"); | 2268 | NodeFS.writeFileSync(NodePath.join(repoDir, "feature.txt"), "feature\n"); |
| 2269 | yield* runGit(repoDir, ["add", "feature.txt"]); | 2269 | yield* runGit(repoDir, ["add", "feature.txt"]); |
| 2270 | yield* runGit(repoDir, ["commit", "-m", "Feature commit"]); | 2270 | yield* runGit(repoDir, ["commit", "-m", "Feature commit"]); |
| 2271 | yield* runGit(repoDir, ["push", "-u", "origin", "feature/remote-base"]); | 2271 | yield* runGit(repoDir, ["push", "-u", "origin", "feature/remote-base"]); |
| ... | @@ -2304,7 +2304,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -2304,7 +2304,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 2304 | yield* runGit(repoDir, ["checkout", "-b", "feature/no-fork-match"]); | 2304 | yield* runGit(repoDir, ["checkout", "-b", "feature/no-fork-match"]); |
| 2305 | const remoteDir = yield* createBareRemote(); | 2305 | const remoteDir = yield* createBareRemote(); |
| 2306 | yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); | 2306 | yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); |
| 2307 | fs.writeFileSync(path.join(repoDir, "changes.txt"), "change\n"); | 2307 | NodeFS.writeFileSync(NodePath.join(repoDir, "changes.txt"), "change\n"); |
| 2308 | yield* runGit(repoDir, ["add", "changes.txt"]); | 2308 | yield* runGit(repoDir, ["add", "changes.txt"]); |
| 2309 | yield* runGit(repoDir, ["commit", "-m", "Feature commit"]); | 2309 | yield* runGit(repoDir, ["commit", "-m", "Feature commit"]); |
| 2310 | yield* runGit(repoDir, ["push", "-u", "origin", "feature/no-fork-match"]); | 2310 | yield* runGit(repoDir, ["push", "-u", "origin", "feature/no-fork-match"]); |
| ... | @@ -2376,7 +2376,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -2376,7 +2376,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 2376 | const forkDir = yield* createBareRemote(); | 2376 | const forkDir = yield* createBareRemote(); |
| 2377 | yield* runGit(repoDir, ["remote", "add", "fork-seed", forkDir]); | 2377 | yield* runGit(repoDir, ["remote", "add", "fork-seed", forkDir]); |
| 2378 | yield* runGit(repoDir, ["checkout", "-b", "statemachine"]); | 2378 | yield* runGit(repoDir, ["checkout", "-b", "statemachine"]); |
| 2379 | fs.writeFileSync(path.join(repoDir, "changes.txt"), "change\n"); | 2379 | NodeFS.writeFileSync(NodePath.join(repoDir, "changes.txt"), "change\n"); |
| 2380 | yield* runGit(repoDir, ["add", "changes.txt"]); | 2380 | yield* runGit(repoDir, ["add", "changes.txt"]); |
| 2381 | yield* runGit(repoDir, ["commit", "-m", "Feature commit"]); | 2381 | yield* runGit(repoDir, ["commit", "-m", "Feature commit"]); |
| 2382 | yield* runGit(repoDir, ["push", "-u", "fork-seed", "statemachine"]); | 2382 | yield* runGit(repoDir, ["push", "-u", "fork-seed", "statemachine"]); |
| ... | @@ -2556,7 +2556,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -2556,7 +2556,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 2556 | const repoDir = yield* makeTempDir("t3code-git-manager-"); | 2556 | const repoDir = yield* makeTempDir("t3code-git-manager-"); |
| 2557 | yield* initRepo(repoDir); | 2557 | yield* initRepo(repoDir); |
| 2558 | yield* runGit(repoDir, ["checkout", "-b", "feature/pr-local"]); | 2558 | yield* runGit(repoDir, ["checkout", "-b", "feature/pr-local"]); |
| 2559 | fs.writeFileSync(path.join(repoDir, "local.txt"), "local\n"); | 2559 | NodeFS.writeFileSync(NodePath.join(repoDir, "local.txt"), "local\n"); |
| 2560 | yield* runGit(repoDir, ["add", "local.txt"]); | 2560 | yield* runGit(repoDir, ["add", "local.txt"]); |
| 2561 | yield* runGit(repoDir, ["commit", "-m", "Local PR branch"]); | 2561 | yield* runGit(repoDir, ["commit", "-m", "Local PR branch"]); |
| 2562 | 2562 | ||
| ... | @@ -2597,7 +2597,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -2597,7 +2597,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 2597 | yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); | 2597 | yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); |
| 2598 | yield* runGit(repoDir, ["push", "-u", "origin", "main"]); | 2598 | yield* runGit(repoDir, ["push", "-u", "origin", "main"]); |
| 2599 | yield* runGit(repoDir, ["checkout", "-b", "feature/pr-local-upstream"]); | 2599 | yield* runGit(repoDir, ["checkout", "-b", "feature/pr-local-upstream"]); |
| 2600 | fs.writeFileSync(path.join(repoDir, "upstream.txt"), "upstream\n"); | 2600 | NodeFS.writeFileSync(NodePath.join(repoDir, "upstream.txt"), "upstream\n"); |
| 2601 | yield* runGit(repoDir, ["add", "upstream.txt"]); | 2601 | yield* runGit(repoDir, ["add", "upstream.txt"]); |
| 2602 | yield* runGit(repoDir, ["commit", "-m", "Local upstream PR branch"]); | 2602 | yield* runGit(repoDir, ["commit", "-m", "Local upstream PR branch"]); |
| 2603 | yield* runGit(repoDir, ["push", "-u", "origin", "feature/pr-local-upstream"]); | 2603 | yield* runGit(repoDir, ["push", "-u", "origin", "feature/pr-local-upstream"]); |
| ... | @@ -2655,7 +2655,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -2655,7 +2655,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 2655 | yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); | 2655 | yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); |
| 2656 | yield* runGit(repoDir, ["push", "-u", "origin", "main"]); | 2656 | yield* runGit(repoDir, ["push", "-u", "origin", "main"]); |
| 2657 | yield* runGit(repoDir, ["checkout", "-b", "feature/pr-local-no-head-repo"]); | 2657 | yield* runGit(repoDir, ["checkout", "-b", "feature/pr-local-no-head-repo"]); |
| 2658 | fs.writeFileSync(path.join(repoDir, "no-head-repo.txt"), "upstream\n"); | 2658 | NodeFS.writeFileSync(NodePath.join(repoDir, "no-head-repo.txt"), "upstream\n"); |
| 2659 | yield* runGit(repoDir, ["add", "no-head-repo.txt"]); | 2659 | yield* runGit(repoDir, ["add", "no-head-repo.txt"]); |
| 2660 | yield* runGit(repoDir, ["commit", "-m", "Local PR branch without repo metadata"]); | 2660 | yield* runGit(repoDir, ["commit", "-m", "Local PR branch without repo metadata"]); |
| 2661 | yield* runGit(repoDir, ["push", "-u", "origin", "feature/pr-local-no-head-repo"]); | 2661 | yield* runGit(repoDir, ["push", "-u", "origin", "feature/pr-local-no-head-repo"]); |
| ... | @@ -2702,7 +2702,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -2702,7 +2702,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 2702 | yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); | 2702 | yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); |
| 2703 | yield* runGit(repoDir, ["push", "-u", "origin", "main"]); | 2703 | yield* runGit(repoDir, ["push", "-u", "origin", "main"]); |
| 2704 | yield* runGit(repoDir, ["checkout", "-b", "feature/pr-worktree"]); | 2704 | yield* runGit(repoDir, ["checkout", "-b", "feature/pr-worktree"]); |
| 2705 | fs.writeFileSync(path.join(repoDir, "worktree.txt"), "worktree\n"); | 2705 | NodeFS.writeFileSync(NodePath.join(repoDir, "worktree.txt"), "worktree\n"); |
| 2706 | yield* runGit(repoDir, ["add", "worktree.txt"]); | 2706 | yield* runGit(repoDir, ["add", "worktree.txt"]); |
| 2707 | yield* runGit(repoDir, ["commit", "-m", "PR worktree branch"]); | 2707 | yield* runGit(repoDir, ["commit", "-m", "PR worktree branch"]); |
| 2708 | yield* runGit(repoDir, ["push", "-u", "origin", "feature/pr-worktree"]); | 2708 | yield* runGit(repoDir, ["push", "-u", "origin", "feature/pr-worktree"]); |
| ... | @@ -2730,7 +2730,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -2730,7 +2730,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 2730 | 2730 | ||
| 2731 | expect(result.branch).toBe("feature/pr-worktree"); | 2731 | expect(result.branch).toBe("feature/pr-worktree"); |
| 2732 | expect(result.worktreePath).not.toBeNull(); | 2732 | expect(result.worktreePath).not.toBeNull(); |
| 2733 | expect(fs.existsSync(result.worktreePath as string)).toBe(true); | 2733 | expect(NodeFS.existsSync(result.worktreePath as string)).toBe(true); |
| 2734 | const worktreeBranch = (yield* runGit(result.worktreePath as string, [ | 2734 | const worktreeBranch = (yield* runGit(result.worktreePath as string, [ |
| 2735 | "branch", | 2735 | "branch", |
| 2736 | "--show-current", | 2736 | "--show-current", |
| ... | @@ -2747,7 +2747,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -2747,7 +2747,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 2747 | yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); | 2747 | yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); |
| 2748 | yield* runGit(repoDir, ["push", "-u", "origin", "main"]); | 2748 | yield* runGit(repoDir, ["push", "-u", "origin", "main"]); |
| 2749 | yield* runGit(repoDir, ["checkout", "-b", "feature/pr-worktree-setup"]); | 2749 | yield* runGit(repoDir, ["checkout", "-b", "feature/pr-worktree-setup"]); |
| 2750 | fs.writeFileSync(path.join(repoDir, "setup.txt"), "setup\n"); | 2750 | NodeFS.writeFileSync(NodePath.join(repoDir, "setup.txt"), "setup\n"); |
| 2751 | yield* runGit(repoDir, ["add", "setup.txt"]); | 2751 | yield* runGit(repoDir, ["add", "setup.txt"]); |
| 2752 | yield* runGit(repoDir, ["commit", "-m", "PR worktree setup branch"]); | 2752 | yield* runGit(repoDir, ["commit", "-m", "PR worktree setup branch"]); |
| 2753 | yield* runGit(repoDir, ["push", "-u", "origin", "feature/pr-worktree-setup"]); | 2753 | yield* runGit(repoDir, ["push", "-u", "origin", "feature/pr-worktree-setup"]); |
| ... | @@ -2802,7 +2802,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -2802,7 +2802,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 2802 | yield* runGit(repoDir, ["push", "-u", "origin", "main"]); | 2802 | yield* runGit(repoDir, ["push", "-u", "origin", "main"]); |
| 2803 | yield* runGit(repoDir, ["remote", "add", "fork-seed", forkDir]); | 2803 | yield* runGit(repoDir, ["remote", "add", "fork-seed", forkDir]); |
| 2804 | yield* runGit(repoDir, ["checkout", "-b", "feature/pr-fork"]); | 2804 | yield* runGit(repoDir, ["checkout", "-b", "feature/pr-fork"]); |
| 2805 | fs.writeFileSync(path.join(repoDir, "fork.txt"), "fork\n"); | 2805 | NodeFS.writeFileSync(NodePath.join(repoDir, "fork.txt"), "fork\n"); |
| 2806 | yield* runGit(repoDir, ["add", "fork.txt"]); | 2806 | yield* runGit(repoDir, ["add", "fork.txt"]); |
| 2807 | yield* runGit(repoDir, ["commit", "-m", "Fork PR branch"]); | 2807 | yield* runGit(repoDir, ["commit", "-m", "Fork PR branch"]); |
| 2808 | yield* runGit(repoDir, ["push", "-u", "fork-seed", "feature/pr-fork"]); | 2808 | yield* runGit(repoDir, ["push", "-u", "fork-seed", "feature/pr-fork"]); |
| ... | @@ -2864,7 +2864,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -2864,7 +2864,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 2864 | yield* runGit(repoDir, ["push", "-u", "origin", "main"]); | 2864 | yield* runGit(repoDir, ["push", "-u", "origin", "main"]); |
| 2865 | yield* runGit(repoDir, ["remote", "add", "fork-seed", forkDir]); | 2865 | yield* runGit(repoDir, ["remote", "add", "fork-seed", forkDir]); |
| 2866 | yield* runGit(repoDir, ["checkout", "-b", "feature/pr-local-fork"]); | 2866 | yield* runGit(repoDir, ["checkout", "-b", "feature/pr-local-fork"]); |
| 2867 | fs.writeFileSync(path.join(repoDir, "local-fork.txt"), "local fork\n"); | 2867 | NodeFS.writeFileSync(NodePath.join(repoDir, "local-fork.txt"), "local fork\n"); |
| 2868 | yield* runGit(repoDir, ["add", "local-fork.txt"]); | 2868 | yield* runGit(repoDir, ["add", "local-fork.txt"]); |
| 2869 | yield* runGit(repoDir, ["commit", "-m", "Local fork PR branch"]); | 2869 | yield* runGit(repoDir, ["commit", "-m", "Local fork PR branch"]); |
| 2870 | yield* runGit(repoDir, ["push", "-u", "fork-seed", "feature/pr-local-fork"]); | 2870 | yield* runGit(repoDir, ["push", "-u", "fork-seed", "feature/pr-local-fork"]); |
| ... | @@ -2917,7 +2917,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -2917,7 +2917,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 2917 | yield* runGit(repoDir, ["push", "-u", "origin", "main"]); | 2917 | yield* runGit(repoDir, ["push", "-u", "origin", "main"]); |
| 2918 | yield* runGit(repoDir, ["remote", "add", "binbandit-seed", forkDir]); | 2918 | yield* runGit(repoDir, ["remote", "add", "binbandit-seed", forkDir]); |
| 2919 | yield* runGit(repoDir, ["checkout", "-b", "fix/git-action-default-without-origin"]); | 2919 | yield* runGit(repoDir, ["checkout", "-b", "fix/git-action-default-without-origin"]); |
| 2920 | fs.writeFileSync(path.join(repoDir, "derived-fork.txt"), "derived fork\n"); | 2920 | NodeFS.writeFileSync(NodePath.join(repoDir, "derived-fork.txt"), "derived fork\n"); |
| 2921 | yield* runGit(repoDir, ["add", "derived-fork.txt"]); | 2921 | yield* runGit(repoDir, ["add", "derived-fork.txt"]); |
| 2922 | yield* runGit(repoDir, ["commit", "-m", "Derived fork PR branch"]); | 2922 | yield* runGit(repoDir, ["commit", "-m", "Derived fork PR branch"]); |
| 2923 | yield* runGit(repoDir, [ | 2923 | yield* runGit(repoDir, [ |
| ... | @@ -2969,11 +2969,15 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -2969,11 +2969,15 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 2969 | const repoDir = yield* makeTempDir("t3code-git-manager-"); | 2969 | const repoDir = yield* makeTempDir("t3code-git-manager-"); |
| 2970 | yield* initRepo(repoDir); | 2970 | yield* initRepo(repoDir); |
| 2971 | yield* runGit(repoDir, ["checkout", "-b", "feature/pr-existing-worktree"]); | 2971 | yield* runGit(repoDir, ["checkout", "-b", "feature/pr-existing-worktree"]); |
| 2972 | fs.writeFileSync(path.join(repoDir, "existing.txt"), "existing\n"); | 2972 | NodeFS.writeFileSync(NodePath.join(repoDir, "existing.txt"), "existing\n"); |
| 2973 | yield* runGit(repoDir, ["add", "existing.txt"]); | 2973 | yield* runGit(repoDir, ["add", "existing.txt"]); |
| 2974 | yield* runGit(repoDir, ["commit", "-m", "Existing worktree branch"]); | 2974 | yield* runGit(repoDir, ["commit", "-m", "Existing worktree branch"]); |
| 2975 | yield* runGit(repoDir, ["checkout", "main"]); | 2975 | yield* runGit(repoDir, ["checkout", "main"]); |
| 2976 | const worktreePath = path.join(repoDir, "..", `pr-existing-${path.basename(repoDir)}`); | 2976 | const worktreePath = NodePath.join( |
| 2977 | repoDir, | ||
| 2978 | "..", | ||
| 2979 | `pr-existing-${NodePath.basename(repoDir)}`, | ||
| 2980 | ); | ||
| 2977 | yield* runGit(repoDir, ["worktree", "add", worktreePath, "feature/pr-existing-worktree"]); | 2981 | yield* runGit(repoDir, ["worktree", "add", worktreePath, "feature/pr-existing-worktree"]); |
| 2978 | 2982 | ||
| 2979 | const setupCalls: ProjectSetupScriptRunner.ProjectSetupScriptRunnerInput[] = []; | 2983 | const setupCalls: ProjectSetupScriptRunner.ProjectSetupScriptRunnerInput[] = []; |
| ... | @@ -3004,8 +3008,8 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -3004,8 +3008,8 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 3004 | threadId: asThreadId("thread-pr-existing-worktree"), | 3008 | threadId: asThreadId("thread-pr-existing-worktree"), |
| 3005 | }); | 3009 | }); |
| 3006 | 3010 | ||
| 3007 | expect(result.worktreePath && fs.realpathSync.native(result.worktreePath)).toBe( | 3011 | expect(result.worktreePath && NodeFS.realpathSync.native(result.worktreePath)).toBe( |
| 3008 | fs.realpathSync.native(worktreePath), | 3012 | NodeFS.realpathSync.native(worktreePath), |
| 3009 | ); | 3013 | ); |
| 3010 | expect(result.branch).toBe("feature/pr-existing-worktree"); | 3014 | expect(result.branch).toBe("feature/pr-existing-worktree"); |
| 3011 | expect(setupCalls).toHaveLength(0); | 3015 | expect(setupCalls).toHaveLength(0); |
| ... | @@ -3024,7 +3028,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -3024,7 +3028,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 3024 | yield* runGit(repoDir, ["push", "-u", "origin", "main"]); | 3028 | yield* runGit(repoDir, ["push", "-u", "origin", "main"]); |
| 3025 | yield* runGit(repoDir, ["remote", "add", "fork-seed", forkDir]); | 3029 | yield* runGit(repoDir, ["remote", "add", "fork-seed", forkDir]); |
| 3026 | yield* runGit(repoDir, ["checkout", "-b", "fork-main-source"]); | 3030 | yield* runGit(repoDir, ["checkout", "-b", "fork-main-source"]); |
| 3027 | fs.writeFileSync(path.join(repoDir, "fork-main.txt"), "fork main\n"); | 3031 | NodeFS.writeFileSync(NodePath.join(repoDir, "fork-main.txt"), "fork main\n"); |
| 3028 | yield* runGit(repoDir, ["add", "fork-main.txt"]); | 3032 | yield* runGit(repoDir, ["add", "fork-main.txt"]); |
| 3029 | yield* runGit(repoDir, ["commit", "-m", "Fork main branch"]); | 3033 | yield* runGit(repoDir, ["commit", "-m", "Fork main branch"]); |
| 3030 | yield* runGit(repoDir, ["push", "-u", "fork-seed", "fork-main-source:main"]); | 3034 | yield* runGit(repoDir, ["push", "-u", "fork-seed", "fork-main-source:main"]); |
| ... | @@ -3084,7 +3088,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -3084,7 +3088,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 3084 | yield* runGit(repoDir, ["push", "-u", "origin", "main"]); | 3088 | yield* runGit(repoDir, ["push", "-u", "origin", "main"]); |
| 3085 | yield* runGit(repoDir, ["remote", "add", "fork-seed", forkDir]); | 3089 | yield* runGit(repoDir, ["remote", "add", "fork-seed", forkDir]); |
| 3086 | yield* runGit(repoDir, ["checkout", "-b", "fork-main-source"]); | 3090 | yield* runGit(repoDir, ["checkout", "-b", "fork-main-source"]); |
| 3087 | fs.writeFileSync(path.join(repoDir, "fork-main-second.txt"), "fork main second\n"); | 3091 | NodeFS.writeFileSync(NodePath.join(repoDir, "fork-main-second.txt"), "fork main second\n"); |
| 3088 | yield* runGit(repoDir, ["add", "fork-main-second.txt"]); | 3092 | yield* runGit(repoDir, ["add", "fork-main-second.txt"]); |
| 3089 | yield* runGit(repoDir, ["commit", "-m", "Fork main second branch"]); | 3093 | yield* runGit(repoDir, ["commit", "-m", "Fork main second branch"]); |
| 3090 | yield* runGit(repoDir, ["push", "-u", "fork-seed", "fork-main-source:main"]); | 3094 | yield* runGit(repoDir, ["push", "-u", "fork-seed", "fork-main-source:main"]); |
| ... | @@ -3142,12 +3146,16 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -3142,12 +3146,16 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 3142 | yield* runGit(repoDir, ["push", "-u", "origin", "main"]); | 3146 | yield* runGit(repoDir, ["push", "-u", "origin", "main"]); |
| 3143 | yield* runGit(repoDir, ["remote", "add", "fork-seed", forkDir]); | 3147 | yield* runGit(repoDir, ["remote", "add", "fork-seed", forkDir]); |
| 3144 | yield* runGit(repoDir, ["checkout", "-b", "feature/pr-reused-fork"]); | 3148 | yield* runGit(repoDir, ["checkout", "-b", "feature/pr-reused-fork"]); |
| 3145 | fs.writeFileSync(path.join(repoDir, "reused-fork.txt"), "reused fork\n"); | 3149 | NodeFS.writeFileSync(NodePath.join(repoDir, "reused-fork.txt"), "reused fork\n"); |
| 3146 | yield* runGit(repoDir, ["add", "reused-fork.txt"]); | 3150 | yield* runGit(repoDir, ["add", "reused-fork.txt"]); |
| 3147 | yield* runGit(repoDir, ["commit", "-m", "Reused fork PR branch"]); | 3151 | yield* runGit(repoDir, ["commit", "-m", "Reused fork PR branch"]); |
| 3148 | yield* runGit(repoDir, ["push", "-u", "fork-seed", "feature/pr-reused-fork"]); | 3152 | yield* runGit(repoDir, ["push", "-u", "fork-seed", "feature/pr-reused-fork"]); |
| 3149 | yield* runGit(repoDir, ["checkout", "main"]); | 3153 | yield* runGit(repoDir, ["checkout", "main"]); |
| 3150 | const worktreePath = path.join(repoDir, "..", `pr-reused-fork-${path.basename(repoDir)}`); | 3154 | const worktreePath = NodePath.join( |
| 3155 | repoDir, | ||
| 3156 | "..", | ||
| 3157 | `pr-reused-fork-${NodePath.basename(repoDir)}`, | ||
| 3158 | ); | ||
| 3151 | yield* runGit(repoDir, ["worktree", "add", worktreePath, "feature/pr-reused-fork"]); | 3159 | yield* runGit(repoDir, ["worktree", "add", worktreePath, "feature/pr-reused-fork"]); |
| 3152 | yield* runGit(worktreePath, ["branch", "--unset-upstream"], true); | 3160 | yield* runGit(worktreePath, ["branch", "--unset-upstream"], true); |
| 3153 | 3161 | ||
| ... | @@ -3179,8 +3187,8 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -3179,8 +3187,8 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 3179 | mode: "worktree", | 3187 | mode: "worktree", |
| 3180 | }); | 3188 | }); |
| 3181 | 3189 | ||
| 3182 | expect(result.worktreePath && fs.realpathSync.native(result.worktreePath)).toBe( | 3190 | expect(result.worktreePath && NodeFS.realpathSync.native(result.worktreePath)).toBe( |
| 3183 | fs.realpathSync.native(worktreePath), | 3191 | NodeFS.realpathSync.native(worktreePath), |
| 3184 | ); | 3192 | ); |
| 3185 | expect( | 3193 | expect( |
| 3186 | (yield* runGit(worktreePath, ["rev-parse", "--abbrev-ref", "@{upstream}"])).stdout.trim(), | 3194 | (yield* runGit(worktreePath, ["rev-parse", "--abbrev-ref", "@{upstream}"])).stdout.trim(), |
| ... | @@ -3196,7 +3204,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -3196,7 +3204,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 3196 | yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); | 3204 | yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); |
| 3197 | yield* runGit(repoDir, ["push", "-u", "origin", "main"]); | 3205 | yield* runGit(repoDir, ["push", "-u", "origin", "main"]); |
| 3198 | yield* runGit(repoDir, ["checkout", "-b", "feature/pr-setup-failure"]); | 3206 | yield* runGit(repoDir, ["checkout", "-b", "feature/pr-setup-failure"]); |
| 3199 | fs.writeFileSync(path.join(repoDir, "setup-failure.txt"), "setup failure\n"); | 3207 | NodeFS.writeFileSync(NodePath.join(repoDir, "setup-failure.txt"), "setup failure\n"); |
| 3200 | yield* runGit(repoDir, ["add", "setup-failure.txt"]); | 3208 | yield* runGit(repoDir, ["add", "setup-failure.txt"]); |
| 3201 | yield* runGit(repoDir, ["commit", "-m", "PR setup failure branch"]); | 3209 | yield* runGit(repoDir, ["commit", "-m", "PR setup failure branch"]); |
| 3202 | yield* runGit(repoDir, ["push", "-u", "origin", "feature/pr-setup-failure"]); | 3210 | yield* runGit(repoDir, ["push", "-u", "origin", "feature/pr-setup-failure"]); |
| ... | @@ -3236,7 +3244,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -3236,7 +3244,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 3236 | 3244 | ||
| 3237 | expect(result.branch).toBe("feature/pr-setup-failure"); | 3245 | expect(result.branch).toBe("feature/pr-setup-failure"); |
| 3238 | expect(result.worktreePath).not.toBeNull(); | 3246 | expect(result.worktreePath).not.toBeNull(); |
| 3239 | expect(fs.existsSync(result.worktreePath as string)).toBe(true); | 3247 | expect(NodeFS.existsSync(result.worktreePath as string)).toBe(true); |
| 3240 | }), | 3248 | }), |
| 3241 | ); | 3249 | ); |
| 3242 | 3250 | ||
| ... | @@ -3276,9 +3284,9 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -3276,9 +3284,9 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 3276 | Effect.gen(function* () { | 3284 | Effect.gen(function* () { |
| 3277 | const repoDir = yield* makeTempDir("t3code-git-manager-"); | 3285 | const repoDir = yield* makeTempDir("t3code-git-manager-"); |
| 3278 | yield* initRepo(repoDir); | 3286 | yield* initRepo(repoDir); |
| 3279 | fs.writeFileSync(path.join(repoDir, "hooked.txt"), "hooked\n"); | 3287 | NodeFS.writeFileSync(NodePath.join(repoDir, "hooked.txt"), "hooked\n"); |
| 3280 | fs.writeFileSync( | 3288 | NodeFS.writeFileSync( |
| 3281 | path.join(repoDir, ".git", "hooks", "pre-commit"), | 3289 | NodePath.join(repoDir, ".git", "hooks", "pre-commit"), |
| 3282 | '#!/bin/sh\necho "hook: start" >&2\nsleep 0.05\necho "hook: end" >&2\n', | 3290 | '#!/bin/sh\necho "hook: start" >&2\nsleep 0.05\necho "hook: end" >&2\n', |
| 3283 | { mode: 0o755 }, | 3291 | { mode: 0o755 }, |
| 3284 | ); | 3292 | ); |
| ... | @@ -3339,9 +3347,9 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -3339,9 +3347,9 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 3339 | Effect.gen(function* () { | 3347 | Effect.gen(function* () { |
| 3340 | const repoDir = yield* makeTempDir("t3code-git-manager-"); | 3348 | const repoDir = yield* makeTempDir("t3code-git-manager-"); |
| 3341 | yield* initRepo(repoDir); | 3349 | yield* initRepo(repoDir); |
| 3342 | fs.writeFileSync(path.join(repoDir, "hook-failure.txt"), "broken\n"); | 3350 | NodeFS.writeFileSync(NodePath.join(repoDir, "hook-failure.txt"), "broken\n"); |
| 3343 | fs.writeFileSync( | 3351 | NodeFS.writeFileSync( |
| 3344 | path.join(repoDir, ".git", "hooks", "pre-commit"), | 3352 | NodePath.join(repoDir, ".git", "hooks", "pre-commit"), |
| 3345 | '#!/bin/sh\necho "hook: fail" >&2\nexit 1\n', | 3353 | '#!/bin/sh\necho "hook: fail" >&2\nexit 1\n', |
| 3346 | { mode: 0o755 }, | 3354 | { mode: 0o755 }, |
| 3347 | ); | 3355 | ); |
| ... | @@ -3392,7 +3400,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -3392,7 +3400,7 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 3392 | yield* runGit(repoDir, ["checkout", "-b", "feature/pr-only-follow-up"]); | 3400 | yield* runGit(repoDir, ["checkout", "-b", "feature/pr-only-follow-up"]); |
| 3393 | const remoteDir = yield* createBareRemote(); | 3401 | const remoteDir = yield* createBareRemote(); |
| 3394 | yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); | 3402 | yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); |
| 3395 | fs.writeFileSync(path.join(repoDir, "pr-only.txt"), "pr only\n"); | 3403 | NodeFS.writeFileSync(NodePath.join(repoDir, "pr-only.txt"), "pr only\n"); |
| 3396 | yield* runGit(repoDir, ["add", "pr-only.txt"]); | 3404 | yield* runGit(repoDir, ["add", "pr-only.txt"]); |
| 3397 | yield* runGit(repoDir, ["commit", "-m", "PR only branch"]); | 3405 | yield* runGit(repoDir, ["commit", "-m", "PR only branch"]); |
| 3398 | yield* runGit(repoDir, ["push", "-u", "origin", "feature/pr-only-follow-up"]); | 3406 | yield* runGit(repoDir, ["push", "-u", "origin", "feature/pr-only-follow-up"]); |
apps/server/src/git/Utils.ts+3-3| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off | 1 | // @effect-diagnostics nodeBuiltinImport:off |
| 2 | import { existsSync } from "node:fs"; | 2 | import * as NodeFS from "node:fs"; |
| 3 | import { join } from "node:path"; | 3 | import * as NodePath from "node:path"; |
| 4 | 4 | ||
| 5 | export function isGitRepository(cwd: string): boolean { | 5 | export function isGitRepository(cwd: string): boolean { |
| 6 | return existsSync(join(cwd, ".git")); | 6 | return NodeFS.existsSync(NodePath.join(cwd, ".git")); |
| 7 | } | 7 | } |
apps/server/src/orchestration/Layers/CheckpointReactor.test.ts+17-17| ... | @@ -1,8 +1,8 @@ | ... | @@ -1,8 +1,8 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off | 1 | // @effect-diagnostics nodeBuiltinImport:off |
| 2 | import fs from "node:fs"; | 2 | import * as NodeFS from "node:fs"; |
| 3 | import os from "node:os"; | 3 | import * as NodeOS from "node:os"; |
| 4 | import path from "node:path"; | 4 | import * as NodePath from "node:path"; |
| 5 | import { execFileSync } from "node:child_process"; | 5 | import * as NodeChildProcess from "node:child_process"; |
| 6 | 6 | ||
| 7 | import { | 7 | import { |
| 8 | ProviderDriverKind, | 8 | ProviderDriverKind, |
| ... | @@ -198,7 +198,7 @@ async function waitForEvent( | ... | @@ -198,7 +198,7 @@ async function waitForEvent( |
| 198 | } | 198 | } |
| 199 | 199 | ||
| 200 | function runGit(cwd: string, args: ReadonlyArray<string>) { | 200 | function runGit(cwd: string, args: ReadonlyArray<string>) { |
| 201 | return execFileSync("git", args, { | 201 | return NodeChildProcess.execFileSync("git", args, { |
| 202 | cwd, | 202 | cwd, |
| 203 | stdio: ["ignore", "pipe", "pipe"], | 203 | stdio: ["ignore", "pipe", "pipe"], |
| 204 | encoding: "utf8", | 204 | encoding: "utf8", |
| ... | @@ -206,11 +206,11 @@ function runGit(cwd: string, args: ReadonlyArray<string>) { | ... | @@ -206,11 +206,11 @@ function runGit(cwd: string, args: ReadonlyArray<string>) { |
| 206 | } | 206 | } |
| 207 | 207 | ||
| 208 | function createGitRepository() { | 208 | function createGitRepository() { |
| 209 | const cwd = fs.mkdtempSync(path.join(os.tmpdir(), "t3-checkpoint-handler-")); | 209 | const cwd = NodeFS.mkdtempSync(NodePath.join(NodeOS.tmpdir(), "t3-checkpoint-handler-")); |
| 210 | runGit(cwd, ["init", "--initial-branch=main"]); | 210 | runGit(cwd, ["init", "--initial-branch=main"]); |
| 211 | runGit(cwd, ["config", "user.email", "test@example.com"]); | 211 | runGit(cwd, ["config", "user.email", "test@example.com"]); |
| 212 | runGit(cwd, ["config", "user.name", "Test User"]); | 212 | runGit(cwd, ["config", "user.name", "Test User"]); |
| 213 | fs.writeFileSync(path.join(cwd, "README.md"), "v1\n", "utf8"); | 213 | NodeFS.writeFileSync(NodePath.join(cwd, "README.md"), "v1\n", "utf8"); |
| 214 | runGit(cwd, ["add", "."]); | 214 | runGit(cwd, ["add", "."]); |
| 215 | runGit(cwd, ["commit", "-m", "Initial"]); | 215 | runGit(cwd, ["commit", "-m", "Initial"]); |
| 216 | return cwd; | 216 | return cwd; |
| ... | @@ -267,7 +267,7 @@ describe("CheckpointReactor", () => { | ... | @@ -267,7 +267,7 @@ describe("CheckpointReactor", () => { |
| 267 | while (tempDirs.length > 0) { | 267 | while (tempDirs.length > 0) { |
| 268 | const dir = tempDirs.pop(); | 268 | const dir = tempDirs.pop(); |
| 269 | if (dir) { | 269 | if (dir) { |
| 270 | fs.rmSync(dir, { recursive: true, force: true }); | 270 | NodeFS.rmSync(dir, { recursive: true, force: true }); |
| 271 | } | 271 | } |
| 272 | } | 272 | } |
| 273 | }); | 273 | }); |
| ... | @@ -395,14 +395,14 @@ describe("CheckpointReactor", () => { | ... | @@ -395,14 +395,14 @@ describe("CheckpointReactor", () => { |
| 395 | checkpointRef: checkpointRefForThreadTurn(ThreadId.make("thread-1"), 0), | 395 | checkpointRef: checkpointRefForThreadTurn(ThreadId.make("thread-1"), 0), |
| 396 | }), | 396 | }), |
| 397 | ); | 397 | ); |
| 398 | fs.writeFileSync(path.join(cwd, "README.md"), "v2\n", "utf8"); | 398 | NodeFS.writeFileSync(NodePath.join(cwd, "README.md"), "v2\n", "utf8"); |
| 399 | await runtime.runPromise( | 399 | await runtime.runPromise( |
| 400 | checkpointStore.captureCheckpoint({ | 400 | checkpointStore.captureCheckpoint({ |
| 401 | cwd, | 401 | cwd, |
| 402 | checkpointRef: checkpointRefForThreadTurn(ThreadId.make("thread-1"), 1), | 402 | checkpointRef: checkpointRefForThreadTurn(ThreadId.make("thread-1"), 1), |
| 403 | }), | 403 | }), |
| 404 | ); | 404 | ); |
| 405 | fs.writeFileSync(path.join(cwd, "README.md"), "v3\n", "utf8"); | 405 | NodeFS.writeFileSync(NodePath.join(cwd, "README.md"), "v3\n", "utf8"); |
| 406 | await runtime.runPromise( | 406 | await runtime.runPromise( |
| 407 | checkpointStore.captureCheckpoint({ | 407 | checkpointStore.captureCheckpoint({ |
| 408 | cwd, | 408 | cwd, |
| ... | @@ -456,7 +456,7 @@ describe("CheckpointReactor", () => { | ... | @@ -456,7 +456,7 @@ describe("CheckpointReactor", () => { |
| 456 | checkpointRefForThreadTurn(ThreadId.make("thread-1"), 0), | 456 | checkpointRefForThreadTurn(ThreadId.make("thread-1"), 0), |
| 457 | ); | 457 | ); |
| 458 | 458 | ||
| 459 | fs.writeFileSync(path.join(harness.cwd, "README.md"), "v2\n", "utf8"); | 459 | NodeFS.writeFileSync(NodePath.join(harness.cwd, "README.md"), "v2\n", "utf8"); |
| 460 | harness.provider.emit({ | 460 | harness.provider.emit({ |
| 461 | type: "turn.completed", | 461 | type: "turn.completed", |
| 462 | eventId: EventId.make("evt-turn-completed-1"), | 462 | eventId: EventId.make("evt-turn-completed-1"), |
| ... | @@ -554,7 +554,7 @@ describe("CheckpointReactor", () => { | ... | @@ -554,7 +554,7 @@ describe("CheckpointReactor", () => { |
| 554 | checkpointRefForThreadTurn(ThreadId.make("thread-1"), 0), | 554 | checkpointRefForThreadTurn(ThreadId.make("thread-1"), 0), |
| 555 | ); | 555 | ); |
| 556 | 556 | ||
| 557 | fs.writeFileSync(path.join(harness.cwd, "README.md"), "v2\n", "utf8"); | 557 | NodeFS.writeFileSync(NodePath.join(harness.cwd, "README.md"), "v2\n", "utf8"); |
| 558 | 558 | ||
| 559 | harness.provider.emit({ | 559 | harness.provider.emit({ |
| 560 | type: "turn.completed", | 560 | type: "turn.completed", |
| ... | @@ -628,7 +628,7 @@ describe("CheckpointReactor", () => { | ... | @@ -628,7 +628,7 @@ describe("CheckpointReactor", () => { |
| 628 | checkpointRefForThreadTurn(ThreadId.make("thread-1"), 0), | 628 | checkpointRefForThreadTurn(ThreadId.make("thread-1"), 0), |
| 629 | ); | 629 | ); |
| 630 | 630 | ||
| 631 | fs.writeFileSync(path.join(harness.cwd, "README.md"), "v2\n", "utf8"); | 631 | NodeFS.writeFileSync(NodePath.join(harness.cwd, "README.md"), "v2\n", "utf8"); |
| 632 | harness.provider.emit({ | 632 | harness.provider.emit({ |
| 633 | type: "turn.completed", | 633 | type: "turn.completed", |
| 634 | eventId: EventId.make("evt-turn-completed-claude-1"), | 634 | eventId: EventId.make("evt-turn-completed-claude-1"), |
| ... | @@ -761,7 +761,7 @@ describe("CheckpointReactor", () => { | ... | @@ -761,7 +761,7 @@ describe("CheckpointReactor", () => { |
| 761 | }), | 761 | }), |
| 762 | ); | 762 | ); |
| 763 | 763 | ||
| 764 | fs.writeFileSync(path.join(harness.cwd, "README.md"), "v2\n", "utf8"); | 764 | NodeFS.writeFileSync(NodePath.join(harness.cwd, "README.md"), "v2\n", "utf8"); |
| 765 | harness.provider.emit({ | 765 | harness.provider.emit({ |
| 766 | type: "turn.completed", | 766 | type: "turn.completed", |
| 767 | eventId: EventId.make("evt-turn-completed-missing-provider-cwd"), | 767 | eventId: EventId.make("evt-turn-completed-missing-provider-cwd"), |
| ... | @@ -829,8 +829,8 @@ describe("CheckpointReactor", () => { | ... | @@ -829,8 +829,8 @@ describe("CheckpointReactor", () => { |
| 829 | }); | 829 | }); |
| 830 | 830 | ||
| 831 | it("continues processing runtime events after a single checkpoint runtime failure", async () => { | 831 | it("continues processing runtime events after a single checkpoint runtime failure", async () => { |
| 832 | const nonRepositorySessionCwd = fs.mkdtempSync( | 832 | const nonRepositorySessionCwd = NodeFS.mkdtempSync( |
| 833 | path.join(os.tmpdir(), "t3-checkpoint-runtime-non-repo-"), | 833 | NodePath.join(NodeOS.tmpdir(), "t3-checkpoint-runtime-non-repo-"), |
| 834 | ); | 834 | ); |
| 835 | tempDirs.push(nonRepositorySessionCwd); | 835 | tempDirs.push(nonRepositorySessionCwd); |
| 836 | 836 | ||
| ... | @@ -963,7 +963,7 @@ describe("CheckpointReactor", () => { | ... | @@ -963,7 +963,7 @@ describe("CheckpointReactor", () => { |
| 963 | threadId: ThreadId.make("thread-1"), | 963 | threadId: ThreadId.make("thread-1"), |
| 964 | numTurns: 1, | 964 | numTurns: 1, |
| 965 | }); | 965 | }); |
| 966 | expect(fs.readFileSync(path.join(harness.cwd, "README.md"), "utf8")).toBe("v2\n"); | 966 | expect(NodeFS.readFileSync(NodePath.join(harness.cwd, "README.md"), "utf8")).toBe("v2\n"); |
| 967 | expect( | 967 | expect( |
| 968 | gitRefExists(harness.cwd, checkpointRefForThreadTurn(ThreadId.make("thread-1"), 2)), | 968 | gitRefExists(harness.cwd, checkpointRefForThreadTurn(ThreadId.make("thread-1"), 2)), |
| 969 | ).toBe(false); | 969 | ).toBe(false); |
apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts+7-6| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off | 1 | // @effect-diagnostics nodeBuiltinImport:off |
| 2 | import fs from "node:fs"; | 2 | import * as NodeFS from "node:fs"; |
| 3 | import os from "node:os"; | 3 | import * as NodeOS from "node:os"; |
| 4 | import path from "node:path"; | 4 | import * as NodePath from "node:path"; |
| 5 | 5 | ||
| 6 | import { | 6 | import { |
| 7 | ModelSelection, | 7 | ModelSelection, |
| ... | @@ -107,11 +107,11 @@ describe("ProviderCommandReactor", () => { | ... | @@ -107,11 +107,11 @@ describe("ProviderCommandReactor", () => { |
| 107 | } | 107 | } |
| 108 | runtime = null; | 108 | runtime = null; |
| 109 | for (const stateDir of createdStateDirs) { | 109 | for (const stateDir of createdStateDirs) { |
| 110 | fs.rmSync(stateDir, { recursive: true, force: true }); | 110 | NodeFS.rmSync(stateDir, { recursive: true, force: true }); |
| 111 | } | 111 | } |
| 112 | createdStateDirs.clear(); | 112 | createdStateDirs.clear(); |
| 113 | for (const baseDir of createdBaseDirs) { | 113 | for (const baseDir of createdBaseDirs) { |
| 114 | fs.rmSync(baseDir, { recursive: true, force: true }); | 114 | NodeFS.rmSync(baseDir, { recursive: true, force: true }); |
| 115 | } | 115 | } |
| 116 | createdBaseDirs.clear(); | 116 | createdBaseDirs.clear(); |
| 117 | }); | 117 | }); |
| ... | @@ -147,7 +147,8 @@ describe("ProviderCommandReactor", () => { | ... | @@ -147,7 +147,8 @@ describe("ProviderCommandReactor", () => { |
| 147 | readonly requiresNewThreadForModelChange?: boolean; | 147 | readonly requiresNewThreadForModelChange?: boolean; |
| 148 | }) { | 148 | }) { |
| 149 | const now = "2026-01-01T00:00:00.000Z"; | 149 | const now = "2026-01-01T00:00:00.000Z"; |
| 150 | const baseDir = input?.baseDir ?? fs.mkdtempSync(path.join(os.tmpdir(), "t3code-reactor-")); | 150 | const baseDir = |
| 151 | input?.baseDir ?? NodeFS.mkdtempSync(NodePath.join(NodeOS.tmpdir(), "t3code-reactor-")); | ||
| 151 | createdBaseDirs.add(baseDir); | 152 | createdBaseDirs.add(baseDir); |
| 152 | const { stateDir } = deriveServerPathsSync(baseDir, undefined); | 153 | const { stateDir } = deriveServerPathsSync(baseDir, undefined); |
| 153 | createdStateDirs.add(stateDir); | 154 | createdStateDirs.add(stateDir); |
apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.test.ts+6-6| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off | 1 | // @effect-diagnostics nodeBuiltinImport:off |
| 2 | import fs from "node:fs"; | 2 | import * as NodeFS from "node:fs"; |
| 3 | import os from "node:os"; | 3 | import * as NodeOS from "node:os"; |
| 4 | import path from "node:path"; | 4 | import * as NodePath from "node:path"; |
| 5 | 5 | ||
| 6 | import { | 6 | import { |
| 7 | OrchestrationReadModel, | 7 | OrchestrationReadModel, |
| ... | @@ -198,7 +198,7 @@ describe("ProviderRuntimeIngestion", () => { | ... | @@ -198,7 +198,7 @@ describe("ProviderRuntimeIngestion", () => { |
| 198 | const tempDirs: string[] = []; | 198 | const tempDirs: string[] = []; |
| 199 | 199 | ||
| 200 | function makeTempDir(prefix: string): string { | 200 | function makeTempDir(prefix: string): string { |
| 201 | const dir = fs.mkdtempSync(path.join(os.tmpdir(), prefix)); | 201 | const dir = NodeFS.mkdtempSync(NodePath.join(NodeOS.tmpdir(), prefix)); |
| 202 | tempDirs.push(dir); | 202 | tempDirs.push(dir); |
| 203 | return dir; | 203 | return dir; |
| 204 | } | 204 | } |
| ... | @@ -213,13 +213,13 @@ describe("ProviderRuntimeIngestion", () => { | ... | @@ -213,13 +213,13 @@ describe("ProviderRuntimeIngestion", () => { |
| 213 | } | 213 | } |
| 214 | runtime = null; | 214 | runtime = null; |
| 215 | for (const dir of tempDirs.splice(0)) { | 215 | for (const dir of tempDirs.splice(0)) { |
| 216 | fs.rmSync(dir, { recursive: true, force: true }); | 216 | NodeFS.rmSync(dir, { recursive: true, force: true }); |
| 217 | } | 217 | } |
| 218 | }); | 218 | }); |
| 219 | 219 | ||
| 220 | async function createHarness(options?: { serverSettings?: Partial<ServerSettings> }) { | 220 | async function createHarness(options?: { serverSettings?: Partial<ServerSettings> }) { |
| 221 | const workspaceRoot = makeTempDir("t3-provider-project-"); | 221 | const workspaceRoot = makeTempDir("t3-provider-project-"); |
| 222 | fs.mkdirSync(path.join(workspaceRoot, ".git")); | 222 | NodeFS.mkdirSync(NodePath.join(workspaceRoot, ".git")); |
| 223 | const provider = createProviderServiceHarness(); | 223 | const provider = createProviderServiceHarness(); |
| 224 | const orchestrationLayer = OrchestrationEngineLive.pipe( | 224 | const orchestrationLayer = OrchestrationEngineLive.pipe( |
| 225 | Layer.provide(OrchestrationProjectionSnapshotQueryLive), | 225 | Layer.provide(OrchestrationProjectionSnapshotQueryLive), |
apps/server/src/pathExpansion.test.ts+5-5| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off | 1 | // @effect-diagnostics nodeBuiltinImport:off |
| 2 | import { homedir } from "node:os"; | 2 | import * as NodeOS from "node:os"; |
| 3 | import { join } from "node:path"; | 3 | import * as NodePath from "node:path"; |
| 4 | import { describe, expect, it } from "vite-plus/test"; | 4 | import { describe, expect, it } from "vite-plus/test"; |
| 5 | 5 | ||
| 6 | import { expandHomePath } from "./pathExpansion.ts"; | 6 | import { expandHomePath } from "./pathExpansion.ts"; |
| ... | @@ -17,15 +17,15 @@ describe("expandHomePath", () => { | ... | @@ -17,15 +17,15 @@ describe("expandHomePath", () => { |
| 17 | }); | 17 | }); |
| 18 | 18 | ||
| 19 | it("expands a lone tilde to the home directory", () => { | 19 | it("expands a lone tilde to the home directory", () => { |
| 20 | expect(expandHomePath("~")).toBe(homedir()); | 20 | expect(expandHomePath("~")).toBe(NodeOS.homedir()); |
| 21 | }); | 21 | }); |
| 22 | 22 | ||
| 23 | it("expands ~/ to a subpath of the home directory", () => { | 23 | it("expands ~/ to a subpath of the home directory", () => { |
| 24 | expect(expandHomePath("~/.codex-work")).toBe(join(homedir(), ".codex-work")); | 24 | expect(expandHomePath("~/.codex-work")).toBe(NodePath.join(NodeOS.homedir(), ".codex-work")); |
| 25 | }); | 25 | }); |
| 26 | 26 | ||
| 27 | it("expands a Windows-style ~\\ prefix", () => { | 27 | it("expands a Windows-style ~\\ prefix", () => { |
| 28 | expect(expandHomePath("~\\.codex")).toBe(join(homedir(), ".codex")); | 28 | expect(expandHomePath("~\\.codex")).toBe(NodePath.join(NodeOS.homedir(), ".codex")); |
| 29 | }); | 29 | }); |
| 30 | 30 | ||
| 31 | it("does not expand ~user paths", () => { | 31 | it("does not expand ~user paths", () => { |
apps/server/src/pathExpansion.ts+4-4| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off | 1 | // @effect-diagnostics nodeBuiltinImport:off |
| 2 | import { homedir } from "node:os"; | 2 | import * as NodeOS from "node:os"; |
| 3 | import { join } from "node:path"; | 3 | import * as NodePath from "node:path"; |
| 4 | 4 | ||
| 5 | /** | 5 | /** |
| 6 | * Expand a leading `~` (or `~/…`, `~\…`) in a user-supplied path to the | 6 | * Expand a leading `~` (or `~/…`, `~\…`) in a user-supplied path to the |
| ... | @@ -16,9 +16,9 @@ import { join } from "node:path"; | ... | @@ -16,9 +16,9 @@ import { join } from "node:path"; |
| 16 | */ | 16 | */ |
| 17 | export function expandHomePath(value: string): string { | 17 | export function expandHomePath(value: string): string { |
| 18 | if (!value) return value; | 18 | if (!value) return value; |
| 19 | if (value === "~") return homedir(); | 19 | if (value === "~") return NodeOS.homedir(); |
| 20 | if (value.startsWith("~/") || value.startsWith("~\\")) { | 20 | if (value.startsWith("~/") || value.startsWith("~\\")) { |
| 21 | return join(homedir(), value.slice(2)); | 21 | return NodePath.join(NodeOS.homedir(), value.slice(2)); |
| 22 | } | 22 | } |
| 23 | return value; | 23 | return value; |
| 24 | } | 24 | } |
apps/server/src/persistence/NodeSqliteClient.ts+11-7| ... | @@ -4,7 +4,7 @@ | ... | @@ -4,7 +4,7 @@ |
| 4 | * | 4 | * |
| 5 | * @module SqliteClient | 5 | * @module SqliteClient |
| 6 | */ | 6 | */ |
| 7 | import { DatabaseSync, type StatementSync } from "node:sqlite"; | 7 | import * as NodeSqlite from "node:sqlite"; |
| 8 | 8 | ||
| 9 | import * as Cache from "effect/Cache"; | 9 | import * as Cache from "effect/Cache"; |
| 10 | import * as Config from "effect/Config"; | 10 | import * as Config from "effect/Config"; |
| ... | @@ -69,7 +69,7 @@ const checkNodeSqliteCompat = () => { | ... | @@ -69,7 +69,7 @@ const checkNodeSqliteCompat = () => { |
| 69 | 69 | ||
| 70 | const makeWithDatabase = Effect.fn("makeWithDatabase")(function* ( | 70 | const makeWithDatabase = Effect.fn("makeWithDatabase")(function* ( |
| 71 | options: SqliteClientConfig, | 71 | options: SqliteClientConfig, |
| 72 | openDatabase: () => DatabaseSync, | 72 | openDatabase: () => NodeSqlite.DatabaseSync, |
| 73 | ): Effect.fn.Return<Client.SqlClient, never, Scope.Scope | Reactivity.Reactivity> { | 73 | ): Effect.fn.Return<Client.SqlClient, never, Scope.Scope | Reactivity.Reactivity> { |
| 74 | yield* checkNodeSqliteCompat(); | 74 | yield* checkNodeSqliteCompat(); |
| 75 | 75 | ||
| ... | @@ -86,8 +86,8 @@ const makeWithDatabase = Effect.fn("makeWithDatabase")(function* ( | ... | @@ -86,8 +86,8 @@ const makeWithDatabase = Effect.fn("makeWithDatabase")(function* ( |
| 86 | Effect.sync(() => db.close()), | 86 | Effect.sync(() => db.close()), |
| 87 | ); | 87 | ); |
| 88 | 88 | ||
| 89 | const statementReaderCache = new WeakMap<StatementSync, boolean>(); | 89 | const statementReaderCache = new WeakMap<NodeSqlite.StatementSync, boolean>(); |
| 90 | const hasRows = (statement: StatementSync): boolean => { | 90 | const hasRows = (statement: NodeSqlite.StatementSync): boolean => { |
| 91 | const cached = statementReaderCache.get(statement); | 91 | const cached = statementReaderCache.get(statement); |
| 92 | if (cached !== undefined) { | 92 | if (cached !== undefined) { |
| 93 | return cached; | 93 | return cached; |
| ... | @@ -113,7 +113,11 @@ const makeWithDatabase = Effect.fn("makeWithDatabase")(function* ( | ... | @@ -113,7 +113,11 @@ const makeWithDatabase = Effect.fn("makeWithDatabase")(function* ( |
| 113 | }), | 113 | }), |
| 114 | }); | 114 | }); |
| 115 | 115 | ||
| 116 | const runStatement = (statement: StatementSync, params: ReadonlyArray<unknown>, raw: boolean) => | 116 | const runStatement = ( |
| 117 | statement: NodeSqlite.StatementSync, | ||
| 118 | params: ReadonlyArray<unknown>, | ||
| 119 | raw: boolean, | ||
| 120 | ) => | ||
| 117 | Effect.withFiber<ReadonlyArray<any>, SqlError>((fiber) => { | 121 | Effect.withFiber<ReadonlyArray<any>, SqlError>((fiber) => { |
| 118 | statement.setReadBigInts(Boolean(Context.get(fiber.context, Client.SafeIntegers))); | 122 | statement.setReadBigInts(Boolean(Context.get(fiber.context, Client.SafeIntegers))); |
| 119 | try { | 123 | try { |
| ... | @@ -220,7 +224,7 @@ const make = ( | ... | @@ -220,7 +224,7 @@ const make = ( |
| 220 | makeWithDatabase( | 224 | makeWithDatabase( |
| 221 | options, | 225 | options, |
| 222 | () => | 226 | () => |
| 223 | new DatabaseSync(options.filename, { | 227 | new NodeSqlite.DatabaseSync(options.filename, { |
| 224 | readOnly: options.readonly ?? false, | 228 | readOnly: options.readonly ?? false, |
| 225 | allowExtension: options.allowExtension ?? false, | 229 | allowExtension: options.allowExtension ?? false, |
| 226 | }), | 230 | }), |
| ... | @@ -236,7 +240,7 @@ const makeMemory = ( | ... | @@ -236,7 +240,7 @@ const makeMemory = ( |
| 236 | readonly: false, | 240 | readonly: false, |
| 237 | }, | 241 | }, |
| 238 | () => { | 242 | () => { |
| 239 | const database = new DatabaseSync(":memory:", { | 243 | const database = new NodeSqlite.DatabaseSync(":memory:", { |
| 240 | allowExtension: config.allowExtension ?? false, | 244 | allowExtension: config.allowExtension ?? false, |
| 241 | }); | 245 | }); |
| 242 | return database; | 246 | return database; |
apps/server/src/preview/PortScanner.test.ts+4-4| ... | @@ -1,4 +1,4 @@ | ... | @@ -1,4 +1,4 @@ |
| 1 | import * as net from "node:net"; | 1 | import * as NodeNet from "node:net"; |
| 2 | 2 | ||
| 3 | import { it as effectIt } from "@effect/vitest"; | 3 | import { it as effectIt } from "@effect/vitest"; |
| 4 | import { HostProcessPlatform } from "@t3tools/shared/hostProcess"; | 4 | import { HostProcessPlatform } from "@t3tools/shared/hostProcess"; |
| ... | @@ -17,9 +17,9 @@ const TestPortDiscoveryLive = PortScanner.layer.pipe( | ... | @@ -17,9 +17,9 @@ const TestPortDiscoveryLive = PortScanner.layer.pipe( |
| 17 | ), | 17 | ), |
| 18 | ); | 18 | ); |
| 19 | 19 | ||
| 20 | const openServer = (port: number): Effect.Effect<net.Server | null> => | 20 | const openServer = (port: number): Effect.Effect<NodeNet.Server | null> => |
| 21 | Effect.callback((resume) => { | 21 | Effect.callback((resume) => { |
| 22 | const server = net.createServer(); | 22 | const server = NodeNet.createServer(); |
| 23 | server.once("error", () => { | 23 | server.once("error", () => { |
| 24 | resume(Effect.succeed(null)); | 24 | resume(Effect.succeed(null)); |
| 25 | }); | 25 | }); |
| ... | @@ -31,7 +31,7 @@ const openServer = (port: number): Effect.Effect<net.Server | null> => | ... | @@ -31,7 +31,7 @@ const openServer = (port: number): Effect.Effect<net.Server | null> => |
| 31 | }); | 31 | }); |
| 32 | }); | 32 | }); |
| 33 | 33 | ||
| 34 | const closeServer = (server: net.Server): Effect.Effect<void> => | 34 | const closeServer = (server: NodeNet.Server): Effect.Effect<void> => |
| 35 | Effect.callback((resume) => { | 35 | Effect.callback((resume) => { |
| 36 | server.close(() => resume(Effect.void)); | 36 | server.close(() => resume(Effect.void)); |
| 37 | }); | 37 | }); |
apps/server/src/provider/Layers/ClaudeAdapter.test.ts+9-9| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off | 1 | // @effect-diagnostics nodeBuiltinImport:off |
| 2 | import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs"; | 2 | import * as NodeFS from "node:fs"; |
| 3 | import os from "node:os"; | 3 | import * as NodeOS from "node:os"; |
| 4 | import path from "node:path"; | 4 | import * as NodePath from "node:path"; |
| 5 | 5 | ||
| 6 | import * as NodeServices from "@effect/platform-node/NodeServices"; | 6 | import * as NodeServices from "@effect/platform-node/NodeServices"; |
| 7 | import type { | 7 | import type { |
| ... | @@ -395,7 +395,7 @@ describe("ClaudeAdapterLive", () => { | ... | @@ -395,7 +395,7 @@ describe("ClaudeAdapterLive", () => { |
| 395 | }); | 395 | }); |
| 396 | 396 | ||
| 397 | const createInput = harness.getLastCreateQueryInput(); | 397 | const createInput = harness.getLastCreateQueryInput(); |
| 398 | assert.equal(createInput?.options.env?.HOME, path.join(os.homedir(), ".claude-work")); | 398 | assert.equal(createInput?.options.env?.HOME, NodePath.join(NodeOS.homedir(), ".claude-work")); |
| 399 | }).pipe( | 399 | }).pipe( |
| 400 | Effect.provideService(Random.Random, makeDeterministicRandomService()), | 400 | Effect.provideService(Random.Random, makeDeterministicRandomService()), |
| 401 | Effect.provide(harness.layer), | 401 | Effect.provide(harness.layer), |
| ... | @@ -649,7 +649,7 @@ describe("ClaudeAdapterLive", () => { | ... | @@ -649,7 +649,7 @@ describe("ClaudeAdapterLive", () => { |
| 649 | }); | 649 | }); |
| 650 | 650 | ||
| 651 | it.effect("embeds image attachments in Claude user messages", () => { | 651 | it.effect("embeds image attachments in Claude user messages", () => { |
| 652 | const baseDir = mkdtempSync(path.join(os.tmpdir(), "claude-attachments-")); | 652 | const baseDir = NodeFS.mkdtempSync(NodePath.join(NodeOS.tmpdir(), "claude-attachments-")); |
| 653 | const harness = makeHarness({ | 653 | const harness = makeHarness({ |
| 654 | cwd: "/tmp/project-claude-attachments", | 654 | cwd: "/tmp/project-claude-attachments", |
| 655 | baseDir, | 655 | baseDir, |
| ... | @@ -657,7 +657,7 @@ describe("ClaudeAdapterLive", () => { | ... | @@ -657,7 +657,7 @@ describe("ClaudeAdapterLive", () => { |
| 657 | return Effect.gen(function* () { | 657 | return Effect.gen(function* () { |
| 658 | yield* Effect.addFinalizer(() => | 658 | yield* Effect.addFinalizer(() => |
| 659 | Effect.sync(() => | 659 | Effect.sync(() => |
| 660 | rmSync(baseDir, { | 660 | NodeFS.rmSync(baseDir, { |
| 661 | recursive: true, | 661 | recursive: true, |
| 662 | force: true, | 662 | force: true, |
| 663 | }), | 663 | }), |
| ... | @@ -674,9 +674,9 @@ describe("ClaudeAdapterLive", () => { | ... | @@ -674,9 +674,9 @@ describe("ClaudeAdapterLive", () => { |
| 674 | mimeType: "image/png", | 674 | mimeType: "image/png", |
| 675 | sizeBytes: 4, | 675 | sizeBytes: 4, |
| 676 | }; | 676 | }; |
| 677 | const attachmentPath = path.join(attachmentsDir, attachmentRelativePath(attachment)); | 677 | const attachmentPath = NodePath.join(attachmentsDir, attachmentRelativePath(attachment)); |
| 678 | mkdirSync(path.dirname(attachmentPath), { recursive: true }); | 678 | NodeFS.mkdirSync(NodePath.dirname(attachmentPath), { recursive: true }); |
| 679 | writeFileSync(attachmentPath, Uint8Array.from([1, 2, 3, 4])); | 679 | NodeFS.writeFileSync(attachmentPath, Uint8Array.from([1, 2, 3, 4])); |
| 680 | 680 | ||
| 681 | const session = yield* adapter.startSession({ | 681 | const session = yield* adapter.startSession({ |
| 682 | threadId: THREAD_ID, | 682 | threadId: THREAD_ID, |
apps/server/src/provider/Layers/CodexAdapter.test.ts+98-96| ... | @@ -1,8 +1,8 @@ | ... | @@ -1,8 +1,8 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off | 1 | // @effect-diagnostics nodeBuiltinImport:off |
| 2 | import assert from "node:assert/strict"; | 2 | import * as NodeAssert from "node:assert/strict"; |
| 3 | import fs from "node:fs"; | 3 | import * as NodeFS from "node:fs"; |
| 4 | import os from "node:os"; | 4 | import * as NodeOS from "node:os"; |
| 5 | import path from "node:path"; | 5 | import * as NodePath from "node:path"; |
| 6 | import { | 6 | import { |
| 7 | ApprovalRequestId, | 7 | ApprovalRequestId, |
| 8 | CodexSettings, | 8 | CodexSettings, |
| ... | @@ -250,8 +250,8 @@ validationLayer("CodexAdapterLive validation", (it) => { | ... | @@ -250,8 +250,8 @@ validationLayer("CodexAdapterLive validation", (it) => { |
| 250 | }) | 250 | }) |
| 251 | .pipe(Effect.result); | 251 | .pipe(Effect.result); |
| 252 | 252 | ||
| 253 | assert.equal(result._tag, "Failure"); | 253 | NodeAssert.equal(result._tag, "Failure"); |
| 254 | assert.deepStrictEqual( | 254 | NodeAssert.deepStrictEqual( |
| 255 | result.failure, | 255 | result.failure, |
| 256 | new ProviderAdapterValidationError({ | 256 | new ProviderAdapterValidationError({ |
| 257 | provider: ProviderDriverKind.make("codex"), | 257 | provider: ProviderDriverKind.make("codex"), |
| ... | @@ -259,7 +259,7 @@ validationLayer("CodexAdapterLive validation", (it) => { | ... | @@ -259,7 +259,7 @@ validationLayer("CodexAdapterLive validation", (it) => { |
| 259 | issue: "Expected provider 'codex' but received 'claudeAgent'.", | 259 | issue: "Expected provider 'codex' but received 'claudeAgent'.", |
| 260 | }), | 260 | }), |
| 261 | ); | 261 | ); |
| 262 | assert.equal(validationRuntimeFactory.factory.mock.calls.length, 0); | 262 | NodeAssert.equal(validationRuntimeFactory.factory.mock.calls.length, 0); |
| 263 | }), | 263 | }), |
| 264 | ); | 264 | ); |
| 265 | it.effect("maps codex model options before starting a session", () => | 265 | it.effect("maps codex model options before starting a session", () => |
| ... | @@ -276,7 +276,7 @@ validationLayer("CodexAdapterLive validation", (it) => { | ... | @@ -276,7 +276,7 @@ validationLayer("CodexAdapterLive validation", (it) => { |
| 276 | runtimeMode: "full-access", | 276 | runtimeMode: "full-access", |
| 277 | }); | 277 | }); |
| 278 | 278 | ||
| 279 | assert.deepStrictEqual(validationRuntimeFactory.factory.mock.calls[0]?.[0], { | 279 | NodeAssert.deepStrictEqual(validationRuntimeFactory.factory.mock.calls[0]?.[0], { |
| 280 | binaryPath: "codex", | 280 | binaryPath: "codex", |
| 281 | cwd: process.cwd(), | 281 | cwd: process.cwd(), |
| 282 | model: "gpt-5.3-codex", | 282 | model: "gpt-5.3-codex", |
| ... | @@ -319,10 +319,10 @@ sessionErrorLayer("CodexAdapterLive session errors", (it) => { | ... | @@ -319,10 +319,10 @@ sessionErrorLayer("CodexAdapterLive session errors", (it) => { |
| 319 | }) | 319 | }) |
| 320 | .pipe(Effect.result); | 320 | .pipe(Effect.result); |
| 321 | 321 | ||
| 322 | assert.equal(result._tag, "Failure"); | 322 | NodeAssert.equal(result._tag, "Failure"); |
| 323 | assert.equal(result.failure._tag, "ProviderAdapterSessionNotFoundError"); | 323 | NodeAssert.equal(result.failure._tag, "ProviderAdapterSessionNotFoundError"); |
| 324 | assert.equal(result.failure.provider, "codex"); | 324 | NodeAssert.equal(result.failure.provider, "codex"); |
| 325 | assert.equal(result.failure.threadId, "sess-missing"); | 325 | NodeAssert.equal(result.failure.threadId, "sess-missing"); |
| 326 | }), | 326 | }), |
| 327 | ); | 327 | ); |
| 328 | 328 | ||
| ... | @@ -335,7 +335,7 @@ sessionErrorLayer("CodexAdapterLive session errors", (it) => { | ... | @@ -335,7 +335,7 @@ sessionErrorLayer("CodexAdapterLive session errors", (it) => { |
| 335 | runtimeMode: "full-access", | 335 | runtimeMode: "full-access", |
| 336 | }); | 336 | }); |
| 337 | const runtime = sessionRuntimeFactory.lastRuntime; | 337 | const runtime = sessionRuntimeFactory.lastRuntime; |
| 338 | assert.ok(runtime); | 338 | NodeAssert.ok(runtime); |
| 339 | runtime.sendTurnImpl.mockClear(); | 339 | runtime.sendTurnImpl.mockClear(); |
| 340 | 340 | ||
| 341 | yield* Effect.ignore( | 341 | yield* Effect.ignore( |
| ... | @@ -350,7 +350,7 @@ sessionErrorLayer("CodexAdapterLive session errors", (it) => { | ... | @@ -350,7 +350,7 @@ sessionErrorLayer("CodexAdapterLive session errors", (it) => { |
| 350 | }), | 350 | }), |
| 351 | ); | 351 | ); |
| 352 | 352 | ||
| 353 | assert.deepStrictEqual(runtime.sendTurnImpl.mock.calls[0]?.[0], { | 353 | NodeAssert.deepStrictEqual(runtime.sendTurnImpl.mock.calls[0]?.[0], { |
| 354 | input: "hello", | 354 | input: "hello", |
| 355 | model: "gpt-5.3-codex", | 355 | model: "gpt-5.3-codex", |
| 356 | effort: "high", | 356 | effort: "high", |
| ... | @@ -386,7 +386,7 @@ sessionErrorLayer("CodexAdapterLive session errors", (it) => { | ... | @@ -386,7 +386,7 @@ sessionErrorLayer("CodexAdapterLive session errors", (it) => { |
| 386 | runtimeMode: "full-access", | 386 | runtimeMode: "full-access", |
| 387 | }); | 387 | }); |
| 388 | const runtime = customRuntimeFactory.lastRuntime; | 388 | const runtime = customRuntimeFactory.lastRuntime; |
| 389 | assert.ok(runtime); | 389 | NodeAssert.ok(runtime); |
| 390 | runtime.sendTurnImpl.mockClear(); | 390 | runtime.sendTurnImpl.mockClear(); |
| 391 | 391 | ||
| 392 | yield* Effect.ignore( | 392 | yield* Effect.ignore( |
| ... | @@ -405,7 +405,7 @@ sessionErrorLayer("CodexAdapterLive session errors", (it) => { | ... | @@ -405,7 +405,7 @@ sessionErrorLayer("CodexAdapterLive session errors", (it) => { |
| 405 | }), | 405 | }), |
| 406 | ); | 406 | ); |
| 407 | 407 | ||
| 408 | assert.deepStrictEqual(runtime.sendTurnImpl.mock.calls[0]?.[0], { | 408 | NodeAssert.deepStrictEqual(runtime.sendTurnImpl.mock.calls[0]?.[0], { |
| 409 | input: "hello", | 409 | input: "hello", |
| 410 | model: "gpt-5.3-codex", | 410 | model: "gpt-5.3-codex", |
| 411 | effort: "high", | 411 | effort: "high", |
| ... | @@ -442,7 +442,7 @@ function startLifecycleRuntime() { | ... | @@ -442,7 +442,7 @@ function startLifecycleRuntime() { |
| 442 | runtimeMode: "full-access", | 442 | runtimeMode: "full-access", |
| 443 | }); | 443 | }); |
| 444 | const runtime = lifecycleRuntimeFactory.lastRuntime; | 444 | const runtime = lifecycleRuntimeFactory.lastRuntime; |
| 445 | assert.ok(runtime); | 445 | NodeAssert.ok(runtime); |
| 446 | return { adapter, runtime }; | 446 | return { adapter, runtime }; |
| 447 | }); | 447 | }); |
| 448 | } | 448 | } |
| ... | @@ -477,17 +477,17 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => { | ... | @@ -477,17 +477,17 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => { |
| 477 | yield* runtime.emit(event); | 477 | yield* runtime.emit(event); |
| 478 | const firstEvent = yield* Fiber.join(firstEventFiber); | 478 | const firstEvent = yield* Fiber.join(firstEventFiber); |
| 479 | 479 | ||
| 480 | assert.equal(firstEvent._tag, "Some"); | 480 | NodeAssert.equal(firstEvent._tag, "Some"); |
| 481 | if (firstEvent._tag !== "Some") { | 481 | if (firstEvent._tag !== "Some") { |
| 482 | return; | 482 | return; |
| 483 | } | 483 | } |
| 484 | assert.equal(firstEvent.value.type, "item.completed"); | 484 | NodeAssert.equal(firstEvent.value.type, "item.completed"); |
| 485 | if (firstEvent.value.type !== "item.completed") { | 485 | if (firstEvent.value.type !== "item.completed") { |
| 486 | return; | 486 | return; |
| 487 | } | 487 | } |
| 488 | assert.equal(firstEvent.value.itemId, "msg_1"); | 488 | NodeAssert.equal(firstEvent.value.itemId, "msg_1"); |
| 489 | assert.equal(firstEvent.value.turnId, "turn-1"); | 489 | NodeAssert.equal(firstEvent.value.turnId, "turn-1"); |
| 490 | assert.equal(firstEvent.value.payload.itemType, "assistant_message"); | 490 | NodeAssert.equal(firstEvent.value.payload.itemType, "assistant_message"); |
| 491 | }), | 491 | }), |
| 492 | ); | 492 | ); |
| 493 | 493 | ||
| ... | @@ -524,13 +524,13 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => { | ... | @@ -524,13 +524,13 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => { |
| 524 | }); | 524 | }); |
| 525 | const firstEvent = yield* Fiber.join(firstEventFiber); | 525 | const firstEvent = yield* Fiber.join(firstEventFiber); |
| 526 | 526 | ||
| 527 | assert.equal(firstEvent._tag, "Some"); | 527 | NodeAssert.equal(firstEvent._tag, "Some"); |
| 528 | if (firstEvent._tag !== "Some" || firstEvent.value.type !== "item.completed") { | 528 | if (firstEvent._tag !== "Some" || firstEvent.value.type !== "item.completed") { |
| 529 | return; | 529 | return; |
| 530 | } | 530 | } |
| 531 | assert.equal(firstEvent.value.payload.itemType, "mcp_tool_call"); | 531 | NodeAssert.equal(firstEvent.value.payload.itemType, "mcp_tool_call"); |
| 532 | assert.equal(firstEvent.value.payload.title, "t3-code · preview_status"); | 532 | NodeAssert.equal(firstEvent.value.payload.title, "t3-code · preview_status"); |
| 533 | assert.deepStrictEqual(firstEvent.value.payload.data, { | 533 | NodeAssert.deepStrictEqual(firstEvent.value.payload.data, { |
| 534 | completedAtMs: 1_778_000_000_000, | 534 | completedAtMs: 1_778_000_000_000, |
| 535 | threadId: "thread-1", | 535 | threadId: "thread-1", |
| 536 | turnId: "turn-1", | 536 | turnId: "turn-1", |
| ... | @@ -578,16 +578,16 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => { | ... | @@ -578,16 +578,16 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => { |
| 578 | yield* runtime.emit(event); | 578 | yield* runtime.emit(event); |
| 579 | const firstEvent = yield* Fiber.join(firstEventFiber); | 579 | const firstEvent = yield* Fiber.join(firstEventFiber); |
| 580 | 580 | ||
| 581 | assert.equal(firstEvent._tag, "Some"); | 581 | NodeAssert.equal(firstEvent._tag, "Some"); |
| 582 | if (firstEvent._tag !== "Some") { | 582 | if (firstEvent._tag !== "Some") { |
| 583 | return; | 583 | return; |
| 584 | } | 584 | } |
| 585 | assert.equal(firstEvent.value.type, "turn.proposed.completed"); | 585 | NodeAssert.equal(firstEvent.value.type, "turn.proposed.completed"); |
| 586 | if (firstEvent.value.type !== "turn.proposed.completed") { | 586 | if (firstEvent.value.type !== "turn.proposed.completed") { |
| 587 | return; | 587 | return; |
| 588 | } | 588 | } |
| 589 | assert.equal(firstEvent.value.turnId, "turn-1"); | 589 | NodeAssert.equal(firstEvent.value.turnId, "turn-1"); |
| 590 | assert.equal(firstEvent.value.payload.planMarkdown, "## Final plan\n\n- one\n- two"); | 590 | NodeAssert.equal(firstEvent.value.payload.planMarkdown, "## Final plan\n\n- one\n- two"); |
| 591 | }), | 591 | }), |
| 592 | ); | 592 | ); |
| 593 | 593 | ||
| ... | @@ -615,16 +615,16 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => { | ... | @@ -615,16 +615,16 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => { |
| 615 | 615 | ||
| 616 | const firstEvent = yield* Fiber.join(firstEventFiber); | 616 | const firstEvent = yield* Fiber.join(firstEventFiber); |
| 617 | 617 | ||
| 618 | assert.equal(firstEvent._tag, "Some"); | 618 | NodeAssert.equal(firstEvent._tag, "Some"); |
| 619 | if (firstEvent._tag !== "Some") { | 619 | if (firstEvent._tag !== "Some") { |
| 620 | return; | 620 | return; |
| 621 | } | 621 | } |
| 622 | assert.equal(firstEvent.value.type, "turn.proposed.delta"); | 622 | NodeAssert.equal(firstEvent.value.type, "turn.proposed.delta"); |
| 623 | if (firstEvent.value.type !== "turn.proposed.delta") { | 623 | if (firstEvent.value.type !== "turn.proposed.delta") { |
| 624 | return; | 624 | return; |
| 625 | } | 625 | } |
| 626 | assert.equal(firstEvent.value.turnId, "turn-1"); | 626 | NodeAssert.equal(firstEvent.value.turnId, "turn-1"); |
| 627 | assert.equal(firstEvent.value.payload.delta, "## Final plan"); | 627 | NodeAssert.equal(firstEvent.value.payload.delta, "## Final plan"); |
| 628 | }), | 628 | }), |
| 629 | ); | 629 | ); |
| 630 | 630 | ||
| ... | @@ -646,16 +646,16 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => { | ... | @@ -646,16 +646,16 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => { |
| 646 | yield* runtime.emit(event); | 646 | yield* runtime.emit(event); |
| 647 | const firstEvent = yield* Fiber.join(firstEventFiber); | 647 | const firstEvent = yield* Fiber.join(firstEventFiber); |
| 648 | 648 | ||
| 649 | assert.equal(firstEvent._tag, "Some"); | 649 | NodeAssert.equal(firstEvent._tag, "Some"); |
| 650 | if (firstEvent._tag !== "Some") { | 650 | if (firstEvent._tag !== "Some") { |
| 651 | return; | 651 | return; |
| 652 | } | 652 | } |
| 653 | assert.equal(firstEvent.value.type, "session.exited"); | 653 | NodeAssert.equal(firstEvent.value.type, "session.exited"); |
| 654 | if (firstEvent.value.type !== "session.exited") { | 654 | if (firstEvent.value.type !== "session.exited") { |
| 655 | return; | 655 | return; |
| 656 | } | 656 | } |
| 657 | assert.equal(firstEvent.value.threadId, "thread-1"); | 657 | NodeAssert.equal(firstEvent.value.threadId, "thread-1"); |
| 658 | assert.equal(firstEvent.value.payload.reason, "Session stopped"); | 658 | NodeAssert.equal(firstEvent.value.payload.reason, "Session stopped"); |
| 659 | }), | 659 | }), |
| 660 | ); | 660 | ); |
| 661 | 661 | ||
| ... | @@ -684,16 +684,16 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => { | ... | @@ -684,16 +684,16 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => { |
| 684 | 684 | ||
| 685 | const firstEvent = yield* Fiber.join(firstEventFiber); | 685 | const firstEvent = yield* Fiber.join(firstEventFiber); |
| 686 | 686 | ||
| 687 | assert.equal(firstEvent._tag, "Some"); | 687 | NodeAssert.equal(firstEvent._tag, "Some"); |
| 688 | if (firstEvent._tag !== "Some") { | 688 | if (firstEvent._tag !== "Some") { |
| 689 | return; | 689 | return; |
| 690 | } | 690 | } |
| 691 | assert.equal(firstEvent.value.type, "runtime.warning"); | 691 | NodeAssert.equal(firstEvent.value.type, "runtime.warning"); |
| 692 | if (firstEvent.value.type !== "runtime.warning") { | 692 | if (firstEvent.value.type !== "runtime.warning") { |
| 693 | return; | 693 | return; |
| 694 | } | 694 | } |
| 695 | assert.equal(firstEvent.value.turnId, "turn-1"); | 695 | NodeAssert.equal(firstEvent.value.turnId, "turn-1"); |
| 696 | assert.equal(firstEvent.value.payload.message, "Reconnecting... 2/5"); | 696 | NodeAssert.equal(firstEvent.value.payload.message, "Reconnecting... 2/5"); |
| 697 | }), | 697 | }), |
| 698 | ); | 698 | ); |
| 699 | 699 | ||
| ... | @@ -715,16 +715,16 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => { | ... | @@ -715,16 +715,16 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => { |
| 715 | 715 | ||
| 716 | const firstEvent = yield* Fiber.join(firstEventFiber); | 716 | const firstEvent = yield* Fiber.join(firstEventFiber); |
| 717 | 717 | ||
| 718 | assert.equal(firstEvent._tag, "Some"); | 718 | NodeAssert.equal(firstEvent._tag, "Some"); |
| 719 | if (firstEvent._tag !== "Some") { | 719 | if (firstEvent._tag !== "Some") { |
| 720 | return; | 720 | return; |
| 721 | } | 721 | } |
| 722 | assert.equal(firstEvent.value.type, "runtime.warning"); | 722 | NodeAssert.equal(firstEvent.value.type, "runtime.warning"); |
| 723 | if (firstEvent.value.type !== "runtime.warning") { | 723 | if (firstEvent.value.type !== "runtime.warning") { |
| 724 | return; | 724 | return; |
| 725 | } | 725 | } |
| 726 | assert.equal(firstEvent.value.turnId, "turn-1"); | 726 | NodeAssert.equal(firstEvent.value.turnId, "turn-1"); |
| 727 | assert.equal( | 727 | NodeAssert.equal( |
| 728 | firstEvent.value.payload.message, | 728 | firstEvent.value.payload.message, |
| 729 | "The filename or extension is too long. (os error 206)", | 729 | "The filename or extension is too long. (os error 206)", |
| 730 | ); | 730 | ); |
| ... | @@ -752,16 +752,16 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => { | ... | @@ -752,16 +752,16 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => { |
| 752 | 752 | ||
| 753 | const firstEvent = yield* Fiber.join(firstEventFiber); | 753 | const firstEvent = yield* Fiber.join(firstEventFiber); |
| 754 | 754 | ||
| 755 | assert.equal(firstEvent._tag, "Some"); | 755 | NodeAssert.equal(firstEvent._tag, "Some"); |
| 756 | if (firstEvent._tag !== "Some") { | 756 | if (firstEvent._tag !== "Some") { |
| 757 | return; | 757 | return; |
| 758 | } | 758 | } |
| 759 | assert.equal(firstEvent.value.type, "thread.realtime.started"); | 759 | NodeAssert.equal(firstEvent.value.type, "thread.realtime.started"); |
| 760 | if (firstEvent.value.type !== "thread.realtime.started") { | 760 | if (firstEvent.value.type !== "thread.realtime.started") { |
| 761 | return; | 761 | return; |
| 762 | } | 762 | } |
| 763 | assert.equal(firstEvent.value.threadId, "thread-1"); | 763 | NodeAssert.equal(firstEvent.value.threadId, "thread-1"); |
| 764 | assert.equal(firstEvent.value.payload.realtimeSessionId, "realtime-session-1"); | 764 | NodeAssert.equal(firstEvent.value.payload.realtimeSessionId, "realtime-session-1"); |
| 765 | }), | 765 | }), |
| 766 | ); | 766 | ); |
| 767 | 767 | ||
| ... | @@ -784,17 +784,17 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => { | ... | @@ -784,17 +784,17 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => { |
| 784 | 784 | ||
| 785 | const firstEvent = yield* Fiber.join(firstEventFiber); | 785 | const firstEvent = yield* Fiber.join(firstEventFiber); |
| 786 | 786 | ||
| 787 | assert.equal(firstEvent._tag, "Some"); | 787 | NodeAssert.equal(firstEvent._tag, "Some"); |
| 788 | if (firstEvent._tag !== "Some") { | 788 | if (firstEvent._tag !== "Some") { |
| 789 | return; | 789 | return; |
| 790 | } | 790 | } |
| 791 | assert.equal(firstEvent.value.type, "runtime.error"); | 791 | NodeAssert.equal(firstEvent.value.type, "runtime.error"); |
| 792 | if (firstEvent.value.type !== "runtime.error") { | 792 | if (firstEvent.value.type !== "runtime.error") { |
| 793 | return; | 793 | return; |
| 794 | } | 794 | } |
| 795 | assert.equal(firstEvent.value.turnId, "turn-1"); | 795 | NodeAssert.equal(firstEvent.value.turnId, "turn-1"); |
| 796 | assert.equal(firstEvent.value.payload.class, "provider_error"); | 796 | NodeAssert.equal(firstEvent.value.payload.class, "provider_error"); |
| 797 | assert.equal( | 797 | NodeAssert.equal( |
| 798 | firstEvent.value.payload.message, | 798 | firstEvent.value.payload.message, |
| 799 | "2026-03-31T18:14:06.833399Z ERROR codex_api::endpoint::responses_websocket: failed to connect to websocket: HTTP error: 503 Service Unavailable, url: wss://chatgpt.com/backend-api/codex/responses", | 799 | "2026-03-31T18:14:06.833399Z ERROR codex_api::endpoint::responses_websocket: failed to connect to websocket: HTTP error: 503 Service Unavailable, url: wss://chatgpt.com/backend-api/codex/responses", |
| 800 | ); | 800 | ); |
| ... | @@ -824,15 +824,15 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => { | ... | @@ -824,15 +824,15 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => { |
| 824 | yield* runtime.emit(event); | 824 | yield* runtime.emit(event); |
| 825 | const firstEvent = yield* Fiber.join(firstEventFiber); | 825 | const firstEvent = yield* Fiber.join(firstEventFiber); |
| 826 | 826 | ||
| 827 | assert.equal(firstEvent._tag, "Some"); | 827 | NodeAssert.equal(firstEvent._tag, "Some"); |
| 828 | if (firstEvent._tag !== "Some") { | 828 | if (firstEvent._tag !== "Some") { |
| 829 | return; | 829 | return; |
| 830 | } | 830 | } |
| 831 | assert.equal(firstEvent.value.type, "request.resolved"); | 831 | NodeAssert.equal(firstEvent.value.type, "request.resolved"); |
| 832 | if (firstEvent.value.type !== "request.resolved") { | 832 | if (firstEvent.value.type !== "request.resolved") { |
| 833 | return; | 833 | return; |
| 834 | } | 834 | } |
| 835 | assert.equal(firstEvent.value.payload.requestType, "command_execution_approval"); | 835 | NodeAssert.equal(firstEvent.value.payload.requestType, "command_execution_approval"); |
| 836 | }), | 836 | }), |
| 837 | ); | 837 | ); |
| 838 | 838 | ||
| ... | @@ -859,15 +859,15 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => { | ... | @@ -859,15 +859,15 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => { |
| 859 | yield* runtime.emit(event); | 859 | yield* runtime.emit(event); |
| 860 | const firstEvent = yield* Fiber.join(firstEventFiber); | 860 | const firstEvent = yield* Fiber.join(firstEventFiber); |
| 861 | 861 | ||
| 862 | assert.equal(firstEvent._tag, "Some"); | 862 | NodeAssert.equal(firstEvent._tag, "Some"); |
| 863 | if (firstEvent._tag !== "Some") { | 863 | if (firstEvent._tag !== "Some") { |
| 864 | return; | 864 | return; |
| 865 | } | 865 | } |
| 866 | assert.equal(firstEvent.value.type, "request.resolved"); | 866 | NodeAssert.equal(firstEvent.value.type, "request.resolved"); |
| 867 | if (firstEvent.value.type !== "request.resolved") { | 867 | if (firstEvent.value.type !== "request.resolved") { |
| 868 | return; | 868 | return; |
| 869 | } | 869 | } |
| 870 | assert.equal(firstEvent.value.payload.requestType, "file_read_approval"); | 870 | NodeAssert.equal(firstEvent.value.payload.requestType, "file_read_approval"); |
| 871 | }), | 871 | }), |
| 872 | ); | 872 | ); |
| 873 | 873 | ||
| ... | @@ -895,15 +895,15 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => { | ... | @@ -895,15 +895,15 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => { |
| 895 | yield* runtime.emit(event); | 895 | yield* runtime.emit(event); |
| 896 | const firstEvent = yield* Fiber.join(firstEventFiber); | 896 | const firstEvent = yield* Fiber.join(firstEventFiber); |
| 897 | 897 | ||
| 898 | assert.equal(firstEvent._tag, "Some"); | 898 | NodeAssert.equal(firstEvent._tag, "Some"); |
| 899 | if (firstEvent._tag !== "Some") { | 899 | if (firstEvent._tag !== "Some") { |
| 900 | return; | 900 | return; |
| 901 | } | 901 | } |
| 902 | assert.equal(firstEvent.value.type, "user-input.resolved"); | 902 | NodeAssert.equal(firstEvent.value.type, "user-input.resolved"); |
| 903 | if (firstEvent.value.type !== "user-input.resolved") { | 903 | if (firstEvent.value.type !== "user-input.resolved") { |
| 904 | return; | 904 | return; |
| 905 | } | 905 | } |
| 906 | assert.deepEqual(firstEvent.value.payload.answers, { | 906 | NodeAssert.deepEqual(firstEvent.value.payload.answers, { |
| 907 | scope: [], | 907 | scope: [], |
| 908 | }); | 908 | }); |
| 909 | }), | 909 | }), |
| ... | @@ -934,20 +934,20 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => { | ... | @@ -934,20 +934,20 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => { |
| 934 | yield* runtime.emit(event); | 934 | yield* runtime.emit(event); |
| 935 | const events = Array.from(yield* Fiber.join(eventsFiber)); | 935 | const events = Array.from(yield* Fiber.join(eventsFiber)); |
| 936 | 936 | ||
| 937 | assert.equal(events.length, 2); | 937 | NodeAssert.equal(events.length, 2); |
| 938 | 938 | ||
| 939 | const firstEvent = events[0]; | 939 | const firstEvent = events[0]; |
| 940 | const secondEvent = events[1]; | 940 | const secondEvent = events[1]; |
| 941 | 941 | ||
| 942 | assert.equal(firstEvent?.type, "session.state.changed"); | 942 | NodeAssert.equal(firstEvent?.type, "session.state.changed"); |
| 943 | if (firstEvent?.type === "session.state.changed") { | 943 | if (firstEvent?.type === "session.state.changed") { |
| 944 | assert.equal(firstEvent.payload.state, "error"); | 944 | NodeAssert.equal(firstEvent.payload.state, "error"); |
| 945 | assert.equal(firstEvent.payload.reason, "Sandbox setup failed"); | 945 | NodeAssert.equal(firstEvent.payload.reason, "Sandbox setup failed"); |
| 946 | } | 946 | } |
| 947 | 947 | ||
| 948 | assert.equal(secondEvent?.type, "runtime.warning"); | 948 | NodeAssert.equal(secondEvent?.type, "runtime.warning"); |
| 949 | if (secondEvent?.type === "runtime.warning") { | 949 | if (secondEvent?.type === "runtime.warning") { |
| 950 | assert.equal(secondEvent.payload.message, "Sandbox setup failed"); | 950 | NodeAssert.equal(secondEvent.payload.message, "Sandbox setup failed"); |
| 951 | } | 951 | } |
| 952 | }), | 952 | }), |
| 953 | ); | 953 | ); |
| ... | @@ -1006,17 +1006,17 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => { | ... | @@ -1006,17 +1006,17 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => { |
| 1006 | } satisfies ProviderEvent); | 1006 | } satisfies ProviderEvent); |
| 1007 | 1007 | ||
| 1008 | const events = Array.from(yield* Fiber.join(eventsFiber)); | 1008 | const events = Array.from(yield* Fiber.join(eventsFiber)); |
| 1009 | assert.equal(events[0]?.type, "user-input.requested"); | 1009 | NodeAssert.equal(events[0]?.type, "user-input.requested"); |
| 1010 | if (events[0]?.type === "user-input.requested") { | 1010 | if (events[0]?.type === "user-input.requested") { |
| 1011 | assert.equal(events[0].requestId, "req-user-input-1"); | 1011 | NodeAssert.equal(events[0].requestId, "req-user-input-1"); |
| 1012 | assert.equal(events[0].payload.questions[0]?.id, "sandbox_mode"); | 1012 | NodeAssert.equal(events[0].payload.questions[0]?.id, "sandbox_mode"); |
| 1013 | assert.equal(events[0].payload.questions[0]?.multiSelect, false); | 1013 | NodeAssert.equal(events[0].payload.questions[0]?.multiSelect, false); |
| 1014 | } | 1014 | } |
| 1015 | 1015 | ||
| 1016 | assert.equal(events[1]?.type, "user-input.resolved"); | 1016 | NodeAssert.equal(events[1]?.type, "user-input.resolved"); |
| 1017 | if (events[1]?.type === "user-input.resolved") { | 1017 | if (events[1]?.type === "user-input.resolved") { |
| 1018 | assert.equal(events[1].requestId, "req-user-input-1"); | 1018 | NodeAssert.equal(events[1].requestId, "req-user-input-1"); |
| 1019 | assert.deepEqual(events[1].payload.answers, { | 1019 | NodeAssert.deepEqual(events[1].payload.answers, { |
| 1020 | sandbox_mode: "workspace-write", | 1020 | sandbox_mode: "workspace-write", |
| 1021 | }); | 1021 | }); |
| 1022 | } | 1022 | } |
| ... | @@ -1060,16 +1060,16 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => { | ... | @@ -1060,16 +1060,16 @@ lifecycleLayer("CodexAdapterLive lifecycle", (it) => { |
| 1060 | } satisfies ProviderEvent); | 1060 | } satisfies ProviderEvent); |
| 1061 | 1061 | ||
| 1062 | const firstEvent = yield* Fiber.join(firstEventFiber); | 1062 | const firstEvent = yield* Fiber.join(firstEventFiber); |
| 1063 | assert.equal(firstEvent._tag, "Some"); | 1063 | NodeAssert.equal(firstEvent._tag, "Some"); |
| 1064 | if (firstEvent._tag !== "Some") { | 1064 | if (firstEvent._tag !== "Some") { |
| 1065 | return; | 1065 | return; |
| 1066 | } | 1066 | } |
| 1067 | assert.equal(firstEvent.value.type, "thread.token-usage.updated"); | 1067 | NodeAssert.equal(firstEvent.value.type, "thread.token-usage.updated"); |
| 1068 | if (firstEvent.value.type !== "thread.token-usage.updated") { | 1068 | if (firstEvent.value.type !== "thread.token-usage.updated") { |
| 1069 | return; | 1069 | return; |
| 1070 | } | 1070 | } |
| 1071 | 1071 | ||
| 1072 | assert.deepEqual(firstEvent.value.payload.usage, { | 1072 | NodeAssert.deepEqual(firstEvent.value.payload.usage, { |
| 1073 | usedTokens: 126, | 1073 | usedTokens: 126, |
| 1074 | totalProcessedTokens: 11_839, | 1074 | totalProcessedTokens: 11_839, |
| 1075 | maxTokens: 258_400, | 1075 | maxTokens: 258_400, |
| ... | @@ -1119,15 +1119,15 @@ scopedLifecycleLayer("CodexAdapterLive scoped lifecycle", (it) => { | ... | @@ -1119,15 +1119,15 @@ scopedLifecycleLayer("CodexAdapterLive scoped lifecycle", (it) => { |
| 1119 | }); | 1119 | }); |
| 1120 | 1120 | ||
| 1121 | const runtime = scopedLifecycleRuntimeFactory.lastRuntime; | 1121 | const runtime = scopedLifecycleRuntimeFactory.lastRuntime; |
| 1122 | assert.ok(runtime); | 1122 | NodeAssert.ok(runtime); |
| 1123 | 1123 | ||
| 1124 | yield* adapter.stopSession(asThreadId("thread-stop")); | 1124 | yield* adapter.stopSession(asThreadId("thread-stop")); |
| 1125 | 1125 | ||
| 1126 | assert.equal(runtime.closeImpl.mock.calls.length, 1); | 1126 | NodeAssert.equal(runtime.closeImpl.mock.calls.length, 1); |
| 1127 | assert.deepStrictEqual(scopedLifecycleRuntimeFactory.releasedThreadIds, [ | 1127 | NodeAssert.deepStrictEqual(scopedLifecycleRuntimeFactory.releasedThreadIds, [ |
| 1128 | asThreadId("thread-stop"), | 1128 | asThreadId("thread-stop"), |
| 1129 | ]); | 1129 | ]); |
| 1130 | assert.equal(yield* adapter.hasSession(asThreadId("thread-stop")), false); | 1130 | NodeAssert.equal(yield* adapter.hasSession(asThreadId("thread-stop")), false); |
| 1131 | }), | 1131 | }), |
| 1132 | ); | 1132 | ); |
| 1133 | }); | 1133 | }); |
| ... | @@ -1164,20 +1164,22 @@ scopedFailureLayer("CodexAdapterLive scoped startup failure", (it) => { | ... | @@ -1164,20 +1164,22 @@ scopedFailureLayer("CodexAdapterLive scoped startup failure", (it) => { |
| 1164 | }) | 1164 | }) |
| 1165 | .pipe(Effect.result); | 1165 | .pipe(Effect.result); |
| 1166 | 1166 | ||
| 1167 | assert.equal(result._tag, "Failure"); | 1167 | NodeAssert.equal(result._tag, "Failure"); |
| 1168 | assert.equal(result.failure._tag, "ProviderAdapterProcessError"); | 1168 | NodeAssert.equal(result.failure._tag, "ProviderAdapterProcessError"); |
| 1169 | assert.deepStrictEqual(scopedFailureRuntimeFactory.releasedThreadIds, [ | 1169 | NodeAssert.deepStrictEqual(scopedFailureRuntimeFactory.releasedThreadIds, [ |
| 1170 | asThreadId("thread-fail"), | 1170 | asThreadId("thread-fail"), |
| 1171 | ]); | 1171 | ]); |
| 1172 | assert.equal(yield* adapter.hasSession(asThreadId("thread-fail")), false); | 1172 | NodeAssert.equal(yield* adapter.hasSession(asThreadId("thread-fail")), false); |
| 1173 | }), | 1173 | }), |
| 1174 | ); | 1174 | ); |
| 1175 | }); | 1175 | }); |
| 1176 | 1176 | ||
| 1177 | it.effect("flushes managed native logs when the adapter layer shuts down", () => | 1177 | it.effect("flushes managed native logs when the adapter layer shuts down", () => |
| 1178 | Effect.gen(function* () { | 1178 | Effect.gen(function* () { |
| 1179 | const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "t3-codex-adapter-native-log-")); | 1179 | const tempDir = NodeFS.mkdtempSync( |
| 1180 | const basePath = path.join(tempDir, "provider-native.ndjson"); | 1180 | NodePath.join(NodeOS.tmpdir(), "t3-codex-adapter-native-log-"), |
| 1181 | ); | ||
| 1182 | const basePath = NodePath.join(tempDir, "provider-native.ndjson"); | ||
| 1181 | const runtimeFactory = makeRuntimeFactory(); | 1183 | const runtimeFactory = makeRuntimeFactory(); |
| 1182 | const scope = yield* Scope.make("sequential"); | 1184 | const scope = yield* Scope.make("sequential"); |
| 1183 | let scopeClosed = false; | 1185 | let scopeClosed = false; |
| ... | @@ -1208,7 +1210,7 @@ it.effect("flushes managed native logs when the adapter layer shuts down", () => | ... | @@ -1208,7 +1210,7 @@ it.effect("flushes managed native logs when the adapter layer shuts down", () => |
| 1208 | }); | 1210 | }); |
| 1209 | 1211 | ||
| 1210 | const runtime = runtimeFactory.lastRuntime; | 1212 | const runtime = runtimeFactory.lastRuntime; |
| 1211 | assert.ok(runtime); | 1213 | NodeAssert.ok(runtime); |
| 1212 | 1214 | ||
| 1213 | const firstEventFiber = yield* Stream.runHead(adapter.streamEvents).pipe(Effect.forkChild); | 1215 | const firstEventFiber = yield* Stream.runHead(adapter.streamEvents).pipe(Effect.forkChild); |
| 1214 | yield* runtime.emit({ | 1216 | yield* runtime.emit({ |
| ... | @@ -1225,15 +1227,15 @@ it.effect("flushes managed native logs when the adapter layer shuts down", () => | ... | @@ -1225,15 +1227,15 @@ it.effect("flushes managed native logs when the adapter layer shuts down", () => |
| 1225 | yield* Scope.close(scope, Exit.void); | 1227 | yield* Scope.close(scope, Exit.void); |
| 1226 | scopeClosed = true; | 1228 | scopeClosed = true; |
| 1227 | 1229 | ||
| 1228 | const threadLogPath = path.join(tempDir, "thread-logger.log"); | 1230 | const threadLogPath = NodePath.join(tempDir, "thread-logger.log"); |
| 1229 | assert.equal(fs.existsSync(threadLogPath), true); | 1231 | NodeAssert.equal(NodeFS.existsSync(threadLogPath), true); |
| 1230 | const contents = fs.readFileSync(threadLogPath, "utf8"); | 1232 | const contents = NodeFS.readFileSync(threadLogPath, "utf8"); |
| 1231 | assert.match(contents, /NTIVE: .*"message":"native flush test"/); | 1233 | NodeAssert.match(contents, /NTIVE: .*"message":"native flush test"/); |
| 1232 | } finally { | 1234 | } finally { |
| 1233 | if (!scopeClosed) { | 1235 | if (!scopeClosed) { |
| 1234 | yield* Scope.close(scope, Exit.void); | 1236 | yield* Scope.close(scope, Exit.void); |
| 1235 | } | 1237 | } |
| 1236 | fs.rmSync(tempDir, { recursive: true, force: true }); | 1238 | NodeFS.rmSync(tempDir, { recursive: true, force: true }); |
| 1237 | } | 1239 | } |
| 1238 | }), | 1240 | }), |
| 1239 | ); | 1241 | ); |
apps/server/src/provider/Layers/CodexSessionRuntime.test.ts+18-18| ... | @@ -1,4 +1,4 @@ | ... | @@ -1,4 +1,4 @@ |
| 1 | import assert from "node:assert/strict"; | 1 | import * as NodeAssert from "node:assert/strict"; |
| 2 | 2 | ||
| 3 | import * as Effect from "effect/Effect"; | 3 | import * as Effect from "effect/Effect"; |
| 4 | import * as Schema from "effect/Schema"; | 4 | import * as Schema from "effect/Schema"; |
| ... | @@ -55,7 +55,7 @@ describe("buildTurnStartParams", () => { | ... | @@ -55,7 +55,7 @@ describe("buildTurnStartParams", () => { |
| 55 | }), | 55 | }), |
| 56 | ); | 56 | ); |
| 57 | 57 | ||
| 58 | assert.deepStrictEqual(params, { | 58 | NodeAssert.deepStrictEqual(params, { |
| 59 | threadId: "provider-thread-1", | 59 | threadId: "provider-thread-1", |
| 60 | approvalPolicy: "never", | 60 | approvalPolicy: "never", |
| 61 | sandboxPolicy: { | 61 | sandboxPolicy: { |
| ... | @@ -97,7 +97,7 @@ describe("buildTurnStartParams", () => { | ... | @@ -97,7 +97,7 @@ describe("buildTurnStartParams", () => { |
| 97 | }), | 97 | }), |
| 98 | ); | 98 | ); |
| 99 | 99 | ||
| 100 | assert.deepStrictEqual(params, { | 100 | NodeAssert.deepStrictEqual(params, { |
| 101 | threadId: "provider-thread-1", | 101 | threadId: "provider-thread-1", |
| 102 | approvalPolicy: "on-request", | 102 | approvalPolicy: "on-request", |
| 103 | sandboxPolicy: { | 103 | sandboxPolicy: { |
| ... | @@ -134,7 +134,7 @@ describe("buildTurnStartParams", () => { | ... | @@ -134,7 +134,7 @@ describe("buildTurnStartParams", () => { |
| 134 | }), | 134 | }), |
| 135 | ); | 135 | ); |
| 136 | 136 | ||
| 137 | assert.deepStrictEqual(params, { | 137 | NodeAssert.deepStrictEqual(params, { |
| 138 | threadId: "provider-thread-1", | 138 | threadId: "provider-thread-1", |
| 139 | approvalPolicy: "untrusted", | 139 | approvalPolicy: "untrusted", |
| 140 | sandboxPolicy: { | 140 | sandboxPolicy: { |
| ... | @@ -156,19 +156,19 @@ describe("T3 browser developer instructions", () => { | ... | @@ -156,19 +156,19 @@ describe("T3 browser developer instructions", () => { |
| 156 | CODEX_DEFAULT_MODE_DEVELOPER_INSTRUCTIONS, | 156 | CODEX_DEFAULT_MODE_DEVELOPER_INSTRUCTIONS, |
| 157 | CODEX_PLAN_MODE_DEVELOPER_INSTRUCTIONS, | 157 | CODEX_PLAN_MODE_DEVELOPER_INSTRUCTIONS, |
| 158 | ]) { | 158 | ]) { |
| 159 | assert.match(instructions, /t3-code/); | 159 | NodeAssert.match(instructions, /t3-code/); |
| 160 | assert.match(instructions, /preview_status/); | 160 | NodeAssert.match(instructions, /preview_status/); |
| 161 | assert.match(instructions, /preview_open/); | 161 | NodeAssert.match(instructions, /preview_open/); |
| 162 | assert.match(instructions, /Do not switch to global browser skills/); | 162 | NodeAssert.match(instructions, /Do not switch to global browser skills/); |
| 163 | } | 163 | } |
| 164 | }); | 164 | }); |
| 165 | }); | 165 | }); |
| 166 | 166 | ||
| 167 | describe("hasConfiguredMcpServer", () => { | 167 | describe("hasConfiguredMcpServer", () => { |
| 168 | it("detects inline Codex MCP configuration arguments", () => { | 168 | it("detects inline Codex MCP configuration arguments", () => { |
| 169 | assert.equal(hasConfiguredMcpServer(undefined), false); | 169 | NodeAssert.equal(hasConfiguredMcpServer(undefined), false); |
| 170 | assert.equal(hasConfiguredMcpServer(["--model", "gpt-5.4"]), false); | 170 | NodeAssert.equal(hasConfiguredMcpServer(["--model", "gpt-5.4"]), false); |
| 171 | assert.equal( | 171 | NodeAssert.equal( |
| 172 | hasConfiguredMcpServer(["-c", 'mcp_servers.t3-code.url="http://127.0.0.1/mcp"']), | 172 | hasConfiguredMcpServer(["-c", 'mcp_servers.t3-code.url="http://127.0.0.1/mcp"']), |
| 173 | true, | 173 | true, |
| 174 | ); | 174 | ); |
| ... | @@ -177,7 +177,7 @@ describe("hasConfiguredMcpServer", () => { | ... | @@ -177,7 +177,7 @@ describe("hasConfiguredMcpServer", () => { |
| 177 | 177 | ||
| 178 | describe("isRecoverableThreadResumeError", () => { | 178 | describe("isRecoverableThreadResumeError", () => { |
| 179 | it("matches missing thread errors", () => { | 179 | it("matches missing thread errors", () => { |
| 180 | assert.equal( | 180 | NodeAssert.equal( |
| 181 | isRecoverableThreadResumeError( | 181 | isRecoverableThreadResumeError( |
| 182 | new CodexErrors.CodexAppServerRequestError({ | 182 | new CodexErrors.CodexAppServerRequestError({ |
| 183 | code: -32603, | 183 | code: -32603, |
| ... | @@ -189,7 +189,7 @@ describe("isRecoverableThreadResumeError", () => { | ... | @@ -189,7 +189,7 @@ describe("isRecoverableThreadResumeError", () => { |
| 189 | }); | 189 | }); |
| 190 | 190 | ||
| 191 | it("ignores non-recoverable resume errors", () => { | 191 | it("ignores non-recoverable resume errors", () => { |
| 192 | assert.equal( | 192 | NodeAssert.equal( |
| 193 | isRecoverableThreadResumeError( | 193 | isRecoverableThreadResumeError( |
| 194 | new CodexErrors.CodexAppServerRequestError({ | 194 | new CodexErrors.CodexAppServerRequestError({ |
| 195 | code: -32603, | 195 | code: -32603, |
| ... | @@ -201,7 +201,7 @@ describe("isRecoverableThreadResumeError", () => { | ... | @@ -201,7 +201,7 @@ describe("isRecoverableThreadResumeError", () => { |
| 201 | }); | 201 | }); |
| 202 | 202 | ||
| 203 | it("ignores unrelated missing-resource errors that do not mention threads", () => { | 203 | it("ignores unrelated missing-resource errors that do not mention threads", () => { |
| 204 | assert.equal( | 204 | NodeAssert.equal( |
| 205 | isRecoverableThreadResumeError( | 205 | isRecoverableThreadResumeError( |
| 206 | new CodexErrors.CodexAppServerRequestError({ | 206 | new CodexErrors.CodexAppServerRequestError({ |
| 207 | code: -32603, | 207 | code: -32603, |
| ... | @@ -210,7 +210,7 @@ describe("isRecoverableThreadResumeError", () => { | ... | @@ -210,7 +210,7 @@ describe("isRecoverableThreadResumeError", () => { |
| 210 | ), | 210 | ), |
| 211 | false, | 211 | false, |
| 212 | ); | 212 | ); |
| 213 | assert.equal( | 213 | NodeAssert.equal( |
| 214 | isRecoverableThreadResumeError( | 214 | isRecoverableThreadResumeError( |
| 215 | new CodexErrors.CodexAppServerRequestError({ | 215 | new CodexErrors.CodexAppServerRequestError({ |
| 216 | code: -32603, | 216 | code: -32603, |
| ... | @@ -256,8 +256,8 @@ describe("openCodexThread", () => { | ... | @@ -256,8 +256,8 @@ describe("openCodexThread", () => { |
| 256 | }), | 256 | }), |
| 257 | ); | 257 | ); |
| 258 | 258 | ||
| 259 | assert.equal(opened.thread.id, "fresh-thread"); | 259 | NodeAssert.equal(opened.thread.id, "fresh-thread"); |
| 260 | assert.deepStrictEqual( | 260 | NodeAssert.deepStrictEqual( |
| 261 | calls.map((call) => call.method), | 261 | calls.map((call) => call.method), |
| 262 | ["thread/resume", "thread/start"], | 262 | ["thread/resume", "thread/start"], |
| 263 | ); | 263 | ); |
| ... | @@ -283,7 +283,7 @@ describe("openCodexThread", () => { | ... | @@ -283,7 +283,7 @@ describe("openCodexThread", () => { |
| 283 | }, | 283 | }, |
| 284 | }; | 284 | }; |
| 285 | 285 | ||
| 286 | await assert.rejects( | 286 | await NodeAssert.rejects( |
| 287 | Effect.runPromise( | 287 | Effect.runPromise( |
| 288 | openCodexThread({ | 288 | openCodexThread({ |
| 289 | client, | 289 | client, |
apps/server/src/provider/Layers/CursorAdapter.test.ts+63-49| ... | @@ -1,8 +1,8 @@ | ... | @@ -1,8 +1,8 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off | 1 | // @effect-diagnostics nodeBuiltinImport:off |
| 2 | import * as path from "node:path"; | 2 | import * as NodePath from "node:path"; |
| 3 | import * as os from "node:os"; | 3 | import * as NodeOS from "node:os"; |
| 4 | import { chmod, mkdtemp, readFile, writeFile } from "node:fs/promises"; | 4 | import * as NodeFSP from "node:fs/promises"; |
| 5 | import { fileURLToPath } from "node:url"; | 5 | import * as NodeURL from "node:url"; |
| 6 | 6 | ||
| 7 | import * as NodeServices from "@effect/platform-node/NodeServices"; | 7 | import * as NodeServices from "@effect/platform-node/NodeServices"; |
| 8 | import { assert, it } from "@effect/vitest"; | 8 | import { assert, it } from "@effect/vitest"; |
| ... | @@ -36,8 +36,8 @@ class CursorAdapter extends Context.Service<CursorAdapter, CursorAdapterShape>() | ... | @@ -36,8 +36,8 @@ class CursorAdapter extends Context.Service<CursorAdapter, CursorAdapterShape>() |
| 36 | "t3/provider/Layers/CursorAdapter.test/CursorAdapter", | 36 | "t3/provider/Layers/CursorAdapter.test/CursorAdapter", |
| 37 | ) {} | 37 | ) {} |
| 38 | 38 | ||
| 39 | const __dirname = path.dirname(fileURLToPath(import.meta.url)); | 39 | const __dirname = NodePath.dirname(NodeURL.fileURLToPath(import.meta.url)); |
| 40 | const mockAgentPath = path.join(__dirname, "../../../scripts/acp-mock-agent.ts"); | 40 | const mockAgentPath = NodePath.join(__dirname, "../../../scripts/acp-mock-agent.ts"); |
| 41 | const mockAgentCommand = "node"; | 41 | const mockAgentCommand = "node"; |
| 42 | const mockAgentArgs = [mockAgentPath] as const; | 42 | const mockAgentArgs = [mockAgentPath] as const; |
| 43 | 43 | ||
| ... | @@ -45,8 +45,8 @@ async function makeMockAgentWrapper( | ... | @@ -45,8 +45,8 @@ async function makeMockAgentWrapper( |
| 45 | extraEnv?: Record<string, string>, | 45 | extraEnv?: Record<string, string>, |
| 46 | options?: { initialDelaySeconds?: number }, | 46 | options?: { initialDelaySeconds?: number }, |
| 47 | ) { | 47 | ) { |
| 48 | const dir = await mkdtemp(path.join(os.tmpdir(), "cursor-acp-mock-")); | 48 | const dir = await NodeFSP.mkdtemp(NodePath.join(NodeOS.tmpdir(), "cursor-acp-mock-")); |
| 49 | const wrapperPath = path.join(dir, "fake-agent.sh"); | 49 | const wrapperPath = NodePath.join(dir, "fake-agent.sh"); |
| 50 | const envExports = Object.entries(extraEnv ?? {}) | 50 | const envExports = Object.entries(extraEnv ?? {}) |
| 51 | .map(([key, value]) => `export ${key}=${JSON.stringify(value)}`) | 51 | .map(([key, value]) => `export ${key}=${JSON.stringify(value)}`) |
| 52 | .join("\n"); | 52 | .join("\n"); |
| ... | @@ -55,8 +55,8 @@ ${envExports} | ... | @@ -55,8 +55,8 @@ ${envExports} |
| 55 | ${options?.initialDelaySeconds ? `sleep ${JSON.stringify(String(options.initialDelaySeconds))}` : ""} | 55 | ${options?.initialDelaySeconds ? `sleep ${JSON.stringify(String(options.initialDelaySeconds))}` : ""} |
| 56 | exec ${JSON.stringify(mockAgentCommand)} ${mockAgentArgs.map((arg) => JSON.stringify(arg)).join(" ")} "$@" | 56 | exec ${JSON.stringify(mockAgentCommand)} ${mockAgentArgs.map((arg) => JSON.stringify(arg)).join(" ")} "$@" |
| 57 | `; | 57 | `; |
| 58 | await writeFile(wrapperPath, script, "utf8"); | 58 | await NodeFSP.writeFile(wrapperPath, script, "utf8"); |
| 59 | await chmod(wrapperPath, 0o755); | 59 | await NodeFSP.chmod(wrapperPath, 0o755); |
| 60 | return wrapperPath; | 60 | return wrapperPath; |
| 61 | } | 61 | } |
| 62 | 62 | ||
| ... | @@ -65,8 +65,8 @@ async function makeProbeWrapper( | ... | @@ -65,8 +65,8 @@ async function makeProbeWrapper( |
| 65 | argvLogPath: string, | 65 | argvLogPath: string, |
| 66 | extraEnv?: Record<string, string>, | 66 | extraEnv?: Record<string, string>, |
| 67 | ) { | 67 | ) { |
| 68 | const dir = await mkdtemp(path.join(os.tmpdir(), "cursor-acp-probe-")); | 68 | const dir = await NodeFSP.mkdtemp(NodePath.join(NodeOS.tmpdir(), "cursor-acp-probe-")); |
| 69 | const wrapperPath = path.join(dir, "fake-agent.sh"); | 69 | const wrapperPath = NodePath.join(dir, "fake-agent.sh"); |
| 70 | const envExports = Object.entries(extraEnv ?? {}) | 70 | const envExports = Object.entries(extraEnv ?? {}) |
| 71 | .map(([key, value]) => `export ${key}=${JSON.stringify(value)}`) | 71 | .map(([key, value]) => `export ${key}=${JSON.stringify(value)}`) |
| 72 | .join("\n"); | 72 | .join("\n"); |
| ... | @@ -77,13 +77,13 @@ export T3_ACP_REQUEST_LOG_PATH=${JSON.stringify(requestLogPath)} | ... | @@ -77,13 +77,13 @@ export T3_ACP_REQUEST_LOG_PATH=${JSON.stringify(requestLogPath)} |
| 77 | ${envExports} | 77 | ${envExports} |
| 78 | exec ${JSON.stringify(mockAgentCommand)} ${mockAgentArgs.map((arg) => JSON.stringify(arg)).join(" ")} "$@" | 78 | exec ${JSON.stringify(mockAgentCommand)} ${mockAgentArgs.map((arg) => JSON.stringify(arg)).join(" ")} "$@" |
| 79 | `; | 79 | `; |
| 80 | await writeFile(wrapperPath, script, "utf8"); | 80 | await NodeFSP.writeFile(wrapperPath, script, "utf8"); |
| 81 | await chmod(wrapperPath, 0o755); | 81 | await NodeFSP.chmod(wrapperPath, 0o755); |
| 82 | return wrapperPath; | 82 | return wrapperPath; |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | async function readArgvLog(filePath: string) { | 85 | async function readArgvLog(filePath: string) { |
| 86 | const raw = await readFile(filePath, "utf8"); | 86 | const raw = await NodeFSP.readFile(filePath, "utf8"); |
| 87 | return raw | 87 | return raw |
| 88 | .split("\n") | 88 | .split("\n") |
| 89 | .map((line) => line.trim()) | 89 | .map((line) => line.trim()) |
| ... | @@ -92,7 +92,7 @@ async function readArgvLog(filePath: string) { | ... | @@ -92,7 +92,7 @@ async function readArgvLog(filePath: string) { |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | async function readJsonLines(filePath: string) { | 94 | async function readJsonLines(filePath: string) { |
| 95 | const raw = await readFile(filePath, "utf8"); | 95 | const raw = await NodeFSP.readFile(filePath, "utf8"); |
| 96 | return raw | 96 | return raw |
| 97 | .split("\n") | 97 | .split("\n") |
| 98 | .map((line) => line.trim()) | 98 | .map((line) => line.trim()) |
| ... | @@ -103,7 +103,7 @@ async function readJsonLines(filePath: string) { | ... | @@ -103,7 +103,7 @@ async function readJsonLines(filePath: string) { |
| 103 | async function waitForFileContent(filePath: string, attempts = 40) { | 103 | async function waitForFileContent(filePath: string, attempts = 40) { |
| 104 | for (let attempt = 0; attempt < attempts; attempt += 1) { | 104 | for (let attempt = 0; attempt < attempts; attempt += 1) { |
| 105 | try { | 105 | try { |
| 106 | const raw = await readFile(filePath, "utf8"); | 106 | const raw = await NodeFSP.readFile(filePath, "utf8"); |
| 107 | if (raw.trim().length > 0) { | 107 | if (raw.trim().length > 0) { |
| 108 | return raw; | 108 | return raw; |
| 109 | } | 109 | } |
| ... | @@ -315,9 +315,9 @@ cursorAdapterTestLayer("CursorAdapterLive", (it) => { | ... | @@ -315,9 +315,9 @@ cursorAdapterTestLayer("CursorAdapterLive", (it) => { |
| 315 | const settings = yield* ServerSettingsService; | 315 | const settings = yield* ServerSettingsService; |
| 316 | const threadId = ThreadId.make("cursor-stop-session-close"); | 316 | const threadId = ThreadId.make("cursor-stop-session-close"); |
| 317 | const tempDir = yield* Effect.promise(() => | 317 | const tempDir = yield* Effect.promise(() => |
| 318 | mkdtemp(path.join(os.tmpdir(), "cursor-adapter-exit-log-")), | 318 | NodeFSP.mkdtemp(NodePath.join(NodeOS.tmpdir(), "cursor-adapter-exit-log-")), |
| 319 | ); | 319 | ); |
| 320 | const exitLogPath = path.join(tempDir, "exit.log"); | 320 | const exitLogPath = NodePath.join(tempDir, "exit.log"); |
| 321 | 321 | ||
| 322 | const wrapperPath = yield* Effect.promise(() => | 322 | const wrapperPath = yield* Effect.promise(() => |
| 323 | makeMockAgentWrapper({ | 323 | makeMockAgentWrapper({ |
| ... | @@ -349,9 +349,9 @@ cursorAdapterTestLayer("CursorAdapterLive", (it) => { | ... | @@ -349,9 +349,9 @@ cursorAdapterTestLayer("CursorAdapterLive", (it) => { |
| 349 | const settings = yield* ServerSettingsService; | 349 | const settings = yield* ServerSettingsService; |
| 350 | const threadId = ThreadId.make("cursor-concurrent-start-session"); | 350 | const threadId = ThreadId.make("cursor-concurrent-start-session"); |
| 351 | const tempDir = yield* Effect.promise(() => | 351 | const tempDir = yield* Effect.promise(() => |
| 352 | mkdtemp(path.join(os.tmpdir(), "cursor-adapter-concurrent-exit-log-")), | 352 | NodeFSP.mkdtemp(NodePath.join(NodeOS.tmpdir(), "cursor-adapter-concurrent-exit-log-")), |
| 353 | ); | 353 | ); |
| 354 | const exitLogPath = path.join(tempDir, "exit.log"); | 354 | const exitLogPath = NodePath.join(tempDir, "exit.log"); |
| 355 | 355 | ||
| 356 | const wrapperPath = yield* Effect.promise(() => | 356 | const wrapperPath = yield* Effect.promise(() => |
| 357 | makeMockAgentWrapper( | 357 | makeMockAgentWrapper( |
| ... | @@ -414,10 +414,12 @@ cursorAdapterTestLayer("CursorAdapterLive", (it) => { | ... | @@ -414,10 +414,12 @@ cursorAdapterTestLayer("CursorAdapterLive", (it) => { |
| 414 | const adapter = yield* CursorAdapter; | 414 | const adapter = yield* CursorAdapter; |
| 415 | const serverSettings = yield* ServerSettingsService; | 415 | const serverSettings = yield* ServerSettingsService; |
| 416 | const threadId = ThreadId.make("cursor-plan-mode-probe"); | 416 | const threadId = ThreadId.make("cursor-plan-mode-probe"); |
| 417 | const tempDir = yield* Effect.promise(() => mkdtemp(path.join(os.tmpdir(), "cursor-acp-"))); | 417 | const tempDir = yield* Effect.promise(() => |
| 418 | const requestLogPath = path.join(tempDir, "requests.ndjson"); | 418 | NodeFSP.mkdtemp(NodePath.join(NodeOS.tmpdir(), "cursor-acp-")), |
| 419 | const argvLogPath = path.join(tempDir, "argv.txt"); | 419 | ); |
| 420 | yield* Effect.promise(() => writeFile(requestLogPath, "", "utf8")); | 420 | const requestLogPath = NodePath.join(tempDir, "requests.ndjson"); |
| 421 | const argvLogPath = NodePath.join(tempDir, "argv.txt"); | ||
| 422 | yield* Effect.promise(() => NodeFSP.writeFile(requestLogPath, "", "utf8")); | ||
| 421 | const wrapperPath = yield* Effect.promise(() => | 423 | const wrapperPath = yield* Effect.promise(() => |
| 422 | makeProbeWrapper(requestLogPath, argvLogPath), | 424 | makeProbeWrapper(requestLogPath, argvLogPath), |
| 423 | ); | 425 | ); |
| ... | @@ -470,10 +472,12 @@ cursorAdapterTestLayer("CursorAdapterLive", (it) => { | ... | @@ -470,10 +472,12 @@ cursorAdapterTestLayer("CursorAdapterLive", (it) => { |
| 470 | const adapter = yield* CursorAdapter; | 472 | const adapter = yield* CursorAdapter; |
| 471 | const serverSettings = yield* ServerSettingsService; | 473 | const serverSettings = yield* ServerSettingsService; |
| 472 | const threadId = ThreadId.make("cursor-initial-config-probe"); | 474 | const threadId = ThreadId.make("cursor-initial-config-probe"); |
| 473 | const tempDir = yield* Effect.promise(() => mkdtemp(path.join(os.tmpdir(), "cursor-acp-"))); | 475 | const tempDir = yield* Effect.promise(() => |
| 474 | const requestLogPath = path.join(tempDir, "requests.ndjson"); | 476 | NodeFSP.mkdtemp(NodePath.join(NodeOS.tmpdir(), "cursor-acp-")), |
| 475 | const argvLogPath = path.join(tempDir, "argv.txt"); | 477 | ); |
| 476 | yield* Effect.promise(() => writeFile(requestLogPath, "", "utf8")); | 478 | const requestLogPath = NodePath.join(tempDir, "requests.ndjson"); |
| 479 | const argvLogPath = NodePath.join(tempDir, "argv.txt"); | ||
| 480 | yield* Effect.promise(() => NodeFSP.writeFile(requestLogPath, "", "utf8")); | ||
| 477 | const wrapperPath = yield* Effect.promise(() => | 481 | const wrapperPath = yield* Effect.promise(() => |
| 478 | makeProbeWrapper(requestLogPath, argvLogPath), | 482 | makeProbeWrapper(requestLogPath, argvLogPath), |
| 479 | ); | 483 | ); |
| ... | @@ -713,10 +717,12 @@ cursorAdapterTestLayer("CursorAdapterLive", (it) => { | ... | @@ -713,10 +717,12 @@ cursorAdapterTestLayer("CursorAdapterLive", (it) => { |
| 713 | const runtimeEvents: Array<ProviderRuntimeEvent> = []; | 717 | const runtimeEvents: Array<ProviderRuntimeEvent> = []; |
| 714 | const settledEventTypes = new Set<string>(); | 718 | const settledEventTypes = new Set<string>(); |
| 715 | const settledEventsReady = yield* Deferred.make<void>(); | 719 | const settledEventsReady = yield* Deferred.make<void>(); |
| 716 | const tempDir = yield* Effect.promise(() => mkdtemp(path.join(os.tmpdir(), "cursor-acp-"))); | 720 | const tempDir = yield* Effect.promise(() => |
| 717 | const requestLogPath = path.join(tempDir, "requests.ndjson"); | 721 | NodeFSP.mkdtemp(NodePath.join(NodeOS.tmpdir(), "cursor-acp-")), |
| 718 | const argvLogPath = path.join(tempDir, "argv.txt"); | 722 | ); |
| 719 | yield* Effect.promise(() => writeFile(requestLogPath, "", "utf8")); | 723 | const requestLogPath = NodePath.join(tempDir, "requests.ndjson"); |
| 724 | const argvLogPath = NodePath.join(tempDir, "argv.txt"); | ||
| 725 | yield* Effect.promise(() => NodeFSP.writeFile(requestLogPath, "", "utf8")); | ||
| 720 | const wrapperPath = yield* Effect.promise(() => | 726 | const wrapperPath = yield* Effect.promise(() => |
| 721 | makeProbeWrapper(requestLogPath, argvLogPath, { T3_ACP_EMIT_TOOL_CALLS: "1" }), | 727 | makeProbeWrapper(requestLogPath, argvLogPath, { T3_ACP_EMIT_TOOL_CALLS: "1" }), |
| 722 | ); | 728 | ); |
| ... | @@ -931,10 +937,12 @@ cursorAdapterTestLayer("CursorAdapterLive", (it) => { | ... | @@ -931,10 +937,12 @@ cursorAdapterTestLayer("CursorAdapterLive", (it) => { |
| 931 | const adapter = yield* CursorAdapter; | 937 | const adapter = yield* CursorAdapter; |
| 932 | const serverSettings = yield* ServerSettingsService; | 938 | const serverSettings = yield* ServerSettingsService; |
| 933 | const threadId = ThreadId.make("cursor-cancel-probe"); | 939 | const threadId = ThreadId.make("cursor-cancel-probe"); |
| 934 | const tempDir = yield* Effect.promise(() => mkdtemp(path.join(os.tmpdir(), "cursor-acp-"))); | 940 | const tempDir = yield* Effect.promise(() => |
| 935 | const requestLogPath = path.join(tempDir, "requests.ndjson"); | 941 | NodeFSP.mkdtemp(NodePath.join(NodeOS.tmpdir(), "cursor-acp-")), |
| 936 | const argvLogPath = path.join(tempDir, "argv.txt"); | 942 | ); |
| 937 | yield* Effect.promise(() => writeFile(requestLogPath, "", "utf8")); | 943 | const requestLogPath = NodePath.join(tempDir, "requests.ndjson"); |
| 944 | const argvLogPath = NodePath.join(tempDir, "argv.txt"); | ||
| 945 | yield* Effect.promise(() => NodeFSP.writeFile(requestLogPath, "", "utf8")); | ||
| 938 | const wrapperPath = yield* Effect.promise(() => | 946 | const wrapperPath = yield* Effect.promise(() => |
| 939 | makeProbeWrapper(requestLogPath, argvLogPath, { T3_ACP_EMIT_TOOL_CALLS: "1" }), | 947 | makeProbeWrapper(requestLogPath, argvLogPath, { T3_ACP_EMIT_TOOL_CALLS: "1" }), |
| 940 | ); | 948 | ); |
| ... | @@ -1192,10 +1200,12 @@ cursorAdapterTestLayer("CursorAdapterLive", (it) => { | ... | @@ -1192,10 +1200,12 @@ cursorAdapterTestLayer("CursorAdapterLive", (it) => { |
| 1192 | const adapter = yield* CursorAdapter; | 1200 | const adapter = yield* CursorAdapter; |
| 1193 | const serverSettings = yield* ServerSettingsService; | 1201 | const serverSettings = yield* ServerSettingsService; |
| 1194 | const threadId = ThreadId.make("cursor-model-switch"); | 1202 | const threadId = ThreadId.make("cursor-model-switch"); |
| 1195 | const tempDir = yield* Effect.promise(() => mkdtemp(path.join(os.tmpdir(), "cursor-acp-"))); | 1203 | const tempDir = yield* Effect.promise(() => |
| 1196 | const requestLogPath = path.join(tempDir, "requests.ndjson"); | 1204 | NodeFSP.mkdtemp(NodePath.join(NodeOS.tmpdir(), "cursor-acp-")), |
| 1197 | const argvLogPath = path.join(tempDir, "argv.txt"); | 1205 | ); |
| 1198 | yield* Effect.promise(() => writeFile(requestLogPath, "", "utf8")); | 1206 | const requestLogPath = NodePath.join(tempDir, "requests.ndjson"); |
| 1207 | const argvLogPath = NodePath.join(tempDir, "argv.txt"); | ||
| 1208 | yield* Effect.promise(() => NodeFSP.writeFile(requestLogPath, "", "utf8")); | ||
| 1199 | const wrapperPath = yield* Effect.promise(() => | 1209 | const wrapperPath = yield* Effect.promise(() => |
| 1200 | makeProbeWrapper(requestLogPath, argvLogPath), | 1210 | makeProbeWrapper(requestLogPath, argvLogPath), |
| 1201 | ); | 1211 | ); |
| ... | @@ -1255,10 +1265,12 @@ cursorAdapterTestLayer("CursorAdapterLive", (it) => { | ... | @@ -1255,10 +1265,12 @@ cursorAdapterTestLayer("CursorAdapterLive", (it) => { |
| 1255 | const adapter = yield* CursorAdapter; | 1265 | const adapter = yield* CursorAdapter; |
| 1256 | const serverSettings = yield* ServerSettingsService; | 1266 | const serverSettings = yield* ServerSettingsService; |
| 1257 | const threadId = ThreadId.make("cursor-fast-mode-reset"); | 1267 | const threadId = ThreadId.make("cursor-fast-mode-reset"); |
| 1258 | const tempDir = yield* Effect.promise(() => mkdtemp(path.join(os.tmpdir(), "cursor-acp-"))); | 1268 | const tempDir = yield* Effect.promise(() => |
| 1259 | const requestLogPath = path.join(tempDir, "requests.ndjson"); | 1269 | NodeFSP.mkdtemp(NodePath.join(NodeOS.tmpdir(), "cursor-acp-")), |
| 1260 | const argvLogPath = path.join(tempDir, "argv.txt"); | 1270 | ); |
| 1261 | yield* Effect.promise(() => writeFile(requestLogPath, "", "utf8")); | 1271 | const requestLogPath = NodePath.join(tempDir, "requests.ndjson"); |
| 1272 | const argvLogPath = NodePath.join(tempDir, "argv.txt"); | ||
| 1273 | yield* Effect.promise(() => NodeFSP.writeFile(requestLogPath, "", "utf8")); | ||
| 1262 | const wrapperPath = yield* Effect.promise(() => | 1274 | const wrapperPath = yield* Effect.promise(() => |
| 1263 | makeProbeWrapper(requestLogPath, argvLogPath), | 1275 | makeProbeWrapper(requestLogPath, argvLogPath), |
| 1264 | ); | 1276 | ); |
| ... | @@ -1339,10 +1351,12 @@ cursorAdapterTestLayer("CursorAdapterLive", (it) => { | ... | @@ -1339,10 +1351,12 @@ cursorAdapterTestLayer("CursorAdapterLive", (it) => { |
| 1339 | const adapter = yield* CursorAdapter; | 1351 | const adapter = yield* CursorAdapter; |
| 1340 | const serverSettings = yield* ServerSettingsService; | 1352 | const serverSettings = yield* ServerSettingsService; |
| 1341 | const threadId = ThreadId.make("cursor-fast-mode-custom-instance"); | 1353 | const threadId = ThreadId.make("cursor-fast-mode-custom-instance"); |
| 1342 | const tempDir = yield* Effect.promise(() => mkdtemp(path.join(os.tmpdir(), "cursor-acp-"))); | 1354 | const tempDir = yield* Effect.promise(() => |
| 1343 | const requestLogPath = path.join(tempDir, "requests.ndjson"); | 1355 | NodeFSP.mkdtemp(NodePath.join(NodeOS.tmpdir(), "cursor-acp-")), |
| 1344 | const argvLogPath = path.join(tempDir, "argv.txt"); | 1356 | ); |
| 1345 | yield* Effect.promise(() => writeFile(requestLogPath, "", "utf8")); | 1357 | const requestLogPath = NodePath.join(tempDir, "requests.ndjson"); |
| 1358 | const argvLogPath = NodePath.join(tempDir, "argv.txt"); | ||
| 1359 | yield* Effect.promise(() => NodeFSP.writeFile(requestLogPath, "", "utf8")); | ||
| 1346 | const wrapperPath = yield* Effect.promise(() => | 1360 | const wrapperPath = yield* Effect.promise(() => |
| 1347 | makeProbeWrapper(requestLogPath, argvLogPath), | 1361 | makeProbeWrapper(requestLogPath, argvLogPath), |
| 1348 | ); | 1362 | ); |
apps/server/src/provider/Layers/CursorProvider.ts+2-2| ... | @@ -1,4 +1,4 @@ | ... | @@ -1,4 +1,4 @@ |
| 1 | import * as NodeOs from "node:os"; | 1 | import * as NodeOS from "node:os"; |
| 2 | import type { | 2 | import type { |
| 3 | CursorSettings, | 3 | CursorSettings, |
| 4 | ModelCapabilities, | 4 | ModelCapabilities, |
| ... | @@ -746,7 +746,7 @@ function isCursorAboutJsonFormatUnsupported(result: CommandResult): boolean { | ... | @@ -746,7 +746,7 @@ function isCursorAboutJsonFormatUnsupported(result: CommandResult): boolean { |
| 746 | const readCursorCliConfigChannel = Effect.fn("readCursorCliConfigChannel")(function* () { | 746 | const readCursorCliConfigChannel = Effect.fn("readCursorCliConfigChannel")(function* () { |
| 747 | const fileSystem = yield* FileSystem.FileSystem; | 747 | const fileSystem = yield* FileSystem.FileSystem; |
| 748 | const path = yield* Path.Path; | 748 | const path = yield* Path.Path; |
| 749 | const configPath = path.join(NodeOs.homedir(), ".cursor", "cli-config.json"); | 749 | const configPath = path.join(NodeOS.homedir(), ".cursor", "cli-config.json"); |
| 750 | const raw = yield* fileSystem.readFileString(configPath).pipe(Effect.orElseSucceed(() => "")); | 750 | const raw = yield* fileSystem.readFileString(configPath).pipe(Effect.orElseSucceed(() => "")); |
| 751 | return parseCursorCliConfigChannel(raw); | 751 | return parseCursorCliConfigChannel(raw); |
| 752 | }); | 752 | }); |
apps/server/src/provider/Layers/EventNdjsonLogger.test.ts+28-31| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off | 1 | // @effect-diagnostics nodeBuiltinImport:off |
| 2 | import fs from "node:fs"; | 2 | import * as NodeFS from "node:fs"; |
| 3 | import os from "node:os"; | 3 | import * as NodeOS from "node:os"; |
| 4 | import path from "node:path"; | 4 | import * as NodePath from "node:path"; |
| 5 | 5 | ||
| 6 | import { ThreadId } from "@t3tools/contracts"; | 6 | import { ThreadId } from "@t3tools/contracts"; |
| 7 | import { assert, describe, it } from "@effect/vitest"; | 7 | import { assert, describe, it } from "@effect/vitest"; |
| ... | @@ -31,8 +31,8 @@ function parseLogLine(line: string) { | ... | @@ -31,8 +31,8 @@ function parseLogLine(line: string) { |
| 31 | describe("EventNdjsonLogger", () => { | 31 | describe("EventNdjsonLogger", () => { |
| 32 | it.effect("writes effect-style lines to thread-scoped files", () => | 32 | it.effect("writes effect-style lines to thread-scoped files", () => |
| 33 | Effect.gen(function* () { | 33 | Effect.gen(function* () { |
| 34 | const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "t3-provider-log-")); | 34 | const tempDir = NodeFS.mkdtempSync(NodePath.join(NodeOS.tmpdir(), "t3-provider-log-")); |
| 35 | const basePath = path.join(tempDir, "provider-native.ndjson"); | 35 | const basePath = NodePath.join(tempDir, "provider-native.ndjson"); |
| 36 | 36 | ||
| 37 | try { | 37 | try { |
| 38 | const logger = yield* makeEventNdjsonLogger(basePath, { stream: "native" }); | 38 | const logger = yield* makeEventNdjsonLogger(basePath, { stream: "native" }); |
| ... | @@ -51,13 +51,13 @@ describe("EventNdjsonLogger", () => { | ... | @@ -51,13 +51,13 @@ describe("EventNdjsonLogger", () => { |
| 51 | ); | 51 | ); |
| 52 | yield* logger.close(); | 52 | yield* logger.close(); |
| 53 | 53 | ||
| 54 | const threadOnePath = path.join(tempDir, "thread-1.log"); | 54 | const threadOnePath = NodePath.join(tempDir, "thread-1.log"); |
| 55 | const threadTwoPath = path.join(tempDir, "thread-2.log"); | 55 | const threadTwoPath = NodePath.join(tempDir, "thread-2.log"); |
| 56 | assert.equal(fs.existsSync(threadOnePath), true); | 56 | assert.equal(NodeFS.existsSync(threadOnePath), true); |
| 57 | assert.equal(fs.existsSync(threadTwoPath), true); | 57 | assert.equal(NodeFS.existsSync(threadTwoPath), true); |
| 58 | 58 | ||
| 59 | const first = parseLogLine(fs.readFileSync(threadOnePath, "utf8").trim()); | 59 | const first = parseLogLine(NodeFS.readFileSync(threadOnePath, "utf8").trim()); |
| 60 | const second = parseLogLine(fs.readFileSync(threadTwoPath, "utf8").trim()); | 60 | const second = parseLogLine(NodeFS.readFileSync(threadTwoPath, "utf8").trim()); |
| 61 | 61 | ||
| 62 | assert.equal(Number.isNaN(Date.parse(first.observedAt)), false); | 62 | assert.equal(Number.isNaN(Date.parse(first.observedAt)), false); |
| 63 | assert.equal(first.stream, "NTIVE"); | 63 | assert.equal(first.stream, "NTIVE"); |
| ... | @@ -70,7 +70,7 @@ describe("EventNdjsonLogger", () => { | ... | @@ -70,7 +70,7 @@ describe("EventNdjsonLogger", () => { |
| 70 | '{"type":"turn.completed","threadId":"provider-thread-2","id":"evt-2"}', | 70 | '{"type":"turn.completed","threadId":"provider-thread-2","id":"evt-2"}', |
| 71 | ); | 71 | ); |
| 72 | } finally { | 72 | } finally { |
| 73 | fs.rmSync(tempDir, { recursive: true, force: true }); | 73 | NodeFS.rmSync(tempDir, { recursive: true, force: true }); |
| 74 | } | 74 | } |
| 75 | }), | 75 | }), |
| 76 | ); | 76 | ); |
| ... | @@ -79,8 +79,8 @@ describe("EventNdjsonLogger", () => { | ... | @@ -79,8 +79,8 @@ describe("EventNdjsonLogger", () => { |
| 79 | "falls back to a global segment when orchestration thread id is missing or invalid", | 79 | "falls back to a global segment when orchestration thread id is missing or invalid", |
| 80 | () => | 80 | () => |
| 81 | Effect.gen(function* () { | 81 | Effect.gen(function* () { |
| 82 | const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "t3-provider-log-")); | 82 | const tempDir = NodeFS.mkdtempSync(NodePath.join(NodeOS.tmpdir(), "t3-provider-log-")); |
| 83 | const basePath = path.join(tempDir, "provider-canonical.ndjson"); | 83 | const basePath = NodePath.join(tempDir, "provider-canonical.ndjson"); |
| 84 | 84 | ||
| 85 | try { | 85 | try { |
| 86 | const logger = yield* makeEventNdjsonLogger(basePath, { stream: "orchestration" }); | 86 | const logger = yield* makeEventNdjsonLogger(basePath, { stream: "orchestration" }); |
| ... | @@ -93,10 +93,9 @@ describe("EventNdjsonLogger", () => { | ... | @@ -93,10 +93,9 @@ describe("EventNdjsonLogger", () => { |
| 93 | yield* logger.write({ id: "evt-invalid-thread" }, "!!!" as unknown as ThreadId); | 93 | yield* logger.write({ id: "evt-invalid-thread" }, "!!!" as unknown as ThreadId); |
| 94 | yield* logger.close(); | 94 | yield* logger.close(); |
| 95 | 95 | ||
| 96 | const globalPath = path.join(tempDir, "_global.log"); | 96 | const globalPath = NodePath.join(tempDir, "_global.log"); |
| 97 | assert.equal(fs.existsSync(globalPath), true); | 97 | assert.equal(NodeFS.existsSync(globalPath), true); |
| 98 | const lines = fs | 98 | const lines = NodeFS.readFileSync(globalPath, "utf8") |
| 99 | .readFileSync(globalPath, "utf8") | ||
| 100 | .trim() | 99 | .trim() |
| 101 | .split("\n") | 100 | .split("\n") |
| 102 | .map((line) => parseLogLine(line)); | 101 | .map((line) => parseLogLine(line)); |
| ... | @@ -108,15 +107,15 @@ describe("EventNdjsonLogger", () => { | ... | @@ -108,15 +107,15 @@ describe("EventNdjsonLogger", () => { |
| 108 | assert.equal(lines[1]?.stream, "CANON"); | 107 | assert.equal(lines[1]?.stream, "CANON"); |
| 109 | assert.equal(lines[1]?.payload, '{"id":"evt-invalid-thread"}'); | 108 | assert.equal(lines[1]?.payload, '{"id":"evt-invalid-thread"}'); |
| 110 | } finally { | 109 | } finally { |
| 111 | fs.rmSync(tempDir, { recursive: true, force: true }); | 110 | NodeFS.rmSync(tempDir, { recursive: true, force: true }); |
| 112 | } | 111 | } |
| 113 | }), | 112 | }), |
| 114 | ); | 113 | ); |
| 115 | 114 | ||
| 116 | it.effect("serializes concurrent first writes for the same segment", () => | 115 | it.effect("serializes concurrent first writes for the same segment", () => |
| 117 | Effect.gen(function* () { | 116 | Effect.gen(function* () { |
| 118 | const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "t3-provider-log-")); | 117 | const tempDir = NodeFS.mkdtempSync(NodePath.join(NodeOS.tmpdir(), "t3-provider-log-")); |
| 119 | const basePath = path.join(tempDir, "provider-canonical.ndjson"); | 118 | const basePath = NodePath.join(tempDir, "provider-canonical.ndjson"); |
| 120 | 119 | ||
| 121 | try { | 120 | try { |
| 122 | const logger = yield* makeEventNdjsonLogger(basePath, { | 121 | const logger = yield* makeEventNdjsonLogger(basePath, { |
| ... | @@ -137,10 +136,9 @@ describe("EventNdjsonLogger", () => { | ... | @@ -137,10 +136,9 @@ describe("EventNdjsonLogger", () => { |
| 137 | ); | 136 | ); |
| 138 | yield* logger.close(); | 137 | yield* logger.close(); |
| 139 | 138 | ||
| 140 | const globalPath = path.join(tempDir, "_global.log"); | 139 | const globalPath = NodePath.join(tempDir, "_global.log"); |
| 141 | assert.equal(fs.existsSync(globalPath), true); | 140 | assert.equal(NodeFS.existsSync(globalPath), true); |
| 142 | const lines = fs | 141 | const lines = NodeFS.readFileSync(globalPath, "utf8") |
| 143 | .readFileSync(globalPath, "utf8") | ||
| 144 | .trim() | 142 | .trim() |
| 145 | .split("\n") | 143 | .split("\n") |
| 146 | .map((line) => parseLogLine(line)); | 144 | .map((line) => parseLogLine(line)); |
| ... | @@ -151,15 +149,15 @@ describe("EventNdjsonLogger", () => { | ... | @@ -151,15 +149,15 @@ describe("EventNdjsonLogger", () => { |
| 151 | '{"id":"evt-concurrent-2"}', | 149 | '{"id":"evt-concurrent-2"}', |
| 152 | ]); | 150 | ]); |
| 153 | } finally { | 151 | } finally { |
| 154 | fs.rmSync(tempDir, { recursive: true, force: true }); | 152 | NodeFS.rmSync(tempDir, { recursive: true, force: true }); |
| 155 | } | 153 | } |
| 156 | }), | 154 | }), |
| 157 | ); | 155 | ); |
| 158 | 156 | ||
| 159 | it.effect("rotates per-thread files when max size is exceeded", () => | 157 | it.effect("rotates per-thread files when max size is exceeded", () => |
| 160 | Effect.gen(function* () { | 158 | Effect.gen(function* () { |
| 161 | const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "t3-provider-log-")); | 159 | const tempDir = NodeFS.mkdtempSync(NodePath.join(NodeOS.tmpdir(), "t3-provider-log-")); |
| 162 | const basePath = path.join(tempDir, "provider-native.ndjson"); | 160 | const basePath = NodePath.join(tempDir, "provider-native.ndjson"); |
| 163 | 161 | ||
| 164 | try { | 162 | try { |
| 165 | const logger = yield* makeEventNdjsonLogger(basePath, { | 163 | const logger = yield* makeEventNdjsonLogger(basePath, { |
| ... | @@ -185,8 +183,7 @@ describe("EventNdjsonLogger", () => { | ... | @@ -185,8 +183,7 @@ describe("EventNdjsonLogger", () => { |
| 185 | yield* logger.close(); | 183 | yield* logger.close(); |
| 186 | 184 | ||
| 187 | const fileStem = "thread-rotate.log"; | 185 | const fileStem = "thread-rotate.log"; |
| 188 | const matchingFiles = fs | 186 | const matchingFiles = NodeFS.readdirSync(tempDir) |
| 189 | .readdirSync(tempDir) | ||
| 190 | .filter((entry) => entry === fileStem || entry.startsWith(`${fileStem}.`)) | 187 | .filter((entry) => entry === fileStem || entry.startsWith(`${fileStem}.`)) |
| 191 | .toSorted(); | 188 | .toSorted(); |
| 192 | 189 | ||
| ... | @@ -203,7 +200,7 @@ describe("EventNdjsonLogger", () => { | ... | @@ -203,7 +200,7 @@ describe("EventNdjsonLogger", () => { |
| 203 | false, | 200 | false, |
| 204 | ); | 201 | ); |
| 205 | } finally { | 202 | } finally { |
| 206 | fs.rmSync(tempDir, { recursive: true, force: true }); | 203 | NodeFS.rmSync(tempDir, { recursive: true, force: true }); |
| 207 | } | 204 | } |
| 208 | }), | 205 | }), |
| 209 | ); | 206 | ); |
apps/server/src/provider/Layers/EventNdjsonLogger.ts+4-4| ... | @@ -6,8 +6,8 @@ | ... | @@ -6,8 +6,8 @@ |
| 6 | * single effect-style text line in a thread-scoped file. Failures are | 6 | * single effect-style text line in a thread-scoped file. Failures are |
| 7 | * downgraded to warnings so provider runtime behavior is unaffected. | 7 | * downgraded to warnings so provider runtime behavior is unaffected. |
| 8 | */ | 8 | */ |
| 9 | import fs from "node:fs"; | 9 | import * as NodeFS from "node:fs"; |
| 10 | import path from "node:path"; | 10 | import * as NodePath from "node:path"; |
| 11 | 11 | ||
| 12 | import type { ThreadId } from "@t3tools/contracts"; | 12 | import type { ThreadId } from "@t3tools/contracts"; |
| 13 | import { RotatingFileSink } from "@t3tools/shared/logging"; | 13 | import { RotatingFileSink } from "@t3tools/shared/logging"; |
| ... | @@ -178,7 +178,7 @@ export const makeEventNdjsonLogger = Effect.fn("makeEventNdjsonLogger")(function | ... | @@ -178,7 +178,7 @@ export const makeEventNdjsonLogger = Effect.fn("makeEventNdjsonLogger")(function |
| 178 | 178 | ||
| 179 | const directoryReady = yield* Effect.sync(() => { | 179 | const directoryReady = yield* Effect.sync(() => { |
| 180 | try { | 180 | try { |
| 181 | fs.mkdirSync(path.dirname(filePath), { recursive: true }); | 181 | NodeFS.mkdirSync(NodePath.dirname(filePath), { recursive: true }); |
| 182 | return true; | 182 | return true; |
| 183 | } catch (error) { | 183 | } catch (error) { |
| 184 | return { ok: false as const, error }; | 184 | return { ok: false as const, error }; |
| ... | @@ -211,7 +211,7 @@ export const makeEventNdjsonLogger = Effect.fn("makeEventNdjsonLogger")(function | ... | @@ -211,7 +211,7 @@ export const makeEventNdjsonLogger = Effect.fn("makeEventNdjsonLogger")(function |
| 211 | } | 211 | } |
| 212 | 212 | ||
| 213 | return makeThreadWriter({ | 213 | return makeThreadWriter({ |
| 214 | filePath: path.join(path.dirname(filePath), `${threadSegment}.log`), | 214 | filePath: NodePath.join(NodePath.dirname(filePath), `${threadSegment}.log`), |
| 215 | maxBytes, | 215 | maxBytes, |
| 216 | maxFiles, | 216 | maxFiles, |
| 217 | batchWindowMs, | 217 | batchWindowMs, |
apps/server/src/provider/Layers/GrokAdapter.test.ts+18-16| ... | @@ -1,8 +1,8 @@ | ... | @@ -1,8 +1,8 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off | 1 | // @effect-diagnostics nodeBuiltinImport:off |
| 2 | import * as path from "node:path"; | 2 | import * as NodePath from "node:path"; |
| 3 | import * as os from "node:os"; | 3 | import * as NodeOS from "node:os"; |
| 4 | import { chmod, mkdtemp, readFile, writeFile } from "node:fs/promises"; | 4 | import * as NodeFSP from "node:fs/promises"; |
| 5 | import { fileURLToPath } from "node:url"; | 5 | import * as NodeURL from "node:url"; |
| 6 | 6 | ||
| 7 | import * as NodeServices from "@effect/platform-node/NodeServices"; | 7 | import * as NodeServices from "@effect/platform-node/NodeServices"; |
| 8 | import { assert, it } from "@effect/vitest"; | 8 | import { assert, it } from "@effect/vitest"; |
| ... | @@ -26,13 +26,13 @@ import { ServerConfig } from "../../config.ts"; | ... | @@ -26,13 +26,13 @@ import { ServerConfig } from "../../config.ts"; |
| 26 | import { makeGrokAdapter } from "./GrokAdapter.ts"; | 26 | import { makeGrokAdapter } from "./GrokAdapter.ts"; |
| 27 | const decodeGrokSettings = Schema.decodeSync(GrokSettings); | 27 | const decodeGrokSettings = Schema.decodeSync(GrokSettings); |
| 28 | 28 | ||
| 29 | const __dirname = path.dirname(fileURLToPath(import.meta.url)); | 29 | const __dirname = NodePath.dirname(NodeURL.fileURLToPath(import.meta.url)); |
| 30 | const mockAgentPath = path.join(__dirname, "../../../scripts/acp-mock-agent.ts"); | 30 | const mockAgentPath = NodePath.join(__dirname, "../../../scripts/acp-mock-agent.ts"); |
| 31 | const mockAgentCommand = process.execPath; | 31 | const mockAgentCommand = process.execPath; |
| 32 | 32 | ||
| 33 | async function makeMockGrokWrapper(extraEnv?: Record<string, string>) { | 33 | async function makeMockGrokWrapper(extraEnv?: Record<string, string>) { |
| 34 | const dir = await mkdtemp(path.join(os.tmpdir(), "grok-acp-mock-")); | 34 | const dir = await NodeFSP.mkdtemp(NodePath.join(NodeOS.tmpdir(), "grok-acp-mock-")); |
| 35 | const wrapperPath = path.join(dir, "fake-grok.sh"); | 35 | const wrapperPath = NodePath.join(dir, "fake-grok.sh"); |
| 36 | const envExports = Object.entries(extraEnv ?? {}) | 36 | const envExports = Object.entries(extraEnv ?? {}) |
| 37 | .map(([key, value]) => `export ${key}=${JSON.stringify(value)}`) | 37 | .map(([key, value]) => `export ${key}=${JSON.stringify(value)}`) |
| 38 | .join("\n"); | 38 | .join("\n"); |
| ... | @@ -40,8 +40,8 @@ async function makeMockGrokWrapper(extraEnv?: Record<string, string>) { | ... | @@ -40,8 +40,8 @@ async function makeMockGrokWrapper(extraEnv?: Record<string, string>) { |
| 40 | ${envExports} | 40 | ${envExports} |
| 41 | exec ${JSON.stringify(mockAgentCommand)} ${JSON.stringify(mockAgentPath)} "$@" | 41 | exec ${JSON.stringify(mockAgentCommand)} ${JSON.stringify(mockAgentPath)} "$@" |
| 42 | `; | 42 | `; |
| 43 | await writeFile(wrapperPath, script, "utf8"); | 43 | await NodeFSP.writeFile(wrapperPath, script, "utf8"); |
| 44 | await chmod(wrapperPath, 0o755); | 44 | await NodeFSP.chmod(wrapperPath, 0o755); |
| 45 | return wrapperPath; | 45 | return wrapperPath; |
| 46 | } | 46 | } |
| 47 | 47 | ||
| ... | @@ -51,7 +51,7 @@ function waitForFileContent(filePath: string, attempts = 40): Effect.Effect<stri | ... | @@ -51,7 +51,7 @@ function waitForFileContent(filePath: string, attempts = 40): Effect.Effect<stri |
| 51 | if (remainingAttempts <= 0) { | 51 | if (remainingAttempts <= 0) { |
| 52 | return yield* Effect.die(new Error(`Timed out waiting for file content at ${filePath}`)); | 52 | return yield* Effect.die(new Error(`Timed out waiting for file content at ${filePath}`)); |
| 53 | } | 53 | } |
| 54 | const raw = yield* Effect.tryPromise(() => readFile(filePath, "utf8")).pipe( | 54 | const raw = yield* Effect.tryPromise(() => NodeFSP.readFile(filePath, "utf8")).pipe( |
| 55 | Effect.orElseSucceed(() => ""), | 55 | Effect.orElseSucceed(() => ""), |
| 56 | ); | 56 | ); |
| 57 | if (raw.trim().length > 0) { | 57 | if (raw.trim().length > 0) { |
| ... | @@ -64,7 +64,7 @@ function waitForFileContent(filePath: string, attempts = 40): Effect.Effect<stri | ... | @@ -64,7 +64,7 @@ function waitForFileContent(filePath: string, attempts = 40): Effect.Effect<stri |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | async function readJsonLines(filePath: string) { | 66 | async function readJsonLines(filePath: string) { |
| 67 | const raw = await readFile(filePath, "utf8"); | 67 | const raw = await NodeFSP.readFile(filePath, "utf8"); |
| 68 | return raw | 68 | return raw |
| 69 | .split("\n") | 69 | .split("\n") |
| 70 | .map((line) => line.trim()) | 70 | .map((line) => line.trim()) |
| ... | @@ -149,9 +149,9 @@ it.layer(grokAdapterTestLayer)("GrokAdapterLive", (it) => { | ... | @@ -149,9 +149,9 @@ it.layer(grokAdapterTestLayer)("GrokAdapterLive", (it) => { |
| 149 | Effect.gen(function* () { | 149 | Effect.gen(function* () { |
| 150 | const threadId = ThreadId.make("grok-stop-session-close"); | 150 | const threadId = ThreadId.make("grok-stop-session-close"); |
| 151 | const tempDir = yield* Effect.promise(() => | 151 | const tempDir = yield* Effect.promise(() => |
| 152 | mkdtemp(path.join(os.tmpdir(), "grok-adapter-exit-log-")), | 152 | NodeFSP.mkdtemp(NodePath.join(NodeOS.tmpdir(), "grok-adapter-exit-log-")), |
| 153 | ); | 153 | ); |
| 154 | const exitLogPath = path.join(tempDir, "exit.log"); | 154 | const exitLogPath = NodePath.join(tempDir, "exit.log"); |
| 155 | 155 | ||
| 156 | const wrapperPath = yield* Effect.promise(() => | 156 | const wrapperPath = yield* Effect.promise(() => |
| 157 | makeMockGrokWrapper({ | 157 | makeMockGrokWrapper({ |
| ... | @@ -227,8 +227,10 @@ it.layer(grokAdapterTestLayer)("GrokAdapterLive", (it) => { | ... | @@ -227,8 +227,10 @@ it.layer(grokAdapterTestLayer)("GrokAdapterLive", (it) => { |
| 227 | it.effect("responds to ACP approvals using provider-supplied option ids", () => | 227 | it.effect("responds to ACP approvals using provider-supplied option ids", () => |
| 228 | Effect.gen(function* () { | 228 | Effect.gen(function* () { |
| 229 | const threadId = ThreadId.make("grok-custom-approval-option-id"); | 229 | const threadId = ThreadId.make("grok-custom-approval-option-id"); |
| 230 | const tempDir = yield* Effect.promise(() => mkdtemp(path.join(os.tmpdir(), "grok-acp-"))); | 230 | const tempDir = yield* Effect.promise(() => |
| 231 | const requestLogPath = path.join(tempDir, "requests.ndjson"); | 231 | NodeFSP.mkdtemp(NodePath.join(NodeOS.tmpdir(), "grok-acp-")), |
| 232 | ); | ||
| 233 | const requestLogPath = NodePath.join(tempDir, "requests.ndjson"); | ||
| 232 | const wrapperPath = yield* Effect.promise(() => | 234 | const wrapperPath = yield* Effect.promise(() => |
| 233 | makeMockGrokWrapper({ | 235 | makeMockGrokWrapper({ |
| 234 | T3_ACP_REQUEST_LOG_PATH: requestLogPath, | 236 | T3_ACP_REQUEST_LOG_PATH: requestLogPath, |
apps/server/src/provider/Layers/OpenCodeAdapter.test.ts+48-48| ... | @@ -1,4 +1,4 @@ | ... | @@ -1,4 +1,4 @@ |
| 1 | import assert from "node:assert/strict"; | 1 | import * as NodeAssert from "node:assert/strict"; |
| 2 | import * as NodeServices from "@effect/platform-node/NodeServices"; | 2 | import * as NodeServices from "@effect/platform-node/NodeServices"; |
| 3 | import { it } from "@effect/vitest"; | 3 | import { it } from "@effect/vitest"; |
| 4 | import * as Context from "effect/Context"; | 4 | import * as Context from "effect/Context"; |
| ... | @@ -238,11 +238,11 @@ it.layer(OpenCodeAdapterTestLayer)("OpenCodeAdapterLive", (it) => { | ... | @@ -238,11 +238,11 @@ it.layer(OpenCodeAdapterTestLayer)("OpenCodeAdapterLive", (it) => { |
| 238 | runtimeMode: "full-access", | 238 | runtimeMode: "full-access", |
| 239 | }); | 239 | }); |
| 240 | 240 | ||
| 241 | assert.equal(session.provider, "opencode"); | 241 | NodeAssert.equal(session.provider, "opencode"); |
| 242 | assert.equal(session.threadId, "thread-opencode"); | 242 | NodeAssert.equal(session.threadId, "thread-opencode"); |
| 243 | assert.deepEqual(runtimeMock.state.startCalls, []); | 243 | NodeAssert.deepEqual(runtimeMock.state.startCalls, []); |
| 244 | assert.deepEqual(runtimeMock.state.sessionCreateUrls, ["http://127.0.0.1:9999"]); | 244 | NodeAssert.deepEqual(runtimeMock.state.sessionCreateUrls, ["http://127.0.0.1:9999"]); |
| 245 | assert.deepEqual(runtimeMock.state.authHeaders, [ | 245 | NodeAssert.deepEqual(runtimeMock.state.authHeaders, [ |
| 246 | `Basic ${btoa("opencode:secret-password")}`, | 246 | `Basic ${btoa("opencode:secret-password")}`, |
| 247 | ]); | 247 | ]); |
| 248 | }), | 248 | }), |
| ... | @@ -259,8 +259,8 @@ it.layer(OpenCodeAdapterTestLayer)("OpenCodeAdapterLive", (it) => { | ... | @@ -259,8 +259,8 @@ it.layer(OpenCodeAdapterTestLayer)("OpenCodeAdapterLive", (it) => { |
| 259 | 259 | ||
| 260 | yield* adapter.stopSession(asThreadId("thread-opencode")); | 260 | yield* adapter.stopSession(asThreadId("thread-opencode")); |
| 261 | 261 | ||
| 262 | assert.deepEqual(runtimeMock.state.startCalls, []); | 262 | NodeAssert.deepEqual(runtimeMock.state.startCalls, []); |
| 263 | assert.deepEqual( | 263 | NodeAssert.deepEqual( |
| 264 | runtimeMock.state.abortCalls.includes("http://127.0.0.1:9999/session"), | 264 | runtimeMock.state.abortCalls.includes("http://127.0.0.1:9999/session"), |
| 265 | true, | 265 | true, |
| 266 | ); | 266 | ); |
| ... | @@ -286,7 +286,7 @@ it.layer(OpenCodeAdapterTestLayer)("OpenCodeAdapterLive", (it) => { | ... | @@ -286,7 +286,7 @@ it.layer(OpenCodeAdapterTestLayer)("OpenCodeAdapterLive", (it) => { |
| 286 | yield* adapter.stopSession(threadId); | 286 | yield* adapter.stopSession(threadId); |
| 287 | 287 | ||
| 288 | const events = Array.from(yield* Fiber.join(eventsFiber).pipe(Effect.timeout("1 second"))); | 288 | const events = Array.from(yield* Fiber.join(eventsFiber).pipe(Effect.timeout("1 second"))); |
| 289 | assert.deepEqual( | 289 | NodeAssert.deepEqual( |
| 290 | events.map((event) => event.type), | 290 | events.map((event) => event.type), |
| 291 | ["session.started", "thread.started", "session.exited"], | 291 | ["session.started", "thread.started", "session.exited"], |
| 292 | ); | 292 | ); |
| ... | @@ -316,11 +316,11 @@ it.layer(OpenCodeAdapterTestLayer)("OpenCodeAdapterLive", (it) => { | ... | @@ -316,11 +316,11 @@ it.layer(OpenCodeAdapterTestLayer)("OpenCodeAdapterLive", (it) => { |
| 316 | yield* Effect.exit(adapter.stopAll()); | 316 | yield* Effect.exit(adapter.stopAll()); |
| 317 | const sessions = yield* adapter.listSessions(); | 317 | const sessions = yield* adapter.listSessions(); |
| 318 | 318 | ||
| 319 | assert.deepEqual(runtimeMock.state.closeCalls, [ | 319 | NodeAssert.deepEqual(runtimeMock.state.closeCalls, [ |
| 320 | "http://127.0.0.1:9999", | 320 | "http://127.0.0.1:9999", |
| 321 | "http://127.0.0.1:9999", | 321 | "http://127.0.0.1:9999", |
| 322 | ]); | 322 | ]); |
| 323 | assert.deepEqual(sessions, []); | 323 | NodeAssert.deepEqual(sessions, []); |
| 324 | }), | 324 | }), |
| 325 | ); | 325 | ); |
| 326 | 326 | ||
| ... | @@ -348,7 +348,7 @@ it.layer(OpenCodeAdapterTestLayer)("OpenCodeAdapterLive", (it) => { | ... | @@ -348,7 +348,7 @@ it.layer(OpenCodeAdapterTestLayer)("OpenCodeAdapterLive", (it) => { |
| 348 | scopeClosed = true; | 348 | scopeClosed = true; |
| 349 | 349 | ||
| 350 | const exit = yield* Fiber.await(eventsFiber).pipe(Effect.timeout("1 second")); | 350 | const exit = yield* Fiber.await(eventsFiber).pipe(Effect.timeout("1 second")); |
| 351 | assert.equal(Exit.hasInterrupts(exit), true); | 351 | NodeAssert.equal(Exit.hasInterrupts(exit), true); |
| 352 | } finally { | 352 | } finally { |
| 353 | if (!scopeClosed) { | 353 | if (!scopeClosed) { |
| 354 | yield* Scope.close(scope, Exit.void).pipe(Effect.ignore); | 354 | yield* Scope.close(scope, Exit.void).pipe(Effect.ignore); |
| ... | @@ -379,19 +379,19 @@ it.layer(OpenCodeAdapterTestLayer)("OpenCodeAdapterLive", (it) => { | ... | @@ -379,19 +379,19 @@ it.layer(OpenCodeAdapterTestLayer)("OpenCodeAdapterLive", (it) => { |
| 379 | .pipe(Effect.flip); | 379 | .pipe(Effect.flip); |
| 380 | const sessions = yield* adapter.listSessions(); | 380 | const sessions = yield* adapter.listSessions(); |
| 381 | 381 | ||
| 382 | assert.equal(error._tag, "ProviderAdapterRequestError"); | 382 | NodeAssert.equal(error._tag, "ProviderAdapterRequestError"); |
| 383 | if (error._tag !== "ProviderAdapterRequestError") { | 383 | if (error._tag !== "ProviderAdapterRequestError") { |
| 384 | throw new Error("Unexpected error type"); | 384 | throw new Error("Unexpected error type"); |
| 385 | } | 385 | } |
| 386 | assert.equal(error.detail, "prompt failed"); | 386 | NodeAssert.equal(error.detail, "prompt failed"); |
| 387 | assert.equal( | 387 | NodeAssert.equal( |
| 388 | error.message, | 388 | error.message, |
| 389 | "Provider adapter request failed (opencode) for session.promptAsync: prompt failed", | 389 | "Provider adapter request failed (opencode) for session.promptAsync: prompt failed", |
| 390 | ); | 390 | ); |
| 391 | assert.equal(sessions.length, 1); | 391 | NodeAssert.equal(sessions.length, 1); |
| 392 | assert.equal(sessions[0]?.status, "ready"); | 392 | NodeAssert.equal(sessions[0]?.status, "ready"); |
| 393 | assert.equal(sessions[0]?.activeTurnId, undefined); | 393 | NodeAssert.equal(sessions[0]?.activeTurnId, undefined); |
| 394 | assert.equal(sessions[0]?.lastError, "prompt failed"); | 394 | NodeAssert.equal(sessions[0]?.lastError, "prompt failed"); |
| 395 | }), | 395 | }), |
| 396 | ); | 396 | ); |
| 397 | 397 | ||
| ... | @@ -424,13 +424,13 @@ it.layer(OpenCodeAdapterTestLayer)("OpenCodeAdapterLive", (it) => { | ... | @@ -424,13 +424,13 @@ it.layer(OpenCodeAdapterTestLayer)("OpenCodeAdapterLive", (it) => { |
| 424 | model: "openai/gpt-5", | 424 | model: "openai/gpt-5", |
| 425 | }, | 425 | }, |
| 426 | }); | 426 | }); |
| 427 | assert.equal(String(steeredTurn.turnId), String(turn.turnId)); | 427 | NodeAssert.equal(String(steeredTurn.turnId), String(turn.turnId)); |
| 428 | 428 | ||
| 429 | const sessions = yield* adapter.listSessions(); | 429 | const sessions = yield* adapter.listSessions(); |
| 430 | const session = sessions.find((entry) => entry.threadId === threadId); | 430 | const session = sessions.find((entry) => entry.threadId === threadId); |
| 431 | assert.equal(session?.status, "running"); | 431 | NodeAssert.equal(session?.status, "running"); |
| 432 | assert.equal(String(session?.activeTurnId), String(turn.turnId)); | 432 | NodeAssert.equal(String(session?.activeTurnId), String(turn.turnId)); |
| 433 | assert.equal(runtimeMock.state.promptCalls.length, 2); | 433 | NodeAssert.equal(runtimeMock.state.promptCalls.length, 2); |
| 434 | }), | 434 | }), |
| 435 | ); | 435 | ); |
| 436 | 436 | ||
| ... | @@ -466,11 +466,11 @@ it.layer(OpenCodeAdapterTestLayer)("OpenCodeAdapterLive", (it) => { | ... | @@ -466,11 +466,11 @@ it.layer(OpenCodeAdapterTestLayer)("OpenCodeAdapterLive", (it) => { |
| 466 | .pipe(Effect.flip); | 466 | .pipe(Effect.flip); |
| 467 | 467 | ||
| 468 | // The original turn keeps running — only the steer prompt failed. | 468 | // The original turn keeps running — only the steer prompt failed. |
| 469 | assert.equal(error._tag, "ProviderAdapterRequestError"); | 469 | NodeAssert.equal(error._tag, "ProviderAdapterRequestError"); |
| 470 | const sessions = yield* adapter.listSessions(); | 470 | const sessions = yield* adapter.listSessions(); |
| 471 | const session = sessions.find((entry) => entry.threadId === threadId); | 471 | const session = sessions.find((entry) => entry.threadId === threadId); |
| 472 | assert.equal(session?.status, "running"); | 472 | NodeAssert.equal(session?.status, "running"); |
| 473 | assert.equal(String(session?.activeTurnId), String(turn.turnId)); | 473 | NodeAssert.equal(String(session?.activeTurnId), String(turn.turnId)); |
| 474 | }), | 474 | }), |
| 475 | ); | 475 | ); |
| 476 | 476 | ||
| ... | @@ -508,7 +508,7 @@ it.layer(OpenCodeAdapterTestLayer)("OpenCodeAdapterLive", (it) => { | ... | @@ -508,7 +508,7 @@ it.layer(OpenCodeAdapterTestLayer)("OpenCodeAdapterLive", (it) => { |
| 508 | ), | 508 | ), |
| 509 | }); | 509 | }); |
| 510 | 510 | ||
| 511 | assert.deepEqual(runtimeMock.state.promptCalls.at(-1), { | 511 | NodeAssert.deepEqual(runtimeMock.state.promptCalls.at(-1), { |
| 512 | sessionID: "http://127.0.0.1:9999/session", | 512 | sessionID: "http://127.0.0.1:9999/session", |
| 513 | model: { | 513 | model: { |
| 514 | providerID: "anthropic", | 514 | providerID: "anthropic", |
| ... | @@ -552,7 +552,7 @@ it.layer(OpenCodeAdapterTestLayer)("OpenCodeAdapterLive", (it) => { | ... | @@ -552,7 +552,7 @@ it.layer(OpenCodeAdapterTestLayer)("OpenCodeAdapterLive", (it) => { |
| 552 | input: "Fix it", | 552 | input: "Fix it", |
| 553 | }); | 553 | }); |
| 554 | 554 | ||
| 555 | assert.deepEqual(runtimeMock.state.promptCalls.at(-1), { | 555 | NodeAssert.deepEqual(runtimeMock.state.promptCalls.at(-1), { |
| 556 | sessionID: "http://127.0.0.1:9999/session", | 556 | sessionID: "http://127.0.0.1:9999/session", |
| 557 | model: { | 557 | model: { |
| 558 | providerID: "anthropic", | 558 | providerID: "anthropic", |
| ... | @@ -596,15 +596,15 @@ it.layer(OpenCodeAdapterTestLayer)("OpenCodeAdapterLive", (it) => { | ... | @@ -596,15 +596,15 @@ it.layer(OpenCodeAdapterTestLayer)("OpenCodeAdapterLive", (it) => { |
| 596 | }) | 596 | }) |
| 597 | .pipe(Effect.flip); | 597 | .pipe(Effect.flip); |
| 598 | 598 | ||
| 599 | assert.equal(error._tag, "ProviderAdapterValidationError"); | 599 | NodeAssert.equal(error._tag, "ProviderAdapterValidationError"); |
| 600 | if (error._tag !== "ProviderAdapterValidationError") { | 600 | if (error._tag !== "ProviderAdapterValidationError") { |
| 601 | throw new Error("Unexpected error type"); | 601 | throw new Error("Unexpected error type"); |
| 602 | } | 602 | } |
| 603 | assert.equal( | 603 | NodeAssert.equal( |
| 604 | error.issue, | 604 | error.issue, |
| 605 | "OpenCode model selection is bound to instance 'opencode', expected 'opencode_zen'.", | 605 | "OpenCode model selection is bound to instance 'opencode', expected 'opencode_zen'.", |
| 606 | ); | 606 | ); |
| 607 | assert.deepEqual(runtimeMock.state.promptCalls, []); | 607 | NodeAssert.deepEqual(runtimeMock.state.promptCalls, []); |
| 608 | }).pipe(Effect.provide(adapterLayer)); | 608 | }).pipe(Effect.provide(adapterLayer)); |
| 609 | }); | 609 | }); |
| 610 | 610 | ||
| ... | @@ -631,10 +631,10 @@ it.layer(OpenCodeAdapterTestLayer)("OpenCodeAdapterLive", (it) => { | ... | @@ -631,10 +631,10 @@ it.layer(OpenCodeAdapterTestLayer)("OpenCodeAdapterLive", (it) => { |
| 631 | 631 | ||
| 632 | const snapshot = yield* adapter.rollbackThread(threadId, 2); | 632 | const snapshot = yield* adapter.rollbackThread(threadId, 2); |
| 633 | 633 | ||
| 634 | assert.deepEqual(runtimeMock.state.revertCalls, [ | 634 | NodeAssert.deepEqual(runtimeMock.state.revertCalls, [ |
| 635 | { sessionID: "http://127.0.0.1:9999/session" }, | 635 | { sessionID: "http://127.0.0.1:9999/session" }, |
| 636 | ]); | 636 | ]); |
| 637 | assert.deepEqual(snapshot.turns, []); | 637 | NodeAssert.deepEqual(snapshot.turns, []); |
| 638 | }), | 638 | }), |
| 639 | ); | 639 | ); |
| 640 | 640 | ||
| ... | @@ -644,11 +644,11 @@ it.layer(OpenCodeAdapterTestLayer)("OpenCodeAdapterLive", (it) => { | ... | @@ -644,11 +644,11 @@ it.layer(OpenCodeAdapterTestLayer)("OpenCodeAdapterLive", (it) => { |
| 644 | const overlapDelta = appendOpenCodeAssistantTextDelta(firstUpdate.latestText, "lo world"); | 644 | const overlapDelta = appendOpenCodeAssistantTextDelta(firstUpdate.latestText, "lo world"); |
| 645 | const secondUpdate = mergeOpenCodeAssistantText(overlapDelta.nextText, "Hellolo world"); | 645 | const secondUpdate = mergeOpenCodeAssistantText(overlapDelta.nextText, "Hellolo world"); |
| 646 | 646 | ||
| 647 | assert.deepEqual( | 647 | NodeAssert.deepEqual( |
| 648 | [firstUpdate.deltaToEmit, overlapDelta.deltaToEmit, secondUpdate.deltaToEmit], | 648 | [firstUpdate.deltaToEmit, overlapDelta.deltaToEmit, secondUpdate.deltaToEmit], |
| 649 | ["Hello", "lo world", ""], | 649 | ["Hello", "lo world", ""], |
| 650 | ); | 650 | ); |
| 651 | assert.equal(secondUpdate.latestText, "Hellolo world"); | 651 | NodeAssert.equal(secondUpdate.latestText, "Hellolo world"); |
| 652 | }), | 652 | }), |
| 653 | ); | 653 | ); |
| 654 | 654 | ||
| ... | @@ -721,14 +721,14 @@ it.layer(OpenCodeAdapterTestLayer)("OpenCodeAdapterLive", (it) => { | ... | @@ -721,14 +721,14 @@ it.layer(OpenCodeAdapterTestLayer)("OpenCodeAdapterLive", (it) => { |
| 721 | 721 | ||
| 722 | const events = Array.from(yield* Fiber.join(eventsFiber).pipe(Effect.timeout("1 second"))); | 722 | const events = Array.from(yield* Fiber.join(eventsFiber).pipe(Effect.timeout("1 second"))); |
| 723 | const deltas = events.filter((event) => event.type === "content.delta"); | 723 | const deltas = events.filter((event) => event.type === "content.delta"); |
| 724 | assert.deepEqual( | 724 | NodeAssert.deepEqual( |
| 725 | deltas.map((event) => (event.type === "content.delta" ? event.payload.delta : "")), | 725 | deltas.map((event) => (event.type === "content.delta" ? event.payload.delta : "")), |
| 726 | ["A B", "Bonus"], | 726 | ["A B", "Bonus"], |
| 727 | ); | 727 | ); |
| 728 | assert.equal(events.at(-1)?.type, "item.completed"); | 728 | NodeAssert.equal(events.at(-1)?.type, "item.completed"); |
| 729 | const completed = events.at(-1); | 729 | const completed = events.at(-1); |
| 730 | if (completed?.type === "item.completed") { | 730 | if (completed?.type === "item.completed") { |
| 731 | assert.equal(completed.payload.detail, "A BBonus"); | 731 | NodeAssert.equal(completed.payload.detail, "A BBonus"); |
| 732 | } | 732 | } |
| 733 | }), | 733 | }), |
| 734 | ); | 734 | ); |
| ... | @@ -820,27 +820,27 @@ it.layer(OpenCodeAdapterTestLayer)("OpenCodeAdapterLive", (it) => { | ... | @@ -820,27 +820,27 @@ it.layer(OpenCodeAdapterTestLayer)("OpenCodeAdapterLive", (it) => { |
| 820 | return started; | 820 | return started; |
| 821 | }).pipe(Effect.provide(adapterLayer)); | 821 | }).pipe(Effect.provide(adapterLayer)); |
| 822 | 822 | ||
| 823 | assert.equal(session.threadId, "thread-native-log"); | 823 | NodeAssert.equal(session.threadId, "thread-native-log"); |
| 824 | assert.equal(nativeEvents.length, 1); | 824 | NodeAssert.equal(nativeEvents.length, 1); |
| 825 | assert.equal( | 825 | NodeAssert.equal( |
| 826 | nativeEvents.some((record) => record.event?.provider === "opencode"), | 826 | nativeEvents.some((record) => record.event?.provider === "opencode"), |
| 827 | true, | 827 | true, |
| 828 | ); | 828 | ); |
| 829 | assert.equal( | 829 | NodeAssert.equal( |
| 830 | nativeEvents.some( | 830 | nativeEvents.some( |
| 831 | (record) => record.event?.providerThreadId === "http://127.0.0.1:9999/session", | 831 | (record) => record.event?.providerThreadId === "http://127.0.0.1:9999/session", |
| 832 | ), | 832 | ), |
| 833 | true, | 833 | true, |
| 834 | ); | 834 | ); |
| 835 | assert.equal( | 835 | NodeAssert.equal( |
| 836 | nativeEvents.some((record) => record.event?.threadId === "thread-native-log"), | 836 | nativeEvents.some((record) => record.event?.threadId === "thread-native-log"), |
| 837 | true, | 837 | true, |
| 838 | ); | 838 | ); |
| 839 | assert.equal( | 839 | NodeAssert.equal( |
| 840 | nativeEvents.some((record) => record.event?.type === "message.updated"), | 840 | nativeEvents.some((record) => record.event?.type === "message.updated"), |
| 841 | true, | 841 | true, |
| 842 | ); | 842 | ); |
| 843 | assert.equal( | 843 | NodeAssert.equal( |
| 844 | nativeThreadIds.every((threadId) => threadId === "thread-native-log"), | 844 | nativeThreadIds.every((threadId) => threadId === "thread-native-log"), |
| 845 | true, | 845 | true, |
| 846 | ); | 846 | ); |
| ... | @@ -911,9 +911,9 @@ it.layer(OpenCodeAdapterTestLayer)("OpenCodeAdapterLive", (it) => { | ... | @@ -911,9 +911,9 @@ it.layer(OpenCodeAdapterTestLayer)("OpenCodeAdapterLive", (it) => { |
| 911 | }; | 911 | }; |
| 912 | }).pipe(Effect.provide(adapterLayer)); | 912 | }).pipe(Effect.provide(adapterLayer)); |
| 913 | 913 | ||
| 914 | assert.equal(sessions.length, 1); | 914 | NodeAssert.equal(sessions.length, 1); |
| 915 | assert.equal(sessions[0]?.threadId, "thread-native-log-failure"); | 915 | NodeAssert.equal(sessions[0]?.threadId, "thread-native-log-failure"); |
| 916 | assert.deepEqual(closeCallsDuringRun, []); | 916 | NodeAssert.deepEqual(closeCallsDuringRun, []); |
| 917 | }), | 917 | }), |
| 918 | ); | 918 | ); |
| 919 | }); | 919 | }); |
apps/server/src/provider/Layers/OpenCodeProvider.test.ts+22-19| ... | @@ -1,4 +1,4 @@ | ... | @@ -1,4 +1,4 @@ |
| 1 | import assert from "node:assert/strict"; | 1 | import * as NodeAssert from "node:assert/strict"; |
| 2 | 2 | ||
| 3 | import * as NodeServices from "@effect/platform-node/NodeServices"; | 3 | import * as NodeServices from "@effect/platform-node/NodeServices"; |
| 4 | import { it } from "@effect/vitest"; | 4 | import { it } from "@effect/vitest"; |
| ... | @@ -122,9 +122,12 @@ it.layer(testLayer)("checkOpenCodeProviderStatus", (it) => { | ... | @@ -122,9 +122,12 @@ it.layer(testLayer)("checkOpenCodeProviderStatus", (it) => { |
| 122 | runtimeMock.state.runVersionError = new Error("spawn opencode ENOENT"); | 122 | runtimeMock.state.runVersionError = new Error("spawn opencode ENOENT"); |
| 123 | const snapshot = yield* checkOpenCodeProviderStatus(makeOpenCodeSettings(), process.cwd()); | 123 | const snapshot = yield* checkOpenCodeProviderStatus(makeOpenCodeSettings(), process.cwd()); |
| 124 | 124 | ||
| 125 | assert.equal(snapshot.status, "error"); | 125 | NodeAssert.equal(snapshot.status, "error"); |
| 126 | assert.equal(snapshot.installed, false); | 126 | NodeAssert.equal(snapshot.installed, false); |
| 127 | assert.equal(snapshot.message, "OpenCode CLI (`opencode`) is not installed or not on PATH."); | 127 | NodeAssert.equal( |
| 128 | snapshot.message, | ||
| 129 | "OpenCode CLI (`opencode`) is not installed or not on PATH.", | ||
| 130 | ); | ||
| 128 | }), | 131 | }), |
| 129 | ); | 132 | ); |
| 130 | 133 | ||
| ... | @@ -133,9 +136,9 @@ it.layer(testLayer)("checkOpenCodeProviderStatus", (it) => { | ... | @@ -133,9 +136,9 @@ it.layer(testLayer)("checkOpenCodeProviderStatus", (it) => { |
| 133 | runtimeMock.state.runVersionError = new Error("An error occurred in Effect.tryPromise"); | 136 | runtimeMock.state.runVersionError = new Error("An error occurred in Effect.tryPromise"); |
| 134 | const snapshot = yield* checkOpenCodeProviderStatus(makeOpenCodeSettings(), process.cwd()); | 137 | const snapshot = yield* checkOpenCodeProviderStatus(makeOpenCodeSettings(), process.cwd()); |
| 135 | 138 | ||
| 136 | assert.equal(snapshot.status, "error"); | 139 | NodeAssert.equal(snapshot.status, "error"); |
| 137 | assert.equal(snapshot.installed, true); | 140 | NodeAssert.equal(snapshot.installed, true); |
| 138 | assert.equal(snapshot.message, "Failed to execute OpenCode CLI health check."); | 141 | NodeAssert.equal(snapshot.message, "Failed to execute OpenCode CLI health check."); |
| 139 | }), | 142 | }), |
| 140 | ); | 143 | ); |
| 141 | 144 | ||
| ... | @@ -174,20 +177,20 @@ it.layer(testLayer)("checkOpenCodeProviderStatus", (it) => { | ... | @@ -174,20 +177,20 @@ it.layer(testLayer)("checkOpenCodeProviderStatus", (it) => { |
| 174 | const snapshot = yield* checkOpenCodeProviderStatus(makeOpenCodeSettings(), process.cwd()); | 177 | const snapshot = yield* checkOpenCodeProviderStatus(makeOpenCodeSettings(), process.cwd()); |
| 175 | const model = snapshot.models.find((entry) => entry.slug === "openai/gpt-5.4"); | 178 | const model = snapshot.models.find((entry) => entry.slug === "openai/gpt-5.4"); |
| 176 | 179 | ||
| 177 | assert.ok(model); | 180 | NodeAssert.ok(model); |
| 178 | const variantDescriptor = model.capabilities?.optionDescriptors?.find( | 181 | const variantDescriptor = model.capabilities?.optionDescriptors?.find( |
| 179 | (descriptor) => descriptor.id === "variant" && descriptor.type === "select", | 182 | (descriptor) => descriptor.id === "variant" && descriptor.type === "select", |
| 180 | ); | 183 | ); |
| 181 | assert.ok(variantDescriptor && variantDescriptor.type === "select"); | 184 | NodeAssert.ok(variantDescriptor && variantDescriptor.type === "select"); |
| 182 | assert.equal( | 185 | NodeAssert.equal( |
| 183 | variantDescriptor.options.find((option) => option.isDefault === true)?.id, | 186 | variantDescriptor.options.find((option) => option.isDefault === true)?.id, |
| 184 | "medium", | 187 | "medium", |
| 185 | ); | 188 | ); |
| 186 | const agentDescriptor = model.capabilities?.optionDescriptors?.find( | 189 | const agentDescriptor = model.capabilities?.optionDescriptors?.find( |
| 187 | (descriptor) => descriptor.id === "agent" && descriptor.type === "select", | 190 | (descriptor) => descriptor.id === "agent" && descriptor.type === "select", |
| 188 | ); | 191 | ); |
| 189 | assert.ok(agentDescriptor && agentDescriptor.type === "select"); | 192 | NodeAssert.ok(agentDescriptor && agentDescriptor.type === "select"); |
| 190 | assert.equal( | 193 | NodeAssert.equal( |
| 191 | agentDescriptor.options.find((option) => option.isDefault === true)?.id, | 194 | agentDescriptor.options.find((option) => option.isDefault === true)?.id, |
| 192 | "build", | 195 | "build", |
| 193 | ); | 196 | ); |
| ... | @@ -198,7 +201,7 @@ it.layer(testLayer)("checkOpenCodeProviderStatus", (it) => { | ... | @@ -198,7 +201,7 @@ it.layer(testLayer)("checkOpenCodeProviderStatus", (it) => { |
| 198 | Effect.gen(function* () { | 201 | Effect.gen(function* () { |
| 199 | yield* checkOpenCodeProviderStatus(makeOpenCodeSettings(), process.cwd()); | 202 | yield* checkOpenCodeProviderStatus(makeOpenCodeSettings(), process.cwd()); |
| 200 | 203 | ||
| 201 | assert.equal(runtimeMock.state.closeCalls, 1); | 204 | NodeAssert.equal(runtimeMock.state.closeCalls, 1); |
| 202 | }), | 205 | }), |
| 203 | ); | 206 | ); |
| 204 | }); | 207 | }); |
| ... | @@ -215,9 +218,9 @@ it.layer(testLayer)("checkOpenCodeProviderStatus with configured server URL", (i | ... | @@ -215,9 +218,9 @@ it.layer(testLayer)("checkOpenCodeProviderStatus with configured server URL", (i |
| 215 | process.cwd(), | 218 | process.cwd(), |
| 216 | ); | 219 | ); |
| 217 | 220 | ||
| 218 | assert.equal(snapshot.status, "error"); | 221 | NodeAssert.equal(snapshot.status, "error"); |
| 219 | assert.equal(snapshot.installed, true); | 222 | NodeAssert.equal(snapshot.installed, true); |
| 220 | assert.equal( | 223 | NodeAssert.equal( |
| 221 | snapshot.message, | 224 | snapshot.message, |
| 222 | "OpenCode server rejected authentication. Check the server URL and password.", | 225 | "OpenCode server rejected authentication. Check the server URL and password.", |
| 223 | ); | 226 | ); |
| ... | @@ -237,9 +240,9 @@ it.layer(testLayer)("checkOpenCodeProviderStatus with configured server URL", (i | ... | @@ -237,9 +240,9 @@ it.layer(testLayer)("checkOpenCodeProviderStatus with configured server URL", (i |
| 237 | process.cwd(), | 240 | process.cwd(), |
| 238 | ); | 241 | ); |
| 239 | 242 | ||
| 240 | assert.equal(snapshot.status, "error"); | 243 | NodeAssert.equal(snapshot.status, "error"); |
| 241 | assert.equal(snapshot.installed, true); | 244 | NodeAssert.equal(snapshot.installed, true); |
| 242 | assert.equal( | 245 | NodeAssert.equal( |
| 243 | snapshot.message, | 246 | snapshot.message, |
| 244 | "Couldn't reach the configured OpenCode server at http://127.0.0.1:9999. Check that the server is running and the URL is correct.", | 247 | "Couldn't reach the configured OpenCode server at http://127.0.0.1:9999. Check that the server is running and the URL is correct.", |
| 245 | ); | 248 | ); |
apps/server/src/provider/Layers/ProviderService.test.ts+21-15| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off | 1 | // @effect-diagnostics nodeBuiltinImport:off |
| 2 | import fs from "node:fs"; | 2 | import * as NodeFS from "node:fs"; |
| 3 | import os from "node:os"; | 3 | import * as NodeOS from "node:os"; |
| 4 | import path from "node:path"; | 4 | import * as NodePath from "node:path"; |
| 5 | 5 | ||
| 6 | import type { | 6 | import type { |
| 7 | ProviderApprovalDecision, | 7 | ProviderApprovalDecision, |
| ... | @@ -644,8 +644,8 @@ it.effect("ProviderServiceLive writes canonical events to the emitting thread se | ... | @@ -644,8 +644,8 @@ it.effect("ProviderServiceLive writes canonical events to the emitting thread se |
| 644 | 644 | ||
| 645 | it.effect("ProviderServiceLive keeps persisted resumable sessions on startup", () => | 645 | it.effect("ProviderServiceLive keeps persisted resumable sessions on startup", () => |
| 646 | Effect.gen(function* () { | 646 | Effect.gen(function* () { |
| 647 | const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "t3-provider-service-")); | 647 | const tempDir = NodeFS.mkdtempSync(NodePath.join(NodeOS.tmpdir(), "t3-provider-service-")); |
| 648 | const dbPath = path.join(tempDir, "orchestration.sqlite"); | 648 | const dbPath = NodePath.join(tempDir, "orchestration.sqlite"); |
| 649 | 649 | ||
| 650 | const codex = makeFakeCodexAdapter(); | 650 | const codex = makeFakeCodexAdapter(); |
| 651 | const registry = makeAdapterRegistryMock({ | 651 | const registry = makeAdapterRegistryMock({ |
| ... | @@ -706,7 +706,7 @@ it.effect("ProviderServiceLive keeps persisted resumable sessions on startup", ( | ... | @@ -706,7 +706,7 @@ it.effect("ProviderServiceLive keeps persisted resumable sessions on startup", ( |
| 706 | }).pipe(Effect.provide(persistenceLayer)); | 706 | }).pipe(Effect.provide(persistenceLayer)); |
| 707 | assert.equal(legacyTableRows.length, 0); | 707 | assert.equal(legacyTableRows.length, 0); |
| 708 | 708 | ||
| 709 | fs.rmSync(tempDir, { recursive: true, force: true }); | 709 | NodeFS.rmSync(tempDir, { recursive: true, force: true }); |
| 710 | }).pipe(Effect.provide(NodeServices.layer)), | 710 | }).pipe(Effect.provide(NodeServices.layer)), |
| 711 | ); | 711 | ); |
| 712 | 712 | ||
| ... | @@ -714,8 +714,10 @@ it.effect( | ... | @@ -714,8 +714,10 @@ it.effect( |
| 714 | "ProviderServiceLive restores rollback routing after restart using persisted thread mapping", | 714 | "ProviderServiceLive restores rollback routing after restart using persisted thread mapping", |
| 715 | () => | 715 | () => |
| 716 | Effect.gen(function* () { | 716 | Effect.gen(function* () { |
| 717 | const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "t3-provider-service-restart-")); | 717 | const tempDir = NodeFS.mkdtempSync( |
| 718 | const dbPath = path.join(tempDir, "orchestration.sqlite"); | 718 | NodePath.join(NodeOS.tmpdir(), "t3-provider-service-restart-"), |
| 719 | ); | ||
| 720 | const dbPath = NodePath.join(tempDir, "orchestration.sqlite"); | ||
| 719 | const persistenceLayer = makeSqlitePersistenceLive(dbPath); | 721 | const persistenceLayer = makeSqlitePersistenceLive(dbPath); |
| 720 | const runtimeRepositoryLayer = ProviderSessionRuntime.layer.pipe( | 722 | const runtimeRepositoryLayer = ProviderSessionRuntime.layer.pipe( |
| 721 | Layer.provide(persistenceLayer), | 723 | Layer.provide(persistenceLayer), |
| ... | @@ -834,7 +836,7 @@ it.effect( | ... | @@ -834,7 +836,7 @@ it.effect( |
| 834 | assert.equal(typeof rollbackCall?.[0], "string"); | 836 | assert.equal(typeof rollbackCall?.[0], "string"); |
| 835 | assert.equal(rollbackCall?.[1], 1); | 837 | assert.equal(rollbackCall?.[1], 1); |
| 836 | 838 | ||
| 837 | fs.rmSync(tempDir, { recursive: true, force: true }); | 839 | NodeFS.rmSync(tempDir, { recursive: true, force: true }); |
| 838 | }).pipe(Effect.provide(NodeServices.layer)), | 840 | }).pipe(Effect.provide(NodeServices.layer)), |
| 839 | ); | 841 | ); |
| 840 | 842 | ||
| ... | @@ -1283,8 +1285,10 @@ routing.layer("ProviderServiceLive routing", (it) => { | ... | @@ -1283,8 +1285,10 @@ routing.layer("ProviderServiceLive routing", (it) => { |
| 1283 | 1285 | ||
| 1284 | it.effect("reuses persisted resume cursor when startSession is called after a restart", () => | 1286 | it.effect("reuses persisted resume cursor when startSession is called after a restart", () => |
| 1285 | Effect.gen(function* () { | 1287 | Effect.gen(function* () { |
| 1286 | const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "t3-provider-service-start-")); | 1288 | const tempDir = NodeFS.mkdtempSync( |
| 1287 | const dbPath = path.join(tempDir, "orchestration.sqlite"); | 1289 | NodePath.join(NodeOS.tmpdir(), "t3-provider-service-start-"), |
| 1290 | ); | ||
| 1291 | const dbPath = NodePath.join(tempDir, "orchestration.sqlite"); | ||
| 1288 | const persistenceLayer = makeSqlitePersistenceLive(dbPath); | 1292 | const persistenceLayer = makeSqlitePersistenceLive(dbPath); |
| 1289 | const runtimeRepositoryLayer = ProviderSessionRuntime.layer.pipe( | 1293 | const runtimeRepositoryLayer = ProviderSessionRuntime.layer.pipe( |
| 1290 | Layer.provide(persistenceLayer), | 1294 | Layer.provide(persistenceLayer), |
| ... | @@ -1379,7 +1383,7 @@ routing.layer("ProviderServiceLive routing", (it) => { | ... | @@ -1379,7 +1383,7 @@ routing.layer("ProviderServiceLive routing", (it) => { |
| 1379 | assert.equal(startPayload.threadId, initial.threadId); | 1383 | assert.equal(startPayload.threadId, initial.threadId); |
| 1380 | } | 1384 | } |
| 1381 | 1385 | ||
| 1382 | fs.rmSync(tempDir, { recursive: true, force: true }); | 1386 | NodeFS.rmSync(tempDir, { recursive: true, force: true }); |
| 1383 | }).pipe(Effect.provide(NodeServices.layer)), | 1387 | }).pipe(Effect.provide(NodeServices.layer)), |
| 1384 | ); | 1388 | ); |
| 1385 | 1389 | ||
| ... | @@ -1387,8 +1391,10 @@ routing.layer("ProviderServiceLive routing", (it) => { | ... | @@ -1387,8 +1391,10 @@ routing.layer("ProviderServiceLive routing", (it) => { |
| 1387 | "reuses persisted cwd when startSession resumes a claude session without cwd input", | 1391 | "reuses persisted cwd when startSession resumes a claude session without cwd input", |
| 1388 | () => | 1392 | () => |
| 1389 | Effect.gen(function* () { | 1393 | Effect.gen(function* () { |
| 1390 | const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "t3-provider-service-cwd-")); | 1394 | const tempDir = NodeFS.mkdtempSync( |
| 1391 | const dbPath = path.join(tempDir, "orchestration.sqlite"); | 1395 | NodePath.join(NodeOS.tmpdir(), "t3-provider-service-cwd-"), |
| 1396 | ); | ||
| 1397 | const dbPath = NodePath.join(tempDir, "orchestration.sqlite"); | ||
| 1392 | const persistenceLayer = makeSqlitePersistenceLive(dbPath); | 1398 | const persistenceLayer = makeSqlitePersistenceLive(dbPath); |
| 1393 | const runtimeRepositoryLayer = ProviderSessionRuntime.layer.pipe( | 1399 | const runtimeRepositoryLayer = ProviderSessionRuntime.layer.pipe( |
| 1394 | Layer.provide(persistenceLayer), | 1400 | Layer.provide(persistenceLayer), |
| ... | @@ -1477,7 +1483,7 @@ routing.layer("ProviderServiceLive routing", (it) => { | ... | @@ -1477,7 +1483,7 @@ routing.layer("ProviderServiceLive routing", (it) => { |
| 1477 | assert.equal(startPayload.threadId, initial.threadId); | 1483 | assert.equal(startPayload.threadId, initial.threadId); |
| 1478 | } | 1484 | } |
| 1479 | 1485 | ||
| 1480 | fs.rmSync(tempDir, { recursive: true, force: true }); | 1486 | NodeFS.rmSync(tempDir, { recursive: true, force: true }); |
| 1481 | }).pipe(Effect.provide(NodeServices.layer)), | 1487 | }).pipe(Effect.provide(NodeServices.layer)), |
| 1482 | ); | 1488 | ); |
| 1483 | }); | 1489 | }); |
apps/server/src/provider/Layers/ProviderSessionDirectory.test.ts+6-6| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off | 1 | // @effect-diagnostics nodeBuiltinImport:off |
| 2 | import fs from "node:fs"; | 2 | import * as NodeFS from "node:fs"; |
| 3 | import os from "node:os"; | 3 | import * as NodeOS from "node:os"; |
| 4 | import path from "node:path"; | 4 | import * as NodePath from "node:path"; |
| 5 | 5 | ||
| 6 | import * as NodeServices from "@effect/platform-node/NodeServices"; | 6 | import * as NodeServices from "@effect/platform-node/NodeServices"; |
| 7 | import { ProviderDriverKind, ThreadId } from "@t3tools/contracts"; | 7 | import { ProviderDriverKind, ThreadId } from "@t3tools/contracts"; |
| ... | @@ -229,8 +229,8 @@ it.layer(makeDirectoryLayer(SqlitePersistenceMemory))("ProviderSessionDirectoryL | ... | @@ -229,8 +229,8 @@ it.layer(makeDirectoryLayer(SqlitePersistenceMemory))("ProviderSessionDirectoryL |
| 229 | 229 | ||
| 230 | it("rehydrates persisted mappings across layer restart", () => | 230 | it("rehydrates persisted mappings across layer restart", () => |
| 231 | Effect.gen(function* () { | 231 | Effect.gen(function* () { |
| 232 | const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "t3-provider-directory-")); | 232 | const tempDir = NodeFS.mkdtempSync(NodePath.join(NodeOS.tmpdir(), "t3-provider-directory-")); |
| 233 | const dbPath = path.join(tempDir, "orchestration.sqlite"); | 233 | const dbPath = NodePath.join(tempDir, "orchestration.sqlite"); |
| 234 | const directoryLayer = makeDirectoryLayer(makeSqlitePersistenceLive(dbPath)); | 234 | const directoryLayer = makeDirectoryLayer(makeSqlitePersistenceLive(dbPath)); |
| 235 | 235 | ||
| 236 | const threadId = ThreadId.make("thread-restart"); | 236 | const threadId = ThreadId.make("thread-restart"); |
| ... | @@ -266,6 +266,6 @@ it.layer(makeDirectoryLayer(SqlitePersistenceMemory))("ProviderSessionDirectoryL | ... | @@ -266,6 +266,6 @@ it.layer(makeDirectoryLayer(SqlitePersistenceMemory))("ProviderSessionDirectoryL |
| 266 | assert.equal(legacyTableRows.length, 0); | 266 | assert.equal(legacyTableRows.length, 0); |
| 267 | }).pipe(Effect.provide(directoryLayer)); | 267 | }).pipe(Effect.provide(directoryLayer)); |
| 268 | 268 | ||
| 269 | fs.rmSync(tempDir, { recursive: true, force: true }); | 269 | NodeFS.rmSync(tempDir, { recursive: true, force: true }); |
| 270 | })); | 270 | })); |
| 271 | }); | 271 | }); |
apps/server/src/provider/acp/AcpJsonRpcConnection.test.ts+10-10| ... | @@ -1,8 +1,8 @@ | ... | @@ -1,8 +1,8 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off | 1 | // @effect-diagnostics nodeBuiltinImport:off |
| 2 | import * as path from "node:path"; | 2 | import * as NodePath from "node:path"; |
| 3 | import * as os from "node:os"; | 3 | import * as NodeOS from "node:os"; |
| 4 | import { fileURLToPath } from "node:url"; | 4 | import * as NodeURL from "node:url"; |
| 5 | import { mkdtempSync, readFileSync, rmSync } from "node:fs"; | 5 | import * as NodeFS from "node:fs"; |
| 6 | 6 | ||
| 7 | import * as NodeServices from "@effect/platform-node/NodeServices"; | 7 | import * as NodeServices from "@effect/platform-node/NodeServices"; |
| 8 | import { it } from "@effect/vitest"; | 8 | import { it } from "@effect/vitest"; |
| ... | @@ -13,8 +13,8 @@ import { describe, expect } from "vite-plus/test"; | ... | @@ -13,8 +13,8 @@ import { describe, expect } from "vite-plus/test"; |
| 13 | import * as AcpSessionRuntime from "./AcpSessionRuntime.ts"; | 13 | import * as AcpSessionRuntime from "./AcpSessionRuntime.ts"; |
| 14 | import type * as EffectAcpProtocol from "effect-acp/protocol"; | 14 | import type * as EffectAcpProtocol from "effect-acp/protocol"; |
| 15 | 15 | ||
| 16 | const __dirname = path.dirname(fileURLToPath(import.meta.url)); | 16 | const __dirname = NodePath.dirname(NodeURL.fileURLToPath(import.meta.url)); |
| 17 | const mockAgentPath = path.join(__dirname, "../../../scripts/acp-mock-agent.ts"); | 17 | const mockAgentPath = NodePath.join(__dirname, "../../../scripts/acp-mock-agent.ts"); |
| 18 | const mockAgentCommand = "node"; | 18 | const mockAgentCommand = "node"; |
| 19 | const mockAgentArgs = [mockAgentPath]; | 19 | const mockAgentArgs = [mockAgentPath]; |
| 20 | 20 | ||
| ... | @@ -347,8 +347,8 @@ describe("AcpSessionRuntime", () => { | ... | @@ -347,8 +347,8 @@ describe("AcpSessionRuntime", () => { |
| 347 | }); | 347 | }); |
| 348 | 348 | ||
| 349 | it.effect("rejects invalid config option values before sending session/set_config_option", () => { | 349 | it.effect("rejects invalid config option values before sending session/set_config_option", () => { |
| 350 | const tempDir = mkdtempSync(path.join(os.tmpdir(), "acp-runtime-")); | 350 | const tempDir = NodeFS.mkdtempSync(NodePath.join(NodeOS.tmpdir(), "acp-runtime-")); |
| 351 | const requestLogPath = path.join(tempDir, "requests.ndjson"); | 351 | const requestLogPath = NodePath.join(tempDir, "requests.ndjson"); |
| 352 | return Effect.gen(function* () { | 352 | return Effect.gen(function* () { |
| 353 | const runtime = yield* AcpSessionRuntime.AcpSessionRuntime; | 353 | const runtime = yield* AcpSessionRuntime.AcpSessionRuntime; |
| 354 | yield* runtime.start(); | 354 | yield* runtime.start(); |
| ... | @@ -363,7 +363,7 @@ describe("AcpSessionRuntime", () => { | ... | @@ -363,7 +363,7 @@ describe("AcpSessionRuntime", () => { |
| 363 | expect(error.message).toContain("composer-2[fast=true]"); | 363 | expect(error.message).toContain("composer-2[fast=true]"); |
| 364 | } | 364 | } |
| 365 | 365 | ||
| 366 | const recordedRequests = readFileSync(requestLogPath, "utf8") | 366 | const recordedRequests = NodeFS.readFileSync(requestLogPath, "utf8") |
| 367 | .trim() | 367 | .trim() |
| 368 | .split("\n") | 368 | .split("\n") |
| 369 | .filter((line) => line.length > 0) | 369 | .filter((line) => line.length > 0) |
| ... | @@ -392,7 +392,7 @@ describe("AcpSessionRuntime", () => { | ... | @@ -392,7 +392,7 @@ describe("AcpSessionRuntime", () => { |
| 392 | ), | 392 | ), |
| 393 | Effect.scoped, | 393 | Effect.scoped, |
| 394 | Effect.provide(NodeServices.layer), | 394 | Effect.provide(NodeServices.layer), |
| 395 | Effect.ensuring(Effect.sync(() => rmSync(tempDir, { recursive: true, force: true }))), | 395 | Effect.ensuring(Effect.sync(() => NodeFS.rmSync(tempDir, { recursive: true, force: true }))), |
| 396 | ); | 396 | ); |
| 397 | }); | 397 | }); |
| 398 | }); | 398 | }); |
apps/server/src/provider/opencodeRuntime.ts+2-2| ... | @@ -1,4 +1,4 @@ | ... | @@ -1,4 +1,4 @@ |
| 1 | import { pathToFileURL } from "node:url"; | 1 | import * as NodeURL from "node:url"; |
| 2 | 2 | ||
| 3 | import type { ChatAttachment, ProviderApprovalDecision, RuntimeMode } from "@t3tools/contracts"; | 3 | import type { ChatAttachment, ProviderApprovalDecision, RuntimeMode } from "@t3tools/contracts"; |
| 4 | import { | 4 | import { |
| ... | @@ -206,7 +206,7 @@ export function toOpenCodeFileParts(input: { | ... | @@ -206,7 +206,7 @@ export function toOpenCodeFileParts(input: { |
| 206 | type: "file", | 206 | type: "file", |
| 207 | mime: attachment.mimeType, | 207 | mime: attachment.mimeType, |
| 208 | filename: attachment.name, | 208 | filename: attachment.name, |
| 209 | url: pathToFileURL(attachmentPath).href, | 209 | url: NodeURL.pathToFileURL(attachmentPath).href, |
| 210 | }); | 210 | }); |
| 211 | } | 211 | } |
| 212 | 212 |
apps/server/src/provider/providerMaintenance.test.ts+44-44| ... | @@ -1,9 +1,9 @@ | ... | @@ -1,9 +1,9 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off | 1 | // @effect-diagnostics nodeBuiltinImport:off |
| 2 | import { expect, it } from "@effect/vitest"; | 2 | import { expect, it } from "@effect/vitest"; |
| 3 | import { chmodSync, mkdirSync, symlinkSync, writeFileSync } from "node:fs"; | 3 | import * as NodeFS from "node:fs"; |
| 4 | import * as NodeServices from "@effect/platform-node/NodeServices"; | 4 | import * as NodeServices from "@effect/platform-node/NodeServices"; |
| 5 | import * as NodeOS from "node:os"; | 5 | import * as NodeOS from "node:os"; |
| 6 | import path from "node:path"; | 6 | import * as NodePath from "node:path"; |
| 7 | import { ProviderDriverKind, ProviderInstanceId, type ServerProvider } from "@t3tools/contracts"; | 7 | import { ProviderDriverKind, ProviderInstanceId, type ServerProvider } from "@t3tools/contracts"; |
| 8 | import { HostProcessPlatform } from "@t3tools/shared/hostProcess"; | 8 | import { HostProcessPlatform } from "@t3tools/shared/hostProcess"; |
| 9 | import * as Crypto from "effect/Crypto"; | 9 | import * as Crypto from "effect/Crypto"; |
| ... | @@ -25,7 +25,7 @@ const driver = (value: string) => ProviderDriverKind.make(value); | ... | @@ -25,7 +25,7 @@ const driver = (value: string) => ProviderDriverKind.make(value); |
| 25 | const makeTempDir = (name: string) => | 25 | const makeTempDir = (name: string) => |
| 26 | Crypto.Crypto.pipe( | 26 | Crypto.Crypto.pipe( |
| 27 | Effect.flatMap((crypto) => crypto.randomUUIDv4), | 27 | Effect.flatMap((crypto) => crypto.randomUUIDv4), |
| 28 | Effect.map((id) => path.join(NodeOS.tmpdir(), `${name}-${id}`)), | 28 | Effect.map((id) => NodePath.join(NodeOS.tmpdir(), `${name}-${id}`)), |
| 29 | ); | 29 | ); |
| 30 | const isNativeTestCommandPath = | 30 | const isNativeTestCommandPath = |
| 31 | (expectedPathSegment: string) => | 31 | (expectedPathSegment: string) => |
| ... | @@ -203,11 +203,11 @@ it.layer(NodeServices.layer)("providerMaintenance", (it) => { | ... | @@ -203,11 +203,11 @@ it.layer(NodeServices.layer)("providerMaintenance", (it) => { |
| 203 | () => | 203 | () => |
| 204 | Effect.gen(function* () { | 204 | Effect.gen(function* () { |
| 205 | const tempDir = yield* makeTempDir("t3-vite-plus-capabilities"); | 205 | const tempDir = yield* makeTempDir("t3-vite-plus-capabilities"); |
| 206 | const vitePlusBinDir = path.join(tempDir, ".vite-plus", "bin"); | 206 | const vitePlusBinDir = NodePath.join(tempDir, ".vite-plus", "bin"); |
| 207 | mkdirSync(vitePlusBinDir, { recursive: true }); | 207 | NodeFS.mkdirSync(vitePlusBinDir, { recursive: true }); |
| 208 | const packageToolPath = path.join(vitePlusBinDir, "package-tool"); | 208 | const packageToolPath = NodePath.join(vitePlusBinDir, "package-tool"); |
| 209 | writeFileSync(packageToolPath, "#!/bin/sh\n"); | 209 | NodeFS.writeFileSync(packageToolPath, "#!/bin/sh\n"); |
| 210 | chmodSync(packageToolPath, 0o755); | 210 | NodeFS.chmodSync(packageToolPath, 0o755); |
| 211 | 211 | ||
| 212 | const capabilities = yield* resolveProviderMaintenanceCapabilitiesEffect( | 212 | const capabilities = yield* resolveProviderMaintenanceCapabilitiesEffect( |
| 213 | packageToolUpdate, | 213 | packageToolUpdate, |
| ... | @@ -240,9 +240,9 @@ it.layer(NodeServices.layer)("providerMaintenance", (it) => { | ... | @@ -240,9 +240,9 @@ it.layer(NodeServices.layer)("providerMaintenance", (it) => { |
| 240 | () => | 240 | () => |
| 241 | Effect.gen(function* () { | 241 | Effect.gen(function* () { |
| 242 | const tempDir = yield* makeTempDir("t3-bun-capabilities"); | 242 | const tempDir = yield* makeTempDir("t3-bun-capabilities"); |
| 243 | const bunBinDir = path.join(tempDir, ".bun", "bin"); | 243 | const bunBinDir = NodePath.join(tempDir, ".bun", "bin"); |
| 244 | mkdirSync(bunBinDir, { recursive: true }); | 244 | NodeFS.mkdirSync(bunBinDir, { recursive: true }); |
| 245 | writeFileSync(path.join(bunBinDir, "native-package-tool.exe"), "MZ"); | 245 | NodeFS.writeFileSync(NodePath.join(bunBinDir, "native-package-tool.exe"), "MZ"); |
| 246 | 246 | ||
| 247 | const capabilities = yield* resolveProviderMaintenanceCapabilitiesEffect( | 247 | const capabilities = yield* resolveProviderMaintenanceCapabilitiesEffect( |
| 248 | nativePackageToolUpdate, | 248 | nativePackageToolUpdate, |
| ... | @@ -276,11 +276,11 @@ it.layer(NodeServices.layer)("providerMaintenance", (it) => { | ... | @@ -276,11 +276,11 @@ it.layer(NodeServices.layer)("providerMaintenance", (it) => { |
| 276 | () => | 276 | () => |
| 277 | Effect.gen(function* () { | 277 | Effect.gen(function* () { |
| 278 | const tempDir = yield* makeTempDir("t3-pnpm-capabilities"); | 278 | const tempDir = yield* makeTempDir("t3-pnpm-capabilities"); |
| 279 | const pnpmHomeDir = path.join(tempDir, ".local", "share", "pnpm"); | 279 | const pnpmHomeDir = NodePath.join(tempDir, ".local", "share", "pnpm"); |
| 280 | mkdirSync(pnpmHomeDir, { recursive: true }); | 280 | NodeFS.mkdirSync(pnpmHomeDir, { recursive: true }); |
| 281 | const scopedPackageToolPath = path.join(pnpmHomeDir, "scoped-package-tool"); | 281 | const scopedPackageToolPath = NodePath.join(pnpmHomeDir, "scoped-package-tool"); |
| 282 | writeFileSync(scopedPackageToolPath, "#!/bin/sh\n"); | 282 | NodeFS.writeFileSync(scopedPackageToolPath, "#!/bin/sh\n"); |
| 283 | chmodSync(scopedPackageToolPath, 0o755); | 283 | NodeFS.chmodSync(scopedPackageToolPath, 0o755); |
| 284 | 284 | ||
| 285 | const capabilities = yield* resolveProviderMaintenanceCapabilitiesEffect( | 285 | const capabilities = yield* resolveProviderMaintenanceCapabilitiesEffect( |
| 286 | scopedPackageToolUpdate, | 286 | scopedPackageToolUpdate, |
| ... | @@ -336,11 +336,11 @@ it.layer(NodeServices.layer)("providerMaintenance", (it) => { | ... | @@ -336,11 +336,11 @@ it.layer(NodeServices.layer)("providerMaintenance", (it) => { |
| 336 | () => | 336 | () => |
| 337 | Effect.gen(function* () { | 337 | Effect.gen(function* () { |
| 338 | const tempDir = yield* makeTempDir("t3-native-package-tool-native-capabilities"); | 338 | const tempDir = yield* makeTempDir("t3-native-package-tool-native-capabilities"); |
| 339 | const nativeBinDir = path.join(tempDir, ".local", "bin"); | 339 | const nativeBinDir = NodePath.join(tempDir, ".local", "bin"); |
| 340 | mkdirSync(nativeBinDir, { recursive: true }); | 340 | NodeFS.mkdirSync(nativeBinDir, { recursive: true }); |
| 341 | const nativePackageToolPath = path.join(nativeBinDir, "native-package-tool"); | 341 | const nativePackageToolPath = NodePath.join(nativeBinDir, "native-package-tool"); |
| 342 | writeFileSync(nativePackageToolPath, "#!/bin/sh\n"); | 342 | NodeFS.writeFileSync(nativePackageToolPath, "#!/bin/sh\n"); |
| 343 | chmodSync(nativePackageToolPath, 0o755); | 343 | NodeFS.chmodSync(nativePackageToolPath, 0o755); |
| 344 | 344 | ||
| 345 | const capabilities = yield* resolveProviderMaintenanceCapabilitiesEffect( | 345 | const capabilities = yield* resolveProviderMaintenanceCapabilitiesEffect( |
| 346 | nativePackageToolUpdate, | 346 | nativePackageToolUpdate, |
| ... | @@ -373,11 +373,11 @@ it.layer(NodeServices.layer)("providerMaintenance", (it) => { | ... | @@ -373,11 +373,11 @@ it.layer(NodeServices.layer)("providerMaintenance", (it) => { |
| 373 | () => | 373 | () => |
| 374 | Effect.gen(function* () { | 374 | Effect.gen(function* () { |
| 375 | const tempDir = yield* makeTempDir("t3-scoped-package-tool-native-capabilities"); | 375 | const tempDir = yield* makeTempDir("t3-scoped-package-tool-native-capabilities"); |
| 376 | const nativeBinDir = path.join(tempDir, ".scoped-package-tool", "bin"); | 376 | const nativeBinDir = NodePath.join(tempDir, ".scoped-package-tool", "bin"); |
| 377 | mkdirSync(nativeBinDir, { recursive: true }); | 377 | NodeFS.mkdirSync(nativeBinDir, { recursive: true }); |
| 378 | const scopedPackageToolPath = path.join(nativeBinDir, "scoped-package-tool"); | 378 | const scopedPackageToolPath = NodePath.join(nativeBinDir, "scoped-package-tool"); |
| 379 | writeFileSync(scopedPackageToolPath, "#!/bin/sh\n"); | 379 | NodeFS.writeFileSync(scopedPackageToolPath, "#!/bin/sh\n"); |
| 380 | chmodSync(scopedPackageToolPath, 0o755); | 380 | NodeFS.chmodSync(scopedPackageToolPath, 0o755); |
| 381 | 381 | ||
| 382 | const capabilities = yield* resolveProviderMaintenanceCapabilitiesEffect( | 382 | const capabilities = yield* resolveProviderMaintenanceCapabilitiesEffect( |
| 383 | scopedPackageToolUpdate, | 383 | scopedPackageToolUpdate, |
| ... | @@ -454,8 +454,8 @@ it.layer(NodeServices.layer)("providerMaintenance", (it) => { | ... | @@ -454,8 +454,8 @@ it.layer(NodeServices.layer)("providerMaintenance", (it) => { |
| 454 | it.effect("keeps npm updates for binaries symlinked into npm's global node_modules tree", () => | 454 | it.effect("keeps npm updates for binaries symlinked into npm's global node_modules tree", () => |
| 455 | Effect.gen(function* () { | 455 | Effect.gen(function* () { |
| 456 | const tempDir = yield* makeTempDir("t3-npm-capabilities"); | 456 | const tempDir = yield* makeTempDir("t3-npm-capabilities"); |
| 457 | const binDir = path.join(tempDir, "bin"); | 457 | const binDir = NodePath.join(tempDir, "bin"); |
| 458 | const packageBinDir = path.join( | 458 | const packageBinDir = NodePath.join( |
| 459 | tempDir, | 459 | tempDir, |
| 460 | "lib", | 460 | "lib", |
| 461 | "node_modules", | 461 | "node_modules", |
| ... | @@ -463,13 +463,13 @@ it.layer(NodeServices.layer)("providerMaintenance", (it) => { | ... | @@ -463,13 +463,13 @@ it.layer(NodeServices.layer)("providerMaintenance", (it) => { |
| 463 | "package-tool", | 463 | "package-tool", |
| 464 | "bin", | 464 | "bin", |
| 465 | ); | 465 | ); |
| 466 | mkdirSync(binDir, { recursive: true }); | 466 | NodeFS.mkdirSync(binDir, { recursive: true }); |
| 467 | mkdirSync(packageBinDir, { recursive: true }); | 467 | NodeFS.mkdirSync(packageBinDir, { recursive: true }); |
| 468 | const packageBinPath = path.join(packageBinDir, "package-tool.js"); | 468 | const packageBinPath = NodePath.join(packageBinDir, "package-tool.js"); |
| 469 | const symlinkPath = path.join(binDir, "package-tool"); | 469 | const symlinkPath = NodePath.join(binDir, "package-tool"); |
| 470 | writeFileSync(packageBinPath, "#!/usr/bin/env node\n"); | 470 | NodeFS.writeFileSync(packageBinPath, "#!/usr/bin/env node\n"); |
| 471 | chmodSync(packageBinPath, 0o755); | 471 | NodeFS.chmodSync(packageBinPath, 0o755); |
| 472 | symlinkSync(packageBinPath, symlinkPath); | 472 | NodeFS.symlinkSync(packageBinPath, symlinkPath); |
| 473 | 473 | ||
| 474 | const capabilities = yield* resolveProviderMaintenanceCapabilitiesEffect(packageToolUpdate, { | 474 | const capabilities = yield* resolveProviderMaintenanceCapabilitiesEffect(packageToolUpdate, { |
| 475 | binaryPath: symlinkPath, | 475 | binaryPath: symlinkPath, |
| ... | @@ -497,8 +497,8 @@ it.layer(NodeServices.layer)("providerMaintenance", (it) => { | ... | @@ -497,8 +497,8 @@ it.layer(NodeServices.layer)("providerMaintenance", (it) => { |
| 497 | it.effect("uses Effect FileSystem realPath when detecting pnpm global symlinks", () => | 497 | it.effect("uses Effect FileSystem realPath when detecting pnpm global symlinks", () => |
| 498 | Effect.gen(function* () { | 498 | Effect.gen(function* () { |
| 499 | const tempDir = yield* makeTempDir("t3-pnpm-realpath-capabilities"); | 499 | const tempDir = yield* makeTempDir("t3-pnpm-realpath-capabilities"); |
| 500 | const binDir = path.join(tempDir, "bin"); | 500 | const binDir = NodePath.join(tempDir, "bin"); |
| 501 | const packageBinDir = path.join( | 501 | const packageBinDir = NodePath.join( |
| 502 | tempDir, | 502 | tempDir, |
| 503 | ".local", | 503 | ".local", |
| 504 | "share", | 504 | "share", |
| ... | @@ -510,13 +510,13 @@ it.layer(NodeServices.layer)("providerMaintenance", (it) => { | ... | @@ -510,13 +510,13 @@ it.layer(NodeServices.layer)("providerMaintenance", (it) => { |
| 510 | "package-tool", | 510 | "package-tool", |
| 511 | "bin", | 511 | "bin", |
| 512 | ); | 512 | ); |
| 513 | mkdirSync(binDir, { recursive: true }); | 513 | NodeFS.mkdirSync(binDir, { recursive: true }); |
| 514 | mkdirSync(packageBinDir, { recursive: true }); | 514 | NodeFS.mkdirSync(packageBinDir, { recursive: true }); |
| 515 | const packageBinPath = path.join(packageBinDir, "package-tool.js"); | 515 | const packageBinPath = NodePath.join(packageBinDir, "package-tool.js"); |
| 516 | const symlinkPath = path.join(binDir, "package-tool"); | 516 | const symlinkPath = NodePath.join(binDir, "package-tool"); |
| 517 | writeFileSync(packageBinPath, "#!/usr/bin/env node\n"); | 517 | NodeFS.writeFileSync(packageBinPath, "#!/usr/bin/env node\n"); |
| 518 | chmodSync(packageBinPath, 0o755); | 518 | NodeFS.chmodSync(packageBinPath, 0o755); |
| 519 | symlinkSync(packageBinPath, symlinkPath); | 519 | NodeFS.symlinkSync(packageBinPath, symlinkPath); |
| 520 | 520 | ||
| 521 | const capabilities = yield* resolveProviderMaintenanceCapabilitiesEffect(packageToolUpdate, { | 521 | const capabilities = yield* resolveProviderMaintenanceCapabilitiesEffect(packageToolUpdate, { |
| 522 | binaryPath: symlinkPath, | 522 | binaryPath: symlinkPath, |
apps/server/src/relay/AgentAwarenessRelay.test.ts+2-2| ... | @@ -1,4 +1,4 @@ | ... | @@ -1,4 +1,4 @@ |
| 1 | import { generateKeyPairSync } from "node:crypto"; | 1 | import * as NodeCrypto from "node:crypto"; |
| 2 | import * as NodeServices from "@effect/platform-node/NodeServices"; | 2 | import * as NodeServices from "@effect/platform-node/NodeServices"; |
| 3 | 3 | ||
| 4 | import type { | 4 | import type { |
| ... | @@ -348,7 +348,7 @@ describe.sequential("signRelayAgentActivityPublishProof", () => { | ... | @@ -348,7 +348,7 @@ describe.sequential("signRelayAgentActivityPublishProof", () => { |
| 348 | }); | 348 | }); |
| 349 | 349 | ||
| 350 | it("signs the activity publish JWT and rejects tampering", async () => { | 350 | it("signs the activity publish JWT and rejects tampering", async () => { |
| 351 | const keyPair = generateKeyPairSync("ed25519", { | 351 | const keyPair = NodeCrypto.generateKeyPairSync("ed25519", { |
| 352 | privateKeyEncoding: { format: "pem", type: "pkcs8" }, | 352 | privateKeyEncoding: { format: "pem", type: "pkcs8" }, |
| 353 | publicKeyEncoding: { format: "pem", type: "spki" }, | 353 | publicKeyEncoding: { format: "pem", type: "spki" }, |
| 354 | }); | 354 | }); |
apps/server/src/server.test.ts+22-22| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | import * as NodeHttpServer from "@effect/platform-node/NodeHttpServer"; | 1 | import * as NodeHttpServer from "@effect/platform-node/NodeHttpServer"; |
| 2 | import * as NodeSocket from "@effect/platform-node/NodeSocket"; | 2 | import * as NodeSocket from "@effect/platform-node/NodeSocket"; |
| 3 | import * as NodeServices from "@effect/platform-node/NodeServices"; | 3 | import * as NodeServices from "@effect/platform-node/NodeServices"; |
| 4 | import { generateKeyPairSync, type KeyObject, sign } from "node:crypto"; | 4 | import * as NodeCrypto from "node:crypto"; |
| 5 | 5 | ||
| 6 | import { | 6 | import { |
| 7 | AuthAccessTokenType, | 7 | AuthAccessTokenType, |
| ... | @@ -950,14 +950,14 @@ const makeDpopProof = (input: { | ... | @@ -950,14 +950,14 @@ const makeDpopProof = (input: { |
| 950 | readonly iat: number; | 950 | readonly iat: number; |
| 951 | readonly accessToken?: string; | 951 | readonly accessToken?: string; |
| 952 | readonly jti?: string; | 952 | readonly jti?: string; |
| 953 | readonly privateKey?: KeyObject; | 953 | readonly privateKey?: NodeCrypto.KeyObject; |
| 954 | readonly publicJwk?: DpopPublicJwk; | 954 | readonly publicJwk?: DpopPublicJwk; |
| 955 | }) => { | 955 | }) => { |
| 956 | const keyPair = | 956 | const keyPair = |
| 957 | input.privateKey && input.publicJwk | 957 | input.privateKey && input.publicJwk |
| 958 | ? { privateKey: input.privateKey, publicJwk: input.publicJwk } | 958 | ? { privateKey: input.privateKey, publicJwk: input.publicJwk } |
| 959 | : (() => { | 959 | : (() => { |
| 960 | const { privateKey, publicKey } = generateKeyPairSync("ec", { | 960 | const { privateKey, publicKey } = NodeCrypto.generateKeyPairSync("ec", { |
| 961 | namedCurve: "P-256", | 961 | namedCurve: "P-256", |
| 962 | }); | 962 | }); |
| 963 | return { privateKey, publicJwk: publicKey.export({ format: "jwk" }) as DpopPublicJwk }; | 963 | return { privateKey, publicJwk: publicKey.export({ format: "jwk" }) as DpopPublicJwk }; |
| ... | @@ -978,7 +978,7 @@ const makeDpopProof = (input: { | ... | @@ -978,7 +978,7 @@ const makeDpopProof = (input: { |
| 978 | ...(input.accessToken ? { ath: computeDpopAccessTokenHash(input.accessToken) } : {}), | 978 | ...(input.accessToken ? { ath: computeDpopAccessTokenHash(input.accessToken) } : {}), |
| 979 | }), | 979 | }), |
| 980 | ).toString("base64url"); | 980 | ).toString("base64url"); |
| 981 | const signature = sign("sha256", Buffer.from(`${header}.${payload}`), { | 981 | const signature = NodeCrypto.sign("sha256", Buffer.from(`${header}.${payload}`), { |
| 982 | key: keyPair.privateKey, | 982 | key: keyPair.privateKey, |
| 983 | dsaEncoding: "ieee-p1363", | 983 | dsaEncoding: "ieee-p1363", |
| 984 | }).toString("base64url"); | 984 | }).toString("base64url"); |
| ... | @@ -1024,7 +1024,7 @@ const makeCloudMintCredentialRequest = (input: { | ... | @@ -1024,7 +1024,7 @@ const makeCloudMintCredentialRequest = (input: { |
| 1024 | const encodedPayload = Buffer.from(JSON.stringify(payload)).toString("base64url"); | 1024 | const encodedPayload = Buffer.from(JSON.stringify(payload)).toString("base64url"); |
| 1025 | const signingInput = `${header}.${encodedPayload}`; | 1025 | const signingInput = `${header}.${encodedPayload}`; |
| 1026 | return { | 1026 | return { |
| 1027 | proof: `${signingInput}.${sign(null, Buffer.from(signingInput), input.privateKey).toString("base64url")}`, | 1027 | proof: `${signingInput}.${NodeCrypto.sign(null, Buffer.from(signingInput), input.privateKey).toString("base64url")}`, |
| 1028 | }; | 1028 | }; |
| 1029 | }; | 1029 | }; |
| 1030 | 1030 | ||
| ... | @@ -1057,7 +1057,7 @@ const makeCloudEnvironmentHealthRequest = (input: { | ... | @@ -1057,7 +1057,7 @@ const makeCloudEnvironmentHealthRequest = (input: { |
| 1057 | const encodedPayload = Buffer.from(JSON.stringify(payload)).toString("base64url"); | 1057 | const encodedPayload = Buffer.from(JSON.stringify(payload)).toString("base64url"); |
| 1058 | const signingInput = `${header}.${encodedPayload}`; | 1058 | const signingInput = `${header}.${encodedPayload}`; |
| 1059 | return { | 1059 | return { |
| 1060 | proof: `${signingInput}.${sign(null, Buffer.from(signingInput), input.privateKey).toString("base64url")}`, | 1060 | proof: `${signingInput}.${NodeCrypto.sign(null, Buffer.from(signingInput), input.privateKey).toString("base64url")}`, |
| 1061 | }; | 1061 | }; |
| 1062 | }; | 1062 | }; |
| 1063 | 1063 | ||
| ... | @@ -2054,7 +2054,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { | ... | @@ -2054,7 +2054,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 2054 | Effect.gen(function* () { | 2054 | Effect.gen(function* () { |
| 2055 | yield* buildAppUnderTest(); | 2055 | yield* buildAppUnderTest(); |
| 2056 | 2056 | ||
| 2057 | const cloudKeyPair = generateKeyPairSync("ed25519", { | 2057 | const cloudKeyPair = NodeCrypto.generateKeyPairSync("ed25519", { |
| 2058 | privateKeyEncoding: { format: "pem", type: "pkcs8" }, | 2058 | privateKeyEncoding: { format: "pem", type: "pkcs8" }, |
| 2059 | publicKeyEncoding: { format: "pem", type: "spki" }, | 2059 | publicKeyEncoding: { format: "pem", type: "spki" }, |
| 2060 | }); | 2060 | }); |
| ... | @@ -2131,7 +2131,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { | ... | @@ -2131,7 +2131,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 2131 | Effect.gen(function* () { | 2131 | Effect.gen(function* () { |
| 2132 | yield* buildAppUnderTest(); | 2132 | yield* buildAppUnderTest(); |
| 2133 | 2133 | ||
| 2134 | const cloudKeyPair = generateKeyPairSync("ed25519", { | 2134 | const cloudKeyPair = NodeCrypto.generateKeyPairSync("ed25519", { |
| 2135 | privateKeyEncoding: { format: "pem", type: "pkcs8" }, | 2135 | privateKeyEncoding: { format: "pem", type: "pkcs8" }, |
| 2136 | publicKeyEncoding: { format: "pem", type: "spki" }, | 2136 | publicKeyEncoding: { format: "pem", type: "spki" }, |
| 2137 | }); | 2137 | }); |
| ... | @@ -2174,7 +2174,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { | ... | @@ -2174,7 +2174,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 2174 | Effect.gen(function* () { | 2174 | Effect.gen(function* () { |
| 2175 | yield* buildAppUnderTest(); | 2175 | yield* buildAppUnderTest(); |
| 2176 | 2176 | ||
| 2177 | const cloudKeyPair = generateKeyPairSync("ed25519", { | 2177 | const cloudKeyPair = NodeCrypto.generateKeyPairSync("ed25519", { |
| 2178 | privateKeyEncoding: { format: "pem", type: "pkcs8" }, | 2178 | privateKeyEncoding: { format: "pem", type: "pkcs8" }, |
| 2179 | publicKeyEncoding: { format: "pem", type: "spki" }, | 2179 | publicKeyEncoding: { format: "pem", type: "spki" }, |
| 2180 | }); | 2180 | }); |
| ... | @@ -2268,7 +2268,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { | ... | @@ -2268,7 +2268,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 2268 | }, | 2268 | }, |
| 2269 | }); | 2269 | }); |
| 2270 | 2270 | ||
| 2271 | const cloudKeyPair = generateKeyPairSync("ed25519", { | 2271 | const cloudKeyPair = NodeCrypto.generateKeyPairSync("ed25519", { |
| 2272 | privateKeyEncoding: { format: "pem", type: "pkcs8" }, | 2272 | privateKeyEncoding: { format: "pem", type: "pkcs8" }, |
| 2273 | publicKeyEncoding: { format: "pem", type: "spki" }, | 2273 | publicKeyEncoding: { format: "pem", type: "spki" }, |
| 2274 | }); | 2274 | }); |
| ... | @@ -2345,7 +2345,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { | ... | @@ -2345,7 +2345,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 2345 | Effect.gen(function* () { | 2345 | Effect.gen(function* () { |
| 2346 | yield* buildAppUnderTest(); | 2346 | yield* buildAppUnderTest(); |
| 2347 | 2347 | ||
| 2348 | const cloudKeyPair = generateKeyPairSync("ed25519", { | 2348 | const cloudKeyPair = NodeCrypto.generateKeyPairSync("ed25519", { |
| 2349 | privateKeyEncoding: { format: "pem", type: "pkcs8" }, | 2349 | privateKeyEncoding: { format: "pem", type: "pkcs8" }, |
| 2350 | publicKeyEncoding: { format: "pem", type: "spki" }, | 2350 | publicKeyEncoding: { format: "pem", type: "spki" }, |
| 2351 | }); | 2351 | }); |
| ... | @@ -2404,7 +2404,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { | ... | @@ -2404,7 +2404,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 2404 | Effect.gen(function* () { | 2404 | Effect.gen(function* () { |
| 2405 | yield* buildAppUnderTest(); | 2405 | yield* buildAppUnderTest(); |
| 2406 | 2406 | ||
| 2407 | const cloudKeyPair = generateKeyPairSync("ed25519", { | 2407 | const cloudKeyPair = NodeCrypto.generateKeyPairSync("ed25519", { |
| 2408 | privateKeyEncoding: { format: "pem", type: "pkcs8" }, | 2408 | privateKeyEncoding: { format: "pem", type: "pkcs8" }, |
| 2409 | publicKeyEncoding: { format: "pem", type: "spki" }, | 2409 | publicKeyEncoding: { format: "pem", type: "spki" }, |
| 2410 | }); | 2410 | }); |
| ... | @@ -2463,7 +2463,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { | ... | @@ -2463,7 +2463,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 2463 | Effect.gen(function* () { | 2463 | Effect.gen(function* () { |
| 2464 | yield* buildAppUnderTest(); | 2464 | yield* buildAppUnderTest(); |
| 2465 | 2465 | ||
| 2466 | const cloudKeyPair = generateKeyPairSync("ed25519", { | 2466 | const cloudKeyPair = NodeCrypto.generateKeyPairSync("ed25519", { |
| 2467 | privateKeyEncoding: { format: "pem", type: "pkcs8" }, | 2467 | privateKeyEncoding: { format: "pem", type: "pkcs8" }, |
| 2468 | publicKeyEncoding: { format: "pem", type: "spki" }, | 2468 | publicKeyEncoding: { format: "pem", type: "spki" }, |
| 2469 | }); | 2469 | }); |
| ... | @@ -2523,7 +2523,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { | ... | @@ -2523,7 +2523,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 2523 | Effect.gen(function* () { | 2523 | Effect.gen(function* () { |
| 2524 | yield* buildAppUnderTest(); | 2524 | yield* buildAppUnderTest(); |
| 2525 | 2525 | ||
| 2526 | const cloudKeyPair = generateKeyPairSync("ed25519", { | 2526 | const cloudKeyPair = NodeCrypto.generateKeyPairSync("ed25519", { |
| 2527 | privateKeyEncoding: { format: "pem", type: "pkcs8" }, | 2527 | privateKeyEncoding: { format: "pem", type: "pkcs8" }, |
| 2528 | publicKeyEncoding: { format: "pem", type: "spki" }, | 2528 | publicKeyEncoding: { format: "pem", type: "spki" }, |
| 2529 | }); | 2529 | }); |
| ... | @@ -2584,7 +2584,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { | ... | @@ -2584,7 +2584,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 2584 | Effect.gen(function* () { | 2584 | Effect.gen(function* () { |
| 2585 | yield* buildAppUnderTest(); | 2585 | yield* buildAppUnderTest(); |
| 2586 | 2586 | ||
| 2587 | const cloudKeyPair = generateKeyPairSync("ed25519", { | 2587 | const cloudKeyPair = NodeCrypto.generateKeyPairSync("ed25519", { |
| 2588 | privateKeyEncoding: { format: "pem", type: "pkcs8" }, | 2588 | privateKeyEncoding: { format: "pem", type: "pkcs8" }, |
| 2589 | publicKeyEncoding: { format: "pem", type: "spki" }, | 2589 | publicKeyEncoding: { format: "pem", type: "spki" }, |
| 2590 | }); | 2590 | }); |
| ... | @@ -2664,7 +2664,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { | ... | @@ -2664,7 +2664,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 2664 | }, | 2664 | }, |
| 2665 | }); | 2665 | }); |
| 2666 | 2666 | ||
| 2667 | const cloudKeyPair = generateKeyPairSync("ed25519", { | 2667 | const cloudKeyPair = NodeCrypto.generateKeyPairSync("ed25519", { |
| 2668 | privateKeyEncoding: { format: "pem", type: "pkcs8" }, | 2668 | privateKeyEncoding: { format: "pem", type: "pkcs8" }, |
| 2669 | publicKeyEncoding: { format: "pem", type: "spki" }, | 2669 | publicKeyEncoding: { format: "pem", type: "spki" }, |
| 2670 | }); | 2670 | }); |
| ... | @@ -2733,7 +2733,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { | ... | @@ -2733,7 +2733,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 2733 | Effect.gen(function* () { | 2733 | Effect.gen(function* () { |
| 2734 | yield* buildAppUnderTest(); | 2734 | yield* buildAppUnderTest(); |
| 2735 | 2735 | ||
| 2736 | const cloudKeyPair = generateKeyPairSync("ed25519", { | 2736 | const cloudKeyPair = NodeCrypto.generateKeyPairSync("ed25519", { |
| 2737 | privateKeyEncoding: { format: "pem", type: "pkcs8" }, | 2737 | privateKeyEncoding: { format: "pem", type: "pkcs8" }, |
| 2738 | publicKeyEncoding: { format: "pem", type: "spki" }, | 2738 | publicKeyEncoding: { format: "pem", type: "spki" }, |
| 2739 | }); | 2739 | }); |
| ... | @@ -2800,7 +2800,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { | ... | @@ -2800,7 +2800,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 2800 | Effect.gen(function* () { | 2800 | Effect.gen(function* () { |
| 2801 | yield* buildAppUnderTest(); | 2801 | yield* buildAppUnderTest(); |
| 2802 | 2802 | ||
| 2803 | const cloudKeyPair = generateKeyPairSync("ed25519", { | 2803 | const cloudKeyPair = NodeCrypto.generateKeyPairSync("ed25519", { |
| 2804 | privateKeyEncoding: { format: "pem", type: "pkcs8" }, | 2804 | privateKeyEncoding: { format: "pem", type: "pkcs8" }, |
| 2805 | publicKeyEncoding: { format: "pem", type: "spki" }, | 2805 | publicKeyEncoding: { format: "pem", type: "spki" }, |
| 2806 | }); | 2806 | }); |
| ... | @@ -2851,7 +2851,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { | ... | @@ -2851,7 +2851,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 2851 | Effect.gen(function* () { | 2851 | Effect.gen(function* () { |
| 2852 | yield* buildAppUnderTest(); | 2852 | yield* buildAppUnderTest(); |
| 2853 | 2853 | ||
| 2854 | const cloudKeyPair = generateKeyPairSync("ed25519", { | 2854 | const cloudKeyPair = NodeCrypto.generateKeyPairSync("ed25519", { |
| 2855 | privateKeyEncoding: { format: "pem", type: "pkcs8" }, | 2855 | privateKeyEncoding: { format: "pem", type: "pkcs8" }, |
| 2856 | publicKeyEncoding: { format: "pem", type: "spki" }, | 2856 | publicKeyEncoding: { format: "pem", type: "spki" }, |
| 2857 | }); | 2857 | }); |
| ... | @@ -2902,7 +2902,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { | ... | @@ -2902,7 +2902,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 2902 | Effect.gen(function* () { | 2902 | Effect.gen(function* () { |
| 2903 | yield* buildAppUnderTest(); | 2903 | yield* buildAppUnderTest(); |
| 2904 | 2904 | ||
| 2905 | const cloudKeyPair = generateKeyPairSync("ed25519", { | 2905 | const cloudKeyPair = NodeCrypto.generateKeyPairSync("ed25519", { |
| 2906 | privateKeyEncoding: { format: "pem", type: "pkcs8" }, | 2906 | privateKeyEncoding: { format: "pem", type: "pkcs8" }, |
| 2907 | publicKeyEncoding: { format: "pem", type: "spki" }, | 2907 | publicKeyEncoding: { format: "pem", type: "spki" }, |
| 2908 | }); | 2908 | }); |
| ... | @@ -2967,7 +2967,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { | ... | @@ -2967,7 +2967,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 2967 | Effect.gen(function* () { | 2967 | Effect.gen(function* () { |
| 2968 | yield* buildAppUnderTest(); | 2968 | yield* buildAppUnderTest(); |
| 2969 | 2969 | ||
| 2970 | const cloudKeyPair = generateKeyPairSync("ed25519", { | 2970 | const cloudKeyPair = NodeCrypto.generateKeyPairSync("ed25519", { |
| 2971 | privateKeyEncoding: { format: "pem", type: "pkcs8" }, | 2971 | privateKeyEncoding: { format: "pem", type: "pkcs8" }, |
| 2972 | publicKeyEncoding: { format: "pem", type: "spki" }, | 2972 | publicKeyEncoding: { format: "pem", type: "spki" }, |
| 2973 | }); | 2973 | }); |
| ... | @@ -3017,7 +3017,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { | ... | @@ -3017,7 +3017,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 3017 | Effect.gen(function* () { | 3017 | Effect.gen(function* () { |
| 3018 | yield* buildAppUnderTest(); | 3018 | yield* buildAppUnderTest(); |
| 3019 | 3019 | ||
| 3020 | const cloudKeyPair = generateKeyPairSync("ed25519", { | 3020 | const cloudKeyPair = NodeCrypto.generateKeyPairSync("ed25519", { |
| 3021 | privateKeyEncoding: { format: "pem", type: "pkcs8" }, | 3021 | privateKeyEncoding: { format: "pem", type: "pkcs8" }, |
| 3022 | publicKeyEncoding: { format: "pem", type: "spki" }, | 3022 | publicKeyEncoding: { format: "pem", type: "spki" }, |
| 3023 | }); | 3023 | }); |
apps/server/src/terminal/NodePtyAdapter.ts+2-2| ... | @@ -1,4 +1,4 @@ | ... | @@ -1,4 +1,4 @@ |
| 1 | import { createRequire } from "node:module"; | 1 | import * as NodeModule from "node:module"; |
| 2 | 2 | ||
| 3 | import * as Effect from "effect/Effect"; | 3 | import * as Effect from "effect/Effect"; |
| 4 | import * as FileSystem from "effect/FileSystem"; | 4 | import * as FileSystem from "effect/FileSystem"; |
| ... | @@ -11,7 +11,7 @@ import * as PtyAdapter from "./PtyAdapter.ts"; | ... | @@ -11,7 +11,7 @@ import * as PtyAdapter from "./PtyAdapter.ts"; |
| 11 | let didEnsureSpawnHelperExecutable = false; | 11 | let didEnsureSpawnHelperExecutable = false; |
| 12 | 12 | ||
| 13 | const resolveNodePtySpawnHelperPath = Effect.gen(function* () { | 13 | const resolveNodePtySpawnHelperPath = Effect.gen(function* () { |
| 14 | const requireForNodePty = createRequire(import.meta.url); | 14 | const requireForNodePty = NodeModule.createRequire(import.meta.url); |
| 15 | const path = yield* Path.Path; | 15 | const path = yield* Path.Path; |
| 16 | const fs = yield* FileSystem.FileSystem; | 16 | const fs = yield* FileSystem.FileSystem; |
| 17 | const platform = yield* HostProcessPlatform; | 17 | const platform = yield* HostProcessPlatform; |
apps/server/src/textGeneration/CursorTextGeneration.test.ts+25-21| ... | @@ -1,8 +1,8 @@ | ... | @@ -1,8 +1,8 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off | 1 | // @effect-diagnostics nodeBuiltinImport:off |
| 2 | import * as path from "node:path"; | 2 | import * as NodePath from "node:path"; |
| 3 | import * as os from "node:os"; | 3 | import * as NodeOS from "node:os"; |
| 4 | import { fileURLToPath } from "node:url"; | 4 | import * as NodeURL from "node:url"; |
| 5 | import { chmodSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"; | 5 | import * as NodeFS from "node:fs"; |
| 6 | 6 | ||
| 7 | import * as NodeServices from "@effect/platform-node/NodeServices"; | 7 | import * as NodeServices from "@effect/platform-node/NodeServices"; |
| 8 | import { it } from "@effect/vitest"; | 8 | import { it } from "@effect/vitest"; |
| ... | @@ -21,8 +21,8 @@ import * as TextGeneration from "./TextGeneration.ts"; | ... | @@ -21,8 +21,8 @@ import * as TextGeneration from "./TextGeneration.ts"; |
| 21 | import { makeCursorTextGeneration } from "./CursorTextGeneration.ts"; | 21 | import { makeCursorTextGeneration } from "./CursorTextGeneration.ts"; |
| 22 | const decodeCursorSettings = Schema.decodeSync(CursorSettings); | 22 | const decodeCursorSettings = Schema.decodeSync(CursorSettings); |
| 23 | 23 | ||
| 24 | const __dirname = path.dirname(fileURLToPath(import.meta.url)); | 24 | const __dirname = NodePath.dirname(NodeURL.fileURLToPath(import.meta.url)); |
| 25 | const mockAgentPath = path.join(__dirname, "../../scripts/acp-mock-agent.ts"); | 25 | const mockAgentPath = NodePath.join(__dirname, "../../scripts/acp-mock-agent.ts"); |
| 26 | 26 | ||
| 27 | function shellSingleQuote(value: string): string { | 27 | function shellSingleQuote(value: string): string { |
| 28 | return `'${value.replaceAll("'", `'"'"'`)}'`; | 28 | return `'${value.replaceAll("'", `'"'"'`)}'`; |
| ... | @@ -33,10 +33,10 @@ const CursorTextGenerationTestLayer = ServerConfig.ServerConfig.layerTest(proces | ... | @@ -33,10 +33,10 @@ const CursorTextGenerationTestLayer = ServerConfig.ServerConfig.layerTest(proces |
| 33 | }).pipe(Layer.provideMerge(NodeServices.layer)); | 33 | }).pipe(Layer.provideMerge(NodeServices.layer)); |
| 34 | 34 | ||
| 35 | function makeAcpAgentWrapper(dir: string, env: Record<string, string>): string { | 35 | function makeAcpAgentWrapper(dir: string, env: Record<string, string>): string { |
| 36 | const binDir = path.join(dir, "bin"); | 36 | const binDir = NodePath.join(dir, "bin"); |
| 37 | const agentPath = path.join(binDir, "agent"); | 37 | const agentPath = NodePath.join(binDir, "agent"); |
| 38 | mkdirSync(binDir, { recursive: true }); | 38 | NodeFS.mkdirSync(binDir, { recursive: true }); |
| 39 | writeFileSync( | 39 | NodeFS.writeFileSync( |
| 40 | agentPath, | 40 | agentPath, |
| 41 | [ | 41 | [ |
| 42 | "#!/bin/sh", | 42 | "#!/bin/sh", |
| ... | @@ -50,7 +50,7 @@ function makeAcpAgentWrapper(dir: string, env: Record<string, string>): string { | ... | @@ -50,7 +50,7 @@ function makeAcpAgentWrapper(dir: string, env: Record<string, string>): string { |
| 50 | ].join("\n"), | 50 | ].join("\n"), |
| 51 | "utf8", | 51 | "utf8", |
| 52 | ); | 52 | ); |
| 53 | chmodSync(agentPath, 0o755); | 53 | NodeFS.chmodSync(agentPath, 0o755); |
| 54 | return agentPath; | 54 | return agentPath; |
| 55 | } | 55 | } |
| 56 | 56 | ||
| ... | @@ -59,10 +59,10 @@ function withFakeAcpAgent<A, E, R>( | ... | @@ -59,10 +59,10 @@ function withFakeAcpAgent<A, E, R>( |
| 59 | effectFn: (textGeneration: TextGeneration.TextGeneration["Service"]) => Effect.Effect<A, E, R>, | 59 | effectFn: (textGeneration: TextGeneration.TextGeneration["Service"]) => Effect.Effect<A, E, R>, |
| 60 | ) { | 60 | ) { |
| 61 | return Effect.gen(function* () { | 61 | return Effect.gen(function* () { |
| 62 | const tempDir = mkdtempSync(path.join(os.tmpdir(), "t3code-cursor-text-acp-")); | 62 | const tempDir = NodeFS.mkdtempSync(NodePath.join(NodeOS.tmpdir(), "t3code-cursor-text-acp-")); |
| 63 | yield* Effect.addFinalizer(() => | 63 | yield* Effect.addFinalizer(() => |
| 64 | Effect.sync(() => { | 64 | Effect.sync(() => { |
| 65 | rmSync(tempDir, { recursive: true, force: true }); | 65 | NodeFS.rmSync(tempDir, { recursive: true, force: true }); |
| 66 | }), | 66 | }), |
| 67 | ); | 67 | ); |
| 68 | const agentPath = makeAcpAgentWrapper(tempDir, env); | 68 | const agentPath = makeAcpAgentWrapper(tempDir, env); |
| ... | @@ -76,7 +76,7 @@ function waitForFileContent(path: string): Effect.Effect<string> { | ... | @@ -76,7 +76,7 @@ function waitForFileContent(path: string): Effect.Effect<string> { |
| 76 | return Effect.gen(function* () { | 76 | return Effect.gen(function* () { |
| 77 | const deadline = (yield* Clock.currentTimeMillis) + 5_000; | 77 | const deadline = (yield* Clock.currentTimeMillis) + 5_000; |
| 78 | for (;;) { | 78 | for (;;) { |
| 79 | const result = yield* Effect.exit(Effect.sync(() => readFileSync(path, "utf8"))); | 79 | const result = yield* Effect.exit(Effect.sync(() => NodeFS.readFileSync(path, "utf8"))); |
| 80 | if (Exit.isSuccess(result)) { | 80 | if (Exit.isSuccess(result)) { |
| 81 | return result.value; | 81 | return result.value; |
| 82 | } | 82 | } |
| ... | @@ -92,8 +92,10 @@ function waitForFileContent(path: string): Effect.Effect<string> { | ... | @@ -92,8 +92,10 @@ function waitForFileContent(path: string): Effect.Effect<string> { |
| 92 | 92 | ||
| 93 | it.layer(CursorTextGenerationTestLayer)("CursorTextGeneration", (it) => { | 93 | it.layer(CursorTextGenerationTestLayer)("CursorTextGeneration", (it) => { |
| 94 | it.effect("uses ACP model config options instead of raw CLI model ids", () => { | 94 | it.effect("uses ACP model config options instead of raw CLI model ids", () => { |
| 95 | const requestLogDir = mkdtempSync(path.join(os.tmpdir(), "t3code-cursor-text-log-")); | 95 | const requestLogDir = NodeFS.mkdtempSync( |
| 96 | const requestLogPath = path.join(requestLogDir, "requests.ndjson"); | 96 | NodePath.join(NodeOS.tmpdir(), "t3code-cursor-text-log-"), |
| 97 | ); | ||
| 98 | const requestLogPath = NodePath.join(requestLogDir, "requests.ndjson"); | ||
| 97 | 99 | ||
| 98 | return withFakeAcpAgent( | 100 | return withFakeAcpAgent( |
| 99 | { | 101 | { |
| ... | @@ -123,7 +125,7 @@ it.layer(CursorTextGenerationTestLayer)("CursorTextGeneration", (it) => { | ... | @@ -123,7 +125,7 @@ it.layer(CursorTextGenerationTestLayer)("CursorTextGeneration", (it) => { |
| 123 | expect(generated.subject).toBe("Add generated commit message"); | 125 | expect(generated.subject).toBe("Add generated commit message"); |
| 124 | expect(generated.body).toBe("- verify cursor acp model config path"); | 126 | expect(generated.body).toBe("- verify cursor acp model config path"); |
| 125 | 127 | ||
| 126 | const requests = readFileSync(requestLogPath, "utf8") | 128 | const requests = NodeFS.readFileSync(requestLogPath, "utf8") |
| 127 | .trim() | 129 | .trim() |
| 128 | .split("\n") | 130 | .split("\n") |
| 129 | .filter((line) => line.length > 0) | 131 | .filter((line) => line.length > 0) |
| ... | @@ -181,7 +183,7 @@ it.layer(CursorTextGenerationTestLayer)("CursorTextGeneration", (it) => { | ... | @@ -181,7 +183,7 @@ it.layer(CursorTextGenerationTestLayer)("CursorTextGeneration", (it) => { |
| 181 | ]), | 183 | ]), |
| 182 | ); | 184 | ); |
| 183 | 185 | ||
| 184 | rmSync(requestLogDir, { recursive: true, force: true }); | 186 | NodeFS.rmSync(requestLogDir, { recursive: true, force: true }); |
| 185 | }), | 187 | }), |
| 186 | ); | 188 | ); |
| 187 | }); | 189 | }); |
| ... | @@ -235,8 +237,10 @@ it.layer(CursorTextGenerationTestLayer)("CursorTextGeneration", (it) => { | ... | @@ -235,8 +237,10 @@ it.layer(CursorTextGenerationTestLayer)("CursorTextGeneration", (it) => { |
| 235 | ); | 237 | ); |
| 236 | 238 | ||
| 237 | it.effect("closes the ACP child process after text generation completes", () => { | 239 | it.effect("closes the ACP child process after text generation completes", () => { |
| 238 | const exitLogDir = mkdtempSync(path.join(os.tmpdir(), "t3code-cursor-text-exit-log-")); | 240 | const exitLogDir = NodeFS.mkdtempSync( |
| 239 | const exitLogPath = path.join(exitLogDir, "exit.log"); | 241 | NodePath.join(NodeOS.tmpdir(), "t3code-cursor-text-exit-log-"), |
| 242 | ); | ||
| 243 | const exitLogPath = NodePath.join(exitLogDir, "exit.log"); | ||
| 240 | 244 | ||
| 241 | return withFakeAcpAgent( | 245 | return withFakeAcpAgent( |
| 242 | { | 246 | { |
| ... | @@ -265,7 +269,7 @@ it.layer(CursorTextGenerationTestLayer)("CursorTextGeneration", (it) => { | ... | @@ -265,7 +269,7 @@ it.layer(CursorTextGenerationTestLayer)("CursorTextGeneration", (it) => { |
| 265 | const exitLog = yield* waitForFileContent(exitLogPath); | 269 | const exitLog = yield* waitForFileContent(exitLogPath); |
| 266 | expect(exitLog).toContain("exit:0"); | 270 | expect(exitLog).toContain("exit:0"); |
| 267 | 271 | ||
| 268 | rmSync(exitLogDir, { recursive: true, force: true }); | 272 | NodeFS.rmSync(exitLogDir, { recursive: true, force: true }); |
| 269 | }), | 273 | }), |
| 270 | ); | 274 | ); |
| 271 | }); | 275 | }); |
apps/server/src/textGeneration/GrokTextGeneration.test.ts+18-16| ... | @@ -1,8 +1,8 @@ | ... | @@ -1,8 +1,8 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off | 1 | // @effect-diagnostics nodeBuiltinImport:off |
| 2 | import * as path from "node:path"; | 2 | import * as NodePath from "node:path"; |
| 3 | import * as os from "node:os"; | 3 | import * as NodeOS from "node:os"; |
| 4 | import { fileURLToPath } from "node:url"; | 4 | import * as NodeURL from "node:url"; |
| 5 | import { chmodSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"; | 5 | import * as NodeFS from "node:fs"; |
| 6 | 6 | ||
| 7 | import * as NodeServices from "@effect/platform-node/NodeServices"; | 7 | import * as NodeServices from "@effect/platform-node/NodeServices"; |
| 8 | import { it } from "@effect/vitest"; | 8 | import { it } from "@effect/vitest"; |
| ... | @@ -18,8 +18,8 @@ import * as TextGeneration from "./TextGeneration.ts"; | ... | @@ -18,8 +18,8 @@ import * as TextGeneration from "./TextGeneration.ts"; |
| 18 | import { makeGrokTextGeneration } from "./GrokTextGeneration.ts"; | 18 | import { makeGrokTextGeneration } from "./GrokTextGeneration.ts"; |
| 19 | const decodeGrokSettings = Schema.decodeSync(GrokSettings); | 19 | const decodeGrokSettings = Schema.decodeSync(GrokSettings); |
| 20 | 20 | ||
| 21 | const __dirname = path.dirname(fileURLToPath(import.meta.url)); | 21 | const __dirname = NodePath.dirname(NodeURL.fileURLToPath(import.meta.url)); |
| 22 | const mockAgentPath = path.join(__dirname, "../../scripts/acp-mock-agent.ts"); | 22 | const mockAgentPath = NodePath.join(__dirname, "../../scripts/acp-mock-agent.ts"); |
| 23 | 23 | ||
| 24 | function shellSingleQuote(value: string): string { | 24 | function shellSingleQuote(value: string): string { |
| 25 | return `'${value.replaceAll("'", `'"'"'`)}'`; | 25 | return `'${value.replaceAll("'", `'"'"'`)}'`; |
| ... | @@ -30,10 +30,10 @@ const GrokTextGenerationTestLayer = ServerConfig.ServerConfig.layerTest(process. | ... | @@ -30,10 +30,10 @@ const GrokTextGenerationTestLayer = ServerConfig.ServerConfig.layerTest(process. |
| 30 | }).pipe(Layer.provideMerge(NodeServices.layer)); | 30 | }).pipe(Layer.provideMerge(NodeServices.layer)); |
| 31 | 31 | ||
| 32 | function makeAcpGrokWrapper(dir: string, env: Record<string, string>): string { | 32 | function makeAcpGrokWrapper(dir: string, env: Record<string, string>): string { |
| 33 | const binDir = path.join(dir, "bin"); | 33 | const binDir = NodePath.join(dir, "bin"); |
| 34 | const grokPath = path.join(binDir, "grok"); | 34 | const grokPath = NodePath.join(binDir, "grok"); |
| 35 | mkdirSync(binDir, { recursive: true }); | 35 | NodeFS.mkdirSync(binDir, { recursive: true }); |
| 36 | writeFileSync( | 36 | NodeFS.writeFileSync( |
| 37 | grokPath, | 37 | grokPath, |
| 38 | [ | 38 | [ |
| 39 | "#!/bin/sh", | 39 | "#!/bin/sh", |
| ... | @@ -47,7 +47,7 @@ function makeAcpGrokWrapper(dir: string, env: Record<string, string>): string { | ... | @@ -47,7 +47,7 @@ function makeAcpGrokWrapper(dir: string, env: Record<string, string>): string { |
| 47 | ].join("\n"), | 47 | ].join("\n"), |
| 48 | "utf8", | 48 | "utf8", |
| 49 | ); | 49 | ); |
| 50 | chmodSync(grokPath, 0o755); | 50 | NodeFS.chmodSync(grokPath, 0o755); |
| 51 | return grokPath; | 51 | return grokPath; |
| 52 | } | 52 | } |
| 53 | 53 | ||
| ... | @@ -56,10 +56,10 @@ function withFakeAcpGrok<A, E, R>( | ... | @@ -56,10 +56,10 @@ function withFakeAcpGrok<A, E, R>( |
| 56 | effectFn: (textGeneration: TextGeneration.TextGeneration["Service"]) => Effect.Effect<A, E, R>, | 56 | effectFn: (textGeneration: TextGeneration.TextGeneration["Service"]) => Effect.Effect<A, E, R>, |
| 57 | ) { | 57 | ) { |
| 58 | return Effect.gen(function* () { | 58 | return Effect.gen(function* () { |
| 59 | const tempDir = mkdtempSync(path.join(os.tmpdir(), "t3code-grok-text-acp-")); | 59 | const tempDir = NodeFS.mkdtempSync(NodePath.join(NodeOS.tmpdir(), "t3code-grok-text-acp-")); |
| 60 | yield* Effect.addFinalizer(() => | 60 | yield* Effect.addFinalizer(() => |
| 61 | Effect.sync(() => { | 61 | Effect.sync(() => { |
| 62 | rmSync(tempDir, { recursive: true, force: true }); | 62 | NodeFS.rmSync(tempDir, { recursive: true, force: true }); |
| 63 | }), | 63 | }), |
| 64 | ); | 64 | ); |
| 65 | const binaryPath = makeAcpGrokWrapper(tempDir, env); | 65 | const binaryPath = makeAcpGrokWrapper(tempDir, env); |
| ... | @@ -72,7 +72,7 @@ function withFakeAcpGrok<A, E, R>( | ... | @@ -72,7 +72,7 @@ function withFakeAcpGrok<A, E, R>( |
| 72 | function readJsonRpcRequests( | 72 | function readJsonRpcRequests( |
| 73 | filePath: string, | 73 | filePath: string, |
| 74 | ): ReadonlyArray<{ readonly method?: string; readonly params?: Record<string, unknown> }> { | 74 | ): ReadonlyArray<{ readonly method?: string; readonly params?: Record<string, unknown> }> { |
| 75 | return readFileSync(filePath, "utf8") | 75 | return NodeFS.readFileSync(filePath, "utf8") |
| 76 | .trim() | 76 | .trim() |
| 77 | .split("\n") | 77 | .split("\n") |
| 78 | .filter((line) => line.length > 0) | 78 | .filter((line) => line.length > 0) |
| ... | @@ -81,8 +81,10 @@ function readJsonRpcRequests( | ... | @@ -81,8 +81,10 @@ function readJsonRpcRequests( |
| 81 | 81 | ||
| 82 | it.layer(GrokTextGenerationTestLayer)("GrokTextGeneration", (it) => { | 82 | it.layer(GrokTextGenerationTestLayer)("GrokTextGeneration", (it) => { |
| 83 | it.effect("uses ACP with disabled tool capabilities and forwards the requested model id", () => { | 83 | it.effect("uses ACP with disabled tool capabilities and forwards the requested model id", () => { |
| 84 | const requestLogDir = mkdtempSync(path.join(os.tmpdir(), "t3code-grok-text-log-")); | 84 | const requestLogDir = NodeFS.mkdtempSync( |
| 85 | const requestLogPath = path.join(requestLogDir, "requests.ndjson"); | 85 | NodePath.join(NodeOS.tmpdir(), "t3code-grok-text-log-"), |
| 86 | ); | ||
| 87 | const requestLogPath = NodePath.join(requestLogDir, "requests.ndjson"); | ||
| 86 | 88 | ||
| 87 | return withFakeAcpGrok( | 89 | return withFakeAcpGrok( |
| 88 | { | 90 | { |
apps/server/src/vcs/GitVcsDriver.ts+5-2| ... | @@ -1,4 +1,4 @@ | ... | @@ -1,4 +1,4 @@ |
| 1 | import { randomUUID } from "node:crypto"; | 1 | import * as NodeCrypto from "node:crypto"; |
| 2 | 2 | ||
| 3 | import * as Context from "effect/Context"; | 3 | import * as Context from "effect/Context"; |
| 4 | import * as DateTime from "effect/DateTime"; | 4 | import * as DateTime from "effect/DateTime"; |
| ... | @@ -651,7 +651,10 @@ export const makeVcsDriverShape = Effect.fn("makeGitVcsDriverShape")(function* ( | ... | @@ -651,7 +651,10 @@ export const makeVcsDriverShape = Effect.fn("makeGitVcsDriverShape")(function* ( |
| 651 | captureCheckpoint: Effect.fn("GitVcsDriver.checkpoints.captureCheckpoint")(function* (input) { | 651 | captureCheckpoint: Effect.fn("GitVcsDriver.checkpoints.captureCheckpoint")(function* (input) { |
| 652 | const operation = "GitVcsDriver.checkpoints.captureCheckpoint"; | 652 | const operation = "GitVcsDriver.checkpoints.captureCheckpoint"; |
| 653 | const gitCommonDir = yield* resolveGitCommonDir(input.cwd); | 653 | const gitCommonDir = yield* resolveGitCommonDir(input.cwd); |
| 654 | const tempIndexPath = path.join(gitCommonDir, `t3-checkpoint-index-${randomUUID()}`); | 654 | const tempIndexPath = path.join( |
| 655 | gitCommonDir, | ||
| 656 | `t3-checkpoint-index-${NodeCrypto.randomUUID()}`, | ||
| 657 | ); | ||
| 655 | const commitEnv: NodeJS.ProcessEnv = { | 658 | const commitEnv: NodeJS.ProcessEnv = { |
| 656 | ...process.env, | 659 | ...process.env, |
| 657 | GIT_INDEX_FILE: tempIndexPath, | 660 | GIT_INDEX_FILE: tempIndexPath, |
apps/server/src/workspace/WorkspaceEntries.test.ts+9-3| ... | @@ -1,13 +1,14 @@ | ... | @@ -1,13 +1,14 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off | 1 | // @effect-diagnostics nodeBuiltinImport:off |
| 2 | import fsPromises from "node:fs/promises"; | 2 | import * as NodeFSP from "node:fs/promises"; |
| 3 | import * as NodeServices from "@effect/platform-node/NodeServices"; | 3 | import * as NodeServices from "@effect/platform-node/NodeServices"; |
| 4 | import { FileFinder } from "@ff-labs/fff-node"; | 4 | import { FileFinder } from "@ff-labs/fff-node"; |
| 5 | import { it, afterEach, describe, expect, vi } from "@effect/vitest"; | 5 | import { it, afterEach, describe, expect } from "@effect/vitest"; |
| 6 | import * as Effect from "effect/Effect"; | 6 | import * as Effect from "effect/Effect"; |
| 7 | import * as FileSystem from "effect/FileSystem"; | 7 | import * as FileSystem from "effect/FileSystem"; |
| 8 | import * as Layer from "effect/Layer"; | 8 | import * as Layer from "effect/Layer"; |
| 9 | import * as Path from "effect/Path"; | 9 | import * as Path from "effect/Path"; |
| 10 | import * as PlatformError from "effect/PlatformError"; | 10 | import * as PlatformError from "effect/PlatformError"; |
| 11 | import { vi } from "vite-plus/test"; | ||
| 11 | 12 | ||
| 12 | import * as ServerConfig from "../config.ts"; | 13 | import * as ServerConfig from "../config.ts"; |
| 13 | import { HostProcessPlatform } from "@t3tools/shared/hostProcess"; | 14 | import { HostProcessPlatform } from "@t3tools/shared/hostProcess"; |
| ... | @@ -15,6 +16,11 @@ import * as VcsProcess from "../vcs/VcsProcess.ts"; | ... | @@ -15,6 +16,11 @@ import * as VcsProcess from "../vcs/VcsProcess.ts"; |
| 15 | import * as WorkspaceEntries from "./WorkspaceEntries.ts"; | 16 | import * as WorkspaceEntries from "./WorkspaceEntries.ts"; |
| 16 | import * as WorkspacePaths from "./WorkspacePaths.ts"; | 17 | import * as WorkspacePaths from "./WorkspacePaths.ts"; |
| 17 | 18 | ||
| 19 | vi.mock("node:fs/promises", async (importOriginal) => { | ||
| 20 | const actual = await importOriginal<typeof import("node:fs/promises")>(); | ||
| 21 | return { ...actual, readdir: vi.fn(actual.readdir) }; | ||
| 22 | }); | ||
| 23 | |||
| 18 | const TestLayer = Layer.empty.pipe( | 24 | const TestLayer = Layer.empty.pipe( |
| 19 | Layer.provideMerge(WorkspaceEntries.layer.pipe(Layer.provide(WorkspacePaths.layer))), | 25 | Layer.provideMerge(WorkspaceEntries.layer.pipe(Layer.provide(WorkspacePaths.layer))), |
| 20 | Layer.provideMerge(WorkspacePaths.layer), | 26 | Layer.provideMerge(WorkspacePaths.layer), |
| ... | @@ -376,7 +382,7 @@ it.layer(TestLayer, { excludeTestServices: true })("WorkspaceEntries", (it) => { | ... | @@ -376,7 +382,7 @@ it.layer(TestLayer, { excludeTestServices: true })("WorkspaceEntries", (it) => { |
| 376 | const cwd = yield* makeTempDir({ prefix: "t3code-workspace-browse-eacces-" }); | 382 | const cwd = yield* makeTempDir({ prefix: "t3code-workspace-browse-eacces-" }); |
| 377 | 383 | ||
| 378 | const denied = Object.assign(new Error("EACCES: permission denied"), { code: "EACCES" }); | 384 | const denied = Object.assign(new Error("EACCES: permission denied"), { code: "EACCES" }); |
| 379 | vi.spyOn(fsPromises, "readdir").mockRejectedValueOnce(denied); | 385 | vi.mocked(NodeFSP.readdir).mockRejectedValueOnce(denied); |
| 380 | 386 | ||
| 381 | const result = yield* workspaceEntries.browse({ | 387 | const result = yield* workspaceEntries.browse({ |
| 382 | partialPath: yield* appendSeparator(cwd), | 388 | partialPath: yield* appendSeparator(cwd), |
apps/server/src/workspace/WorkspaceEntries.ts+5-5| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off | 1 | // @effect-diagnostics nodeBuiltinImport:off |
| 2 | import { readdir } from "node:fs/promises"; | 2 | import * as NodeFSP from "node:fs/promises"; |
| 3 | import { homedir } from "node:os"; | 3 | import * as NodeOS from "node:os"; |
| 4 | 4 | ||
| 5 | import * as Context from "effect/Context"; | 5 | import * as Context from "effect/Context"; |
| 6 | import * as Effect from "effect/Effect"; | 6 | import * as Effect from "effect/Effect"; |
| ... | @@ -98,10 +98,10 @@ export class WorkspaceEntries extends Context.Service< | ... | @@ -98,10 +98,10 @@ export class WorkspaceEntries extends Context.Service< |
| 98 | 98 | ||
| 99 | function expandHomePath(input: string, path: Path.Path): string { | 99 | function expandHomePath(input: string, path: Path.Path): string { |
| 100 | if (input === "~") { | 100 | if (input === "~") { |
| 101 | return homedir(); | 101 | return NodeOS.homedir(); |
| 102 | } | 102 | } |
| 103 | if (input.startsWith("~/") || input.startsWith("~\\")) { | 103 | if (input.startsWith("~/") || input.startsWith("~\\")) { |
| 104 | return path.join(homedir(), input.slice(2)); | 104 | return path.join(NodeOS.homedir(), input.slice(2)); |
| 105 | } | 105 | } |
| 106 | return input; | 106 | return input; |
| 107 | } | 107 | } |
| ... | @@ -176,7 +176,7 @@ export const make = Effect.gen(function* () { | ... | @@ -176,7 +176,7 @@ export const make = Effect.gen(function* () { |
| 176 | const prefix = endsWithSeparator ? "" : path.basename(resolvedInputPath); | 176 | const prefix = endsWithSeparator ? "" : path.basename(resolvedInputPath); |
| 177 | 177 | ||
| 178 | const dirents = yield* Effect.tryPromise({ | 178 | const dirents = yield* Effect.tryPromise({ |
| 179 | try: () => readdir(parentPath, { withFileTypes: true }), | 179 | try: () => NodeFSP.readdir(parentPath, { withFileTypes: true }), |
| 180 | catch: (cause) => | 180 | catch: (cause) => |
| 181 | new WorkspaceEntriesReadDirectoryError({ | 181 | new WorkspaceEntriesReadDirectoryError({ |
| 182 | cwd: input.cwd, | 182 | cwd: input.cwd, |
apps/server/src/workspace/WorkspaceFileSystem.ts+4-4| ... | @@ -7,7 +7,7 @@ | ... | @@ -7,7 +7,7 @@ |
| 7 | * | 7 | * |
| 8 | * @module WorkspaceFileSystem | 8 | * @module WorkspaceFileSystem |
| 9 | */ | 9 | */ |
| 10 | import { open, realpath } from "node:fs/promises"; | 10 | import * as NodeFSP from "node:fs/promises"; |
| 11 | 11 | ||
| 12 | import type { | 12 | import type { |
| 13 | ProjectReadFileInput, | 13 | ProjectReadFileInput, |
| ... | @@ -89,8 +89,8 @@ export const make = Effect.gen(function* () { | ... | @@ -89,8 +89,8 @@ export const make = Effect.gen(function* () { |
| 89 | return yield* Effect.tryPromise({ | 89 | return yield* Effect.tryPromise({ |
| 90 | try: async () => { | 90 | try: async () => { |
| 91 | const [realWorkspaceRoot, realTargetPath] = await Promise.all([ | 91 | const [realWorkspaceRoot, realTargetPath] = await Promise.all([ |
| 92 | realpath(input.cwd), | 92 | NodeFSP.realpath(input.cwd), |
| 93 | realpath(target.absolutePath), | 93 | NodeFSP.realpath(target.absolutePath), |
| 94 | ]); | 94 | ]); |
| 95 | const relativeRealPath = path.relative(realWorkspaceRoot, realTargetPath); | 95 | const relativeRealPath = path.relative(realWorkspaceRoot, realTargetPath); |
| 96 | if ( | 96 | if ( |
| ... | @@ -101,7 +101,7 @@ export const make = Effect.gen(function* () { | ... | @@ -101,7 +101,7 @@ export const make = Effect.gen(function* () { |
| 101 | throw new Error("Workspace file path resolves outside the project root."); | 101 | throw new Error("Workspace file path resolves outside the project root."); |
| 102 | } | 102 | } |
| 103 | 103 | ||
| 104 | const handle = await open(realTargetPath, "r"); | 104 | const handle = await NodeFSP.open(realTargetPath, "r"); |
| 105 | try { | 105 | try { |
| 106 | const stat = await handle.stat(); | 106 | const stat = await handle.stat(); |
| 107 | if (!stat.isFile()) { | 107 | if (!stat.isFile()) { |
apps/server/src/workspace/WorkspacePaths.ts+3-3| ... | @@ -6,7 +6,7 @@ | ... | @@ -6,7 +6,7 @@ |
| 6 | * | 6 | * |
| 7 | * @module WorkspacePaths | 7 | * @module WorkspacePaths |
| 8 | */ | 8 | */ |
| 9 | import { homedir } from "node:os"; | 9 | import * as NodeOS from "node:os"; |
| 10 | 10 | ||
| 11 | import * as Context from "effect/Context"; | 11 | import * as Context from "effect/Context"; |
| 12 | import * as Effect from "effect/Effect"; | 12 | import * as Effect from "effect/Effect"; |
| ... | @@ -105,10 +105,10 @@ function toPosixRelativePath(input: string): string { | ... | @@ -105,10 +105,10 @@ function toPosixRelativePath(input: string): string { |
| 105 | 105 | ||
| 106 | function expandHomePath(input: string, path: Path.Path): string { | 106 | function expandHomePath(input: string, path: Path.Path): string { |
| 107 | if (input === "~") { | 107 | if (input === "~") { |
| 108 | return homedir(); | 108 | return NodeOS.homedir(); |
| 109 | } | 109 | } |
| 110 | if (input.startsWith("~/") || input.startsWith("~\\")) { | 110 | if (input.startsWith("~/") || input.startsWith("~\\")) { |
| 111 | return path.join(homedir(), input.slice(2)); | 111 | return path.join(NodeOS.homedir(), input.slice(2)); |
| 112 | } | 112 | } |
| 113 | return input; | 113 | return input; |
| 114 | } | 114 | } |
oxlint-plugin-t3code/index.ts+2| ... | @@ -1,5 +1,6 @@ | ... | @@ -1,5 +1,6 @@ |
| 1 | import { definePlugin } from "@oxlint/plugins"; | 1 | import { definePlugin } from "@oxlint/plugins"; |
| 2 | 2 | ||
| 3 | import namespaceNodeImports from "./rules/namespace-node-imports.ts"; | ||
| 3 | import noGlobalProcessRuntime from "./rules/no-global-process-runtime.ts"; | 4 | import noGlobalProcessRuntime from "./rules/no-global-process-runtime.ts"; |
| 4 | import noInlineSchemaCompile from "./rules/no-inline-schema-compile.ts"; | 5 | import noInlineSchemaCompile from "./rules/no-inline-schema-compile.ts"; |
| 5 | import noManualEffectRuntimeInTests from "./rules/no-manual-effect-runtime-in-tests.ts"; | 6 | import noManualEffectRuntimeInTests from "./rules/no-manual-effect-runtime-in-tests.ts"; |
| ... | @@ -9,6 +10,7 @@ export default definePlugin({ | ... | @@ -9,6 +10,7 @@ export default definePlugin({ |
| 9 | name: "t3code", | 10 | name: "t3code", |
| 10 | }, | 11 | }, |
| 11 | rules: { | 12 | rules: { |
| 13 | "namespace-node-imports": namespaceNodeImports, | ||
| 12 | "no-global-process-runtime": noGlobalProcessRuntime, | 14 | "no-global-process-runtime": noGlobalProcessRuntime, |
| 13 | "no-inline-schema-compile": noInlineSchemaCompile, | 15 | "no-inline-schema-compile": noInlineSchemaCompile, |
| 14 | "no-manual-effect-runtime-in-tests": noManualEffectRuntimeInTests, | 16 | "no-manual-effect-runtime-in-tests": noManualEffectRuntimeInTests, |
oxlint-plugin-t3code/rules/namespace-node-imports.test.ts created+63| ... | @@ -0,0 +1,63 @@ | ||
| 1 | import { assert, describe } from "@effect/vitest"; | ||
| 2 | |||
| 3 | import { createOxlintRuleHarness } from "../test/utils.ts"; | ||
| 4 | |||
| 5 | const rule = createOxlintRuleHarness("t3code/namespace-node-imports"); | ||
| 6 | |||
| 7 | describe("t3code/namespace-node-imports", () => { | ||
| 8 | rule.valid( | ||
| 9 | "allows canonical Node namespaces", | ||
| 10 | ` | ||
| 11 | import * as NodeFS from "node:fs"; | ||
| 12 | import * as NodeFSP from "node:fs/promises"; | ||
| 13 | import * as NodeAssert from "node:assert/strict"; | ||
| 14 | import * as NodeChildProcess from "node:child_process"; | ||
| 15 | import * as NodeTimersPromises from "node:timers/promises"; | ||
| 16 | import type * as NodeStream from "node:stream"; | ||
| 17 | |||
| 18 | NodeAssert.ok(NodeChildProcess.spawn && NodeTimersPromises.setTimeout); | ||
| 19 | export const read = NodeFS.readFileSync; | ||
| 20 | export const readAsync = NodeFSP.readFile; | ||
| 21 | export type Input = NodeStream.Readable; | ||
| 22 | `, | ||
| 23 | ); | ||
| 24 | |||
| 25 | rule.valid( | ||
| 26 | "does not apply to non-Node packages", | ||
| 27 | ` | ||
| 28 | import { BrowserWindow } from "electron"; | ||
| 29 | `, | ||
| 30 | ); | ||
| 31 | |||
| 32 | rule.invalid( | ||
| 33 | "reports named imports", | ||
| 34 | ` | ||
| 35 | import { readFile } from "node:fs/promises"; | ||
| 36 | `, | ||
| 37 | (output) => { | ||
| 38 | assert.match(output, /namespace named NodeFSP/); | ||
| 39 | }, | ||
| 40 | ); | ||
| 41 | |||
| 42 | rule.invalid( | ||
| 43 | "reports default imports", | ||
| 44 | ` | ||
| 45 | import path from "node:path"; | ||
| 46 | `, | ||
| 47 | (output) => { | ||
| 48 | assert.match(output, /namespace named NodePath/); | ||
| 49 | }, | ||
| 50 | ); | ||
| 51 | |||
| 52 | rule.invalid( | ||
| 53 | "reports non-canonical namespace aliases", | ||
| 54 | ` | ||
| 55 | import * as Crypto from "node:crypto"; | ||
| 56 | import * as NodeOs from "node:os"; | ||
| 57 | `, | ||
| 58 | (output) => { | ||
| 59 | assert.match(output, /namespace named NodeCrypto/); | ||
| 60 | assert.match(output, /namespace named NodeOS/); | ||
| 61 | }, | ||
| 62 | ); | ||
| 63 | }); | ||
oxlint-plugin-t3code/rules/namespace-node-imports.ts created+76| ... | @@ -0,0 +1,76 @@ | ||
| 1 | import { defineRule } from "@oxlint/plugins"; | ||
| 2 | |||
| 3 | const NODE_MODULE_ALIASES = new Map([ | ||
| 4 | ["assert/strict", "Assert"], | ||
| 5 | ["fs/promises", "FSP"], | ||
| 6 | ]); | ||
| 7 | |||
| 8 | const NODE_SEGMENT_ALIASES = new Map([ | ||
| 9 | ["fs", "FS"], | ||
| 10 | ["os", "OS"], | ||
| 11 | ["url", "URL"], | ||
| 12 | ["vm", "VM"], | ||
| 13 | ]); | ||
| 14 | |||
| 15 | const toPascalCase = (value: string) => | ||
| 16 | value | ||
| 17 | .split(/[_-]/u) | ||
| 18 | .filter((segment) => segment.length > 0) | ||
| 19 | .map((segment) => segment[0]?.toUpperCase() + segment.slice(1)) | ||
| 20 | .join(""); | ||
| 21 | |||
| 22 | const expectedNamespaceAlias = (source: string) => { | ||
| 23 | const moduleName = source.slice("node:".length); | ||
| 24 | const knownAlias = NODE_MODULE_ALIASES.get(moduleName); | ||
| 25 | if (knownAlias !== undefined) return `Node${knownAlias}`; | ||
| 26 | |||
| 27 | return `Node${moduleName | ||
| 28 | .split("/") | ||
| 29 | .map((segment) => NODE_SEGMENT_ALIASES.get(segment) ?? toPascalCase(segment)) | ||
| 30 | .join("")}`; | ||
| 31 | }; | ||
| 32 | |||
| 33 | const literalStringValue = (node: unknown): string | undefined => { | ||
| 34 | if (typeof node !== "object" || node === null) return undefined; | ||
| 35 | if (!("type" in node) || node.type !== "Literal") return undefined; | ||
| 36 | if (!("value" in node) || typeof node.value !== "string") return undefined; | ||
| 37 | return node.value; | ||
| 38 | }; | ||
| 39 | |||
| 40 | const identifierName = (node: unknown): string | undefined => { | ||
| 41 | if (typeof node !== "object" || node === null) return undefined; | ||
| 42 | if (!("type" in node) || node.type !== "Identifier") return undefined; | ||
| 43 | if (!("name" in node) || typeof node.name !== "string") return undefined; | ||
| 44 | return node.name; | ||
| 45 | }; | ||
| 46 | |||
| 47 | export default defineRule({ | ||
| 48 | meta: { | ||
| 49 | type: "problem", | ||
| 50 | docs: { | ||
| 51 | description: "Require canonical namespace imports for Node.js built-in modules.", | ||
| 52 | }, | ||
| 53 | }, | ||
| 54 | create(context) { | ||
| 55 | return { | ||
| 56 | ImportDeclaration(node) { | ||
| 57 | const source = literalStringValue(node.source); | ||
| 58 | if (source === undefined || !source.startsWith("node:")) return; | ||
| 59 | |||
| 60 | const expectedAlias = expectedNamespaceAlias(source); | ||
| 61 | const namespaceImport = | ||
| 62 | node.specifiers.length === 1 && node.specifiers[0]?.type === "ImportNamespaceSpecifier" | ||
| 63 | ? node.specifiers[0] | ||
| 64 | : undefined; | ||
| 65 | const actualAlias = identifierName(namespaceImport?.local); | ||
| 66 | |||
| 67 | if (actualAlias === expectedAlias) return; | ||
| 68 | |||
| 69 | context.report({ | ||
| 70 | node, | ||
| 71 | message: `Import ${source} as a namespace named ${expectedAlias}.`, | ||
| 72 | }); | ||
| 73 | }, | ||
| 74 | }; | ||
| 75 | }, | ||
| 76 | }); | ||
packages/shared/src/logging.ts+15-15| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off | 1 | // @effect-diagnostics nodeBuiltinImport:off |
| 2 | import fs from "node:fs"; | 2 | import * as NodeFS from "node:fs"; |
| 3 | import path from "node:path"; | 3 | import * as NodePath from "node:path"; |
| 4 | 4 | ||
| 5 | export interface RotatingFileSinkOptions { | 5 | export interface RotatingFileSinkOptions { |
| 6 | readonly filePath: string; | 6 | readonly filePath: string; |
| ... | @@ -29,7 +29,7 @@ export class RotatingFileSink { | ... | @@ -29,7 +29,7 @@ export class RotatingFileSink { |
| 29 | this.maxFiles = options.maxFiles; | 29 | this.maxFiles = options.maxFiles; |
| 30 | this.throwOnError = options.throwOnError ?? false; | 30 | this.throwOnError = options.throwOnError ?? false; |
| 31 | 31 | ||
| 32 | fs.mkdirSync(path.dirname(this.filePath), { recursive: true }); | 32 | NodeFS.mkdirSync(NodePath.dirname(this.filePath), { recursive: true }); |
| 33 | this.pruneOverflowBackups(); | 33 | this.pruneOverflowBackups(); |
| 34 | this.currentSize = this.readCurrentSize(); | 34 | this.currentSize = this.readCurrentSize(); |
| 35 | } | 35 | } |
| ... | @@ -43,7 +43,7 @@ export class RotatingFileSink { | ... | @@ -43,7 +43,7 @@ export class RotatingFileSink { |
| 43 | this.rotate(); | 43 | this.rotate(); |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | fs.appendFileSync(this.filePath, buffer); | 46 | NodeFS.appendFileSync(this.filePath, buffer); |
| 47 | this.currentSize += buffer.length; | 47 | this.currentSize += buffer.length; |
| 48 | 48 | ||
| 49 | if (this.currentSize > this.maxBytes) { | 49 | if (this.currentSize > this.maxBytes) { |
| ... | @@ -60,20 +60,20 @@ export class RotatingFileSink { | ... | @@ -60,20 +60,20 @@ export class RotatingFileSink { |
| 60 | private rotate(): void { | 60 | private rotate(): void { |
| 61 | try { | 61 | try { |
| 62 | const oldest = this.withSuffix(this.maxFiles); | 62 | const oldest = this.withSuffix(this.maxFiles); |
| 63 | if (fs.existsSync(oldest)) { | 63 | if (NodeFS.existsSync(oldest)) { |
| 64 | fs.rmSync(oldest, { force: true }); | 64 | NodeFS.rmSync(oldest, { force: true }); |
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | for (let index = this.maxFiles - 1; index >= 1; index -= 1) { | 67 | for (let index = this.maxFiles - 1; index >= 1; index -= 1) { |
| 68 | const source = this.withSuffix(index); | 68 | const source = this.withSuffix(index); |
| 69 | const target = this.withSuffix(index + 1); | 69 | const target = this.withSuffix(index + 1); |
| 70 | if (fs.existsSync(source)) { | 70 | if (NodeFS.existsSync(source)) { |
| 71 | fs.renameSync(source, target); | 71 | NodeFS.renameSync(source, target); |
| 72 | } | 72 | } |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | if (fs.existsSync(this.filePath)) { | 75 | if (NodeFS.existsSync(this.filePath)) { |
| 76 | fs.renameSync(this.filePath, this.withSuffix(1)); | 76 | NodeFS.renameSync(this.filePath, this.withSuffix(1)); |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | this.currentSize = 0; | 79 | this.currentSize = 0; |
| ... | @@ -87,13 +87,13 @@ export class RotatingFileSink { | ... | @@ -87,13 +87,13 @@ export class RotatingFileSink { |
| 87 | 87 | ||
| 88 | private pruneOverflowBackups(): void { | 88 | private pruneOverflowBackups(): void { |
| 89 | try { | 89 | try { |
| 90 | const dir = path.dirname(this.filePath); | 90 | const dir = NodePath.dirname(this.filePath); |
| 91 | const baseName = path.basename(this.filePath); | 91 | const baseName = NodePath.basename(this.filePath); |
| 92 | for (const entry of fs.readdirSync(dir)) { | 92 | for (const entry of NodeFS.readdirSync(dir)) { |
| 93 | if (!entry.startsWith(`${baseName}.`)) continue; | 93 | if (!entry.startsWith(`${baseName}.`)) continue; |
| 94 | const suffix = Number(entry.slice(baseName.length + 1)); | 94 | const suffix = Number(entry.slice(baseName.length + 1)); |
| 95 | if (!Number.isInteger(suffix) || suffix <= this.maxFiles) continue; | 95 | if (!Number.isInteger(suffix) || suffix <= this.maxFiles) continue; |
| 96 | fs.rmSync(path.join(dir, entry), { force: true }); | 96 | NodeFS.rmSync(NodePath.join(dir, entry), { force: true }); |
| 97 | } | 97 | } |
| 98 | } catch { | 98 | } catch { |
| 99 | if (this.throwOnError) { | 99 | if (this.throwOnError) { |
| ... | @@ -104,7 +104,7 @@ export class RotatingFileSink { | ... | @@ -104,7 +104,7 @@ export class RotatingFileSink { |
| 104 | 104 | ||
| 105 | private readCurrentSize(): number { | 105 | private readCurrentSize(): number { |
| 106 | try { | 106 | try { |
| 107 | return fs.statSync(this.filePath).size; | 107 | return NodeFS.statSync(this.filePath).size; |
| 108 | } catch { | 108 | } catch { |
| 109 | return 0; | 109 | return 0; |
| 110 | } | 110 | } |
packages/shared/src/shell.ts+8-8| ... | @@ -1,8 +1,8 @@ | ... | @@ -1,8 +1,8 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off | 1 | // @effect-diagnostics nodeBuiltinImport:off |
| 2 | import * as NodeOS from "node:os"; | 2 | import * as NodeOS from "node:os"; |
| 3 | import * as NodePath from "node:path"; | 3 | import * as NodePath from "node:path"; |
| 4 | import { execFileSync } from "node:child_process"; | 4 | import * as NodeChildProcess from "node:child_process"; |
| 5 | import { accessSync, constants as fileSystemConstants, statSync } from "node:fs"; | 5 | import * as NodeFS from "node:fs"; |
| 6 | import * as Data from "effect/Data"; | 6 | import * as Data from "effect/Data"; |
| 7 | import * as Effect from "effect/Effect"; | 7 | import * as Effect from "effect/Effect"; |
| 8 | import * as FileSystem from "effect/FileSystem"; | 8 | import * as FileSystem from "effect/FileSystem"; |
| ... | @@ -26,7 +26,7 @@ type ExecFileSyncLike = ( | ... | @@ -26,7 +26,7 @@ type ExecFileSyncLike = ( |
| 26 | 26 | ||
| 27 | function canExecuteFile(filePath: string): boolean { | 27 | function canExecuteFile(filePath: string): boolean { |
| 28 | try { | 28 | try { |
| 29 | accessSync(filePath, fileSystemConstants.X_OK); | 29 | NodeFS.accessSync(filePath, NodeFS.constants.X_OK); |
| 30 | return true; | 30 | return true; |
| 31 | } catch { | 31 | } catch { |
| 32 | return false; | 32 | return false; |
| ... | @@ -108,7 +108,7 @@ function resolveSpawnExecutableWithNode( | ... | @@ -108,7 +108,7 @@ function resolveSpawnExecutableWithNode( |
| 108 | ); | 108 | ); |
| 109 | const isExecutable = (candidate: string) => { | 109 | const isExecutable = (candidate: string) => { |
| 110 | try { | 110 | try { |
| 111 | if (!statSync(candidate).isFile()) return false; | 111 | if (!NodeFS.statSync(candidate).isFile()) return false; |
| 112 | if (platform === "win32") { | 112 | if (platform === "win32") { |
| 113 | return windowsPathExtensions.includes(path.extname(candidate).toUpperCase()); | 113 | return windowsPathExtensions.includes(path.extname(candidate).toUpperCase()); |
| 114 | } | 114 | } |
| ... | @@ -192,13 +192,13 @@ export function extractPathFromShellOutput(output: string): string | null { | ... | @@ -192,13 +192,13 @@ export function extractPathFromShellOutput(output: string): string | null { |
| 192 | 192 | ||
| 193 | export function readPathFromLoginShell( | 193 | export function readPathFromLoginShell( |
| 194 | shell: string, | 194 | shell: string, |
| 195 | execFile: ExecFileSyncLike = execFileSync, | 195 | execFile: ExecFileSyncLike = NodeChildProcess.execFileSync, |
| 196 | ): string | undefined { | 196 | ): string | undefined { |
| 197 | return readEnvironmentFromLoginShell(shell, ["PATH"], execFile).PATH; | 197 | return readEnvironmentFromLoginShell(shell, ["PATH"], execFile).PATH; |
| 198 | } | 198 | } |
| 199 | 199 | ||
| 200 | export function readPathFromLaunchctl( | 200 | export function readPathFromLaunchctl( |
| 201 | execFile: ExecFileSyncLike = execFileSync, | 201 | execFile: ExecFileSyncLike = NodeChildProcess.execFileSync, |
| 202 | ): string | undefined { | 202 | ): string | undefined { |
| 203 | try { | 203 | try { |
| 204 | return trimNonEmpty( | 204 | return trimNonEmpty( |
| ... | @@ -305,7 +305,7 @@ export type ShellEnvironmentReader = ( | ... | @@ -305,7 +305,7 @@ export type ShellEnvironmentReader = ( |
| 305 | export const readEnvironmentFromLoginShell: ShellEnvironmentReader = ( | 305 | export const readEnvironmentFromLoginShell: ShellEnvironmentReader = ( |
| 306 | shell, | 306 | shell, |
| 307 | names, | 307 | names, |
| 308 | execFile = execFileSync, | 308 | execFile = NodeChildProcess.execFileSync, |
| 309 | ) => { | 309 | ) => { |
| 310 | if (names.length === 0) { | 310 | if (names.length === 0) { |
| 311 | return {}; | 311 | return {}; |
| ... | @@ -371,7 +371,7 @@ export function readEnvironmentFromWindowsShell( | ... | @@ -371,7 +371,7 @@ export function readEnvironmentFromWindowsShell( |
| 371 | const execFile: ExecFileSyncLike = | 371 | const execFile: ExecFileSyncLike = |
| 372 | typeof optionsOrExecFile === "function" | 372 | typeof optionsOrExecFile === "function" |
| 373 | ? optionsOrExecFile | 373 | ? optionsOrExecFile |
| 374 | : (maybeExecFile ?? (execFileSync as ExecFileSyncLike)); | 374 | : (maybeExecFile ?? (NodeChildProcess.execFileSync as ExecFileSyncLike)); |
| 375 | const command = buildWindowsEnvironmentCaptureCommand(names); | 375 | const command = buildWindowsEnvironmentCaptureCommand(names); |
| 376 | const args = [ | 376 | const args = [ |
| 377 | "-NoLogo", | 377 | "-NoLogo", |
packages/ssh/src/command.ts+5-2| ... | @@ -1,4 +1,4 @@ | ... | @@ -1,4 +1,4 @@ |
| 1 | import * as Crypto from "node:crypto"; | 1 | import * as NodeCrypto from "node:crypto"; |
| 2 | 2 | ||
| 3 | import type { DesktopSshEnvironmentTarget, DesktopUpdateChannel } from "@t3tools/contracts"; | 3 | import type { DesktopSshEnvironmentTarget, DesktopUpdateChannel } from "@t3tools/contracts"; |
| 4 | import { HostProcessPlatform } from "@t3tools/shared/hostProcess"; | 4 | import { HostProcessPlatform } from "@t3tools/shared/hostProcess"; |
| ... | @@ -74,7 +74,10 @@ export function targetConnectionKey(target: DesktopSshEnvironmentTarget): string | ... | @@ -74,7 +74,10 @@ export function targetConnectionKey(target: DesktopSshEnvironmentTarget): string |
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | export function remoteStateKey(target: DesktopSshEnvironmentTarget): string { | 76 | export function remoteStateKey(target: DesktopSshEnvironmentTarget): string { |
| 77 | return Crypto.createHash("sha256").update(targetConnectionKey(target)).digest("hex").slice(0, 16); | 77 | return NodeCrypto.createHash("sha256") |
| 78 | .update(targetConnectionKey(target)) | ||
| 79 | .digest("hex") | ||
| 80 | .slice(0, 16); | ||
| 78 | } | 81 | } |
| 79 | 82 | ||
| 80 | export function buildSshHostSpec(target: DesktopSshEnvironmentTarget): string { | 83 | export function buildSshHostSpec(target: DesktopSshEnvironmentTarget): string { |
scripts/build-desktop-artifact.ts+2-2| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | #!/usr/bin/env node | 1 | #!/usr/bin/env node |
| 2 | 2 | ||
| 3 | import { createRequire } from "node:module"; | 3 | import * as NodeModule from "node:module"; |
| 4 | 4 | ||
| 5 | import { fromYaml } from "@t3tools/shared/schemaYaml"; | 5 | import { fromYaml } from "@t3tools/shared/schemaYaml"; |
| 6 | import { HostProcessPlatform } from "@t3tools/shared/hostProcess"; | 6 | import { HostProcessPlatform } from "@t3tools/shared/hostProcess"; |
| ... | @@ -482,7 +482,7 @@ const stageClerkPasskeyNativeBinaries = Effect.fn("stageClerkPasskeyNativeBinari | ... | @@ -482,7 +482,7 @@ const stageClerkPasskeyNativeBinaries = Effect.fn("stageClerkPasskeyNativeBinari |
| 482 | path.join(stageAppDir, "node_modules", "@clerk", "electron-passkeys", "index.js"), | 482 | path.join(stageAppDir, "node_modules", "@clerk", "electron-passkeys", "index.js"), |
| 483 | ); | 483 | ); |
| 484 | const packageDir = path.dirname(packageEntryPath); | 484 | const packageDir = path.dirname(packageEntryPath); |
| 485 | const packageRequire = createRequire(packageEntryPath); | 485 | const packageRequire = NodeModule.createRequire(packageEntryPath); |
| 486 | 486 | ||
| 487 | for (const artifact of resolveClerkPasskeyNativeArtifacts(platform, arch)) { | 487 | for (const artifact of resolveClerkPasskeyNativeArtifacts(platform, arch)) { |
| 488 | const sourcePath = yield* Effect.try({ | 488 | const sourcePath = yield* Effect.try({ |
scripts/lib/public-config.test.ts+9-9| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off - Tests exercise root env file precedence directly. | 1 | // @effect-diagnostics nodeBuiltinImport:off - Tests exercise root env file precedence directly. |
| 2 | import { mkdtempSync, rmSync, writeFileSync } from "node:fs"; | 2 | import * as NodeFS from "node:fs"; |
| 3 | import { tmpdir } from "node:os"; | 3 | import * as NodeOS from "node:os"; |
| 4 | import { join } from "node:path"; | 4 | import * as NodePath from "node:path"; |
| 5 | import { afterEach, describe, expect, it } from "vite-plus/test"; | 5 | import { afterEach, describe, expect, it } from "vite-plus/test"; |
| 6 | 6 | ||
| 7 | import { loadRepoEnv, resolvePublicConfig } from "./public-config.ts"; | 7 | import { loadRepoEnv, resolvePublicConfig } from "./public-config.ts"; |
| ... | @@ -10,7 +10,7 @@ const temporaryDirectories: string[] = []; | ... | @@ -10,7 +10,7 @@ const temporaryDirectories: string[] = []; |
| 10 | 10 | ||
| 11 | afterEach(() => { | 11 | afterEach(() => { |
| 12 | for (const directory of temporaryDirectories.splice(0)) { | 12 | for (const directory of temporaryDirectories.splice(0)) { |
| 13 | rmSync(directory, { recursive: true, force: true }); | 13 | NodeFS.rmSync(directory, { recursive: true, force: true }); |
| 14 | } | 14 | } |
| 15 | }); | 15 | }); |
| 16 | 16 | ||
| ... | @@ -43,12 +43,12 @@ describe("loadRepoEnv", () => { | ... | @@ -43,12 +43,12 @@ describe("loadRepoEnv", () => { |
| 43 | 43 | ||
| 44 | it("applies process, root local, and root precedence in that order", () => { | 44 | it("applies process, root local, and root precedence in that order", () => { |
| 45 | const repoRoot = makeTemporaryDirectory(); | 45 | const repoRoot = makeTemporaryDirectory(); |
| 46 | writeFileSync( | 46 | NodeFS.writeFileSync( |
| 47 | join(repoRoot, ".env"), | 47 | NodePath.join(repoRoot, ".env"), |
| 48 | "T3CODE_CLERK_PUBLISHABLE_KEY=pk_root\nT3CODE_CLERK_JWT_TEMPLATE=template_root\nT3CODE_CLERK_CLI_OAUTH_CLIENT_ID=oauth_root\nT3CODE_RELAY_URL=https://root.example.test\n", | 48 | "T3CODE_CLERK_PUBLISHABLE_KEY=pk_root\nT3CODE_CLERK_JWT_TEMPLATE=template_root\nT3CODE_CLERK_CLI_OAUTH_CLIENT_ID=oauth_root\nT3CODE_RELAY_URL=https://root.example.test\n", |
| 49 | ); | 49 | ); |
| 50 | writeFileSync( | 50 | NodeFS.writeFileSync( |
| 51 | join(repoRoot, ".env.local"), | 51 | NodePath.join(repoRoot, ".env.local"), |
| 52 | "T3CODE_CLERK_PUBLISHABLE_KEY=pk_local\nT3CODE_CLERK_JWT_TEMPLATE=template_local\nT3CODE_CLERK_CLI_OAUTH_CLIENT_ID=oauth_local\nT3CODE_RELAY_URL=https://local.example.test\n", | 52 | "T3CODE_CLERK_PUBLISHABLE_KEY=pk_local\nT3CODE_CLERK_JWT_TEMPLATE=template_local\nT3CODE_CLERK_CLI_OAUTH_CLIENT_ID=oauth_local\nT3CODE_RELAY_URL=https://local.example.test\n", |
| 53 | ); | 53 | ); |
| 54 | 54 | ||
| ... | @@ -148,7 +148,7 @@ describe("loadRepoEnv", () => { | ... | @@ -148,7 +148,7 @@ describe("loadRepoEnv", () => { |
| 148 | }); | 148 | }); |
| 149 | 149 | ||
| 150 | function makeTemporaryDirectory() { | 150 | function makeTemporaryDirectory() { |
| 151 | const directory = mkdtempSync(join(tmpdir(), "t3code-public-config-")); | 151 | const directory = NodeFS.mkdtempSync(NodePath.join(NodeOS.tmpdir(), "t3code-public-config-")); |
| 152 | temporaryDirectories.push(directory); | 152 | temporaryDirectories.push(directory); |
| 153 | return directory; | 153 | return directory; |
| 154 | } | 154 | } |
scripts/release-smoke.ts+62-64| ... | @@ -1,21 +1,13 @@ | ... | @@ -1,21 +1,13 @@ |
| 1 | // @effect-diagnostics nodeBuiltinImport:off | 1 | // @effect-diagnostics nodeBuiltinImport:off |
| 2 | import { execFileSync } from "node:child_process"; | 2 | import * as NodeChildProcess from "node:child_process"; |
| 3 | import { | 3 | import * as NodeFS from "node:fs"; |
| 4 | cpSync, | 4 | import * as NodeOS from "node:os"; |
| 5 | existsSync, | 5 | import * as NodePath from "node:path"; |
| 6 | mkdirSync, | 6 | import * as NodeURL from "node:url"; |
| 7 | mkdtempSync, | ||
| 8 | readFileSync, | ||
| 9 | rmSync, | ||
| 10 | writeFileSync, | ||
| 11 | } from "node:fs"; | ||
| 12 | import { tmpdir } from "node:os"; | ||
| 13 | import { dirname, join, resolve } from "node:path"; | ||
| 14 | import { fileURLToPath } from "node:url"; | ||
| 15 | import * as Console from "effect/Console"; | 7 | import * as Console from "effect/Console"; |
| 16 | import * as Effect from "effect/Effect"; | 8 | import * as Effect from "effect/Effect"; |
| 17 | 9 | ||
| 18 | const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), ".."); | 10 | const repoRoot = NodePath.resolve(NodePath.dirname(NodeURL.fileURLToPath(import.meta.url)), ".."); |
| 19 | 11 | ||
| 20 | const workspaceFiles = [ | 12 | const workspaceFiles = [ |
| 21 | "package.json", | 13 | "package.json", |
| ... | @@ -44,26 +36,26 @@ const workspaceFiles = [ | ... | @@ -44,26 +36,26 @@ const workspaceFiles = [ |
| 44 | 36 | ||
| 45 | function copyWorkspaceManifestFixture(targetRoot: string): void { | 37 | function copyWorkspaceManifestFixture(targetRoot: string): void { |
| 46 | for (const relativePath of workspaceFiles) { | 38 | for (const relativePath of workspaceFiles) { |
| 47 | const sourcePath = resolve(repoRoot, relativePath); | 39 | const sourcePath = NodePath.resolve(repoRoot, relativePath); |
| 48 | const destinationPath = resolve(targetRoot, relativePath); | 40 | const destinationPath = NodePath.resolve(targetRoot, relativePath); |
| 49 | mkdirSync(dirname(destinationPath), { recursive: true }); | 41 | NodeFS.mkdirSync(NodePath.dirname(destinationPath), { recursive: true }); |
| 50 | cpSync(sourcePath, destinationPath); | 42 | NodeFS.cpSync(sourcePath, destinationPath); |
| 51 | } | 43 | } |
| 52 | 44 | ||
| 53 | const patchesDirectory = resolve(repoRoot, "patches"); | 45 | const patchesDirectory = NodePath.resolve(repoRoot, "patches"); |
| 54 | if (existsSync(patchesDirectory)) { | 46 | if (NodeFS.existsSync(patchesDirectory)) { |
| 55 | cpSync(patchesDirectory, resolve(targetRoot, "patches"), { recursive: true }); | 47 | NodeFS.cpSync(patchesDirectory, NodePath.resolve(targetRoot, "patches"), { recursive: true }); |
| 56 | } | 48 | } |
| 57 | } | 49 | } |
| 58 | 50 | ||
| 59 | function writeMacManifestFixtures(targetRoot: string): { arm64Path: string; x64Path: string } { | 51 | function writeMacManifestFixtures(targetRoot: string): { arm64Path: string; x64Path: string } { |
| 60 | const assetDirectory = resolve(targetRoot, "release-assets"); | 52 | const assetDirectory = NodePath.resolve(targetRoot, "release-assets"); |
| 61 | mkdirSync(assetDirectory, { recursive: true }); | 53 | NodeFS.mkdirSync(assetDirectory, { recursive: true }); |
| 62 | 54 | ||
| 63 | const arm64Path = resolve(assetDirectory, "latest-mac.yml"); | 55 | const arm64Path = NodePath.resolve(assetDirectory, "latest-mac.yml"); |
| 64 | const x64Path = resolve(assetDirectory, "latest-mac-x64.yml"); | 56 | const x64Path = NodePath.resolve(assetDirectory, "latest-mac-x64.yml"); |
| 65 | 57 | ||
| 66 | writeFileSync( | 58 | NodeFS.writeFileSync( |
| 67 | arm64Path, | 59 | arm64Path, |
| 68 | `version: 9.9.9-smoke.0 | 60 | `version: 9.9.9-smoke.0 |
| 69 | files: | 61 | files: |
| ... | @@ -79,7 +71,7 @@ releaseDate: '2026-03-08T10:32:14.587Z' | ... | @@ -79,7 +71,7 @@ releaseDate: '2026-03-08T10:32:14.587Z' |
| 79 | `, | 71 | `, |
| 80 | ); | 72 | ); |
| 81 | 73 | ||
| 82 | writeFileSync( | 74 | NodeFS.writeFileSync( |
| 83 | x64Path, | 75 | x64Path, |
| 84 | `version: 9.9.9-smoke.0 | 76 | `version: 9.9.9-smoke.0 |
| 85 | files: | 77 | files: |
| ... | @@ -102,13 +94,13 @@ function writeWindowsManifestFixtures( | ... | @@ -102,13 +94,13 @@ function writeWindowsManifestFixtures( |
| 102 | targetRoot: string, | 94 | targetRoot: string, |
| 103 | channel: string, | 95 | channel: string, |
| 104 | ): { arm64Path: string; x64Path: string } { | 96 | ): { arm64Path: string; x64Path: string } { |
| 105 | const assetDirectory = resolve(targetRoot, "release-assets"); | 97 | const assetDirectory = NodePath.resolve(targetRoot, "release-assets"); |
| 106 | mkdirSync(assetDirectory, { recursive: true }); | 98 | NodeFS.mkdirSync(assetDirectory, { recursive: true }); |
| 107 | 99 | ||
| 108 | const arm64Path = resolve(assetDirectory, `${channel}-win-arm64.yml`); | 100 | const arm64Path = NodePath.resolve(assetDirectory, `${channel}-win-arm64.yml`); |
| 109 | const x64Path = resolve(assetDirectory, `${channel}-win-x64.yml`); | 101 | const x64Path = NodePath.resolve(assetDirectory, `${channel}-win-x64.yml`); |
| 110 | 102 | ||
| 111 | writeFileSync( | 103 | NodeFS.writeFileSync( |
| 112 | arm64Path, | 104 | arm64Path, |
| 113 | `version: 9.9.9-smoke.0 | 105 | `version: 9.9.9-smoke.0 |
| 114 | files: | 106 | files: |
| ... | @@ -124,7 +116,7 @@ releaseDate: '2026-03-08T10:32:14.587Z' | ... | @@ -124,7 +116,7 @@ releaseDate: '2026-03-08T10:32:14.587Z' |
| 124 | `, | 116 | `, |
| 125 | ); | 117 | ); |
| 126 | 118 | ||
| 127 | writeFileSync( | 119 | NodeFS.writeFileSync( |
| 128 | x64Path, | 120 | x64Path, |
| 129 | `version: 9.9.9-smoke.0 | 121 | `version: 9.9.9-smoke.0 |
| 130 | files: | 122 | files: |
| ... | @@ -147,11 +139,11 @@ function writeWindowsBuilderDebugFixtures(targetRoot: string): { | ... | @@ -147,11 +139,11 @@ function writeWindowsBuilderDebugFixtures(targetRoot: string): { |
| 147 | arm64Path: string; | 139 | arm64Path: string; |
| 148 | x64Path: string; | 140 | x64Path: string; |
| 149 | } { | 141 | } { |
| 150 | const assetDirectory = resolve(targetRoot, "release-assets"); | 142 | const assetDirectory = NodePath.resolve(targetRoot, "release-assets"); |
| 151 | mkdirSync(assetDirectory, { recursive: true }); | 143 | NodeFS.mkdirSync(assetDirectory, { recursive: true }); |
| 152 | 144 | ||
| 153 | const arm64Path = resolve(assetDirectory, "builder-debug-win-arm64.yml"); | 145 | const arm64Path = NodePath.resolve(assetDirectory, "builder-debug-win-arm64.yml"); |
| 154 | const x64Path = resolve(assetDirectory, "builder-debug-win-x64.yml"); | 146 | const x64Path = NodePath.resolve(assetDirectory, "builder-debug-win-x64.yml"); |
| 155 | const debugFixture = `arm64: | 147 | const debugFixture = `arm64: |
| 156 | firstOrDefaultFilePatterns: | 148 | firstOrDefaultFilePatterns: |
| 157 | - '**/*' | 149 | - '**/*' |
| ... | @@ -160,8 +152,8 @@ nsis: | ... | @@ -160,8 +152,8 @@ nsis: |
| 160 | !include "example.nsh" | 152 | !include "example.nsh" |
| 161 | `; | 153 | `; |
| 162 | 154 | ||
| 163 | writeFileSync(arm64Path, debugFixture); | 155 | NodeFS.writeFileSync(arm64Path, debugFixture); |
| 164 | writeFileSync(x64Path, debugFixture); | 156 | NodeFS.writeFileSync(x64Path, debugFixture); |
| 165 | 157 | ||
| 166 | return { arm64Path, x64Path }; | 158 | return { arm64Path, x64Path }; |
| 167 | } | 159 | } |
| ... | @@ -172,13 +164,13 @@ function assertContains(haystack: string, needle: string, message: string): void | ... | @@ -172,13 +164,13 @@ function assertContains(haystack: string, needle: string, message: string): void |
| 172 | } | 164 | } |
| 173 | 165 | ||
| 174 | function assertExists(path: string, message: string): void { | 166 | function assertExists(path: string, message: string): void { |
| 175 | if (!existsSync(path)) { | 167 | if (!NodeFS.existsSync(path)) { |
| 176 | throw new Error(message); | 168 | throw new Error(message); |
| 177 | } | 169 | } |
| 178 | } | 170 | } |
| 179 | 171 | ||
| 180 | function assertPackageVersion(path: string, version: string): void { | 172 | function assertPackageVersion(path: string, version: string): void { |
| 181 | const packageJson = JSON.parse(readFileSync(path, "utf8")) as { | 173 | const packageJson = JSON.parse(NodeFS.readFileSync(path, "utf8")) as { |
| 182 | readonly version?: unknown; | 174 | readonly version?: unknown; |
| 183 | }; | 175 | }; |
| 184 | 176 | ||
| ... | @@ -188,20 +180,20 @@ function assertPackageVersion(path: string, version: string): void { | ... | @@ -188,20 +180,20 @@ function assertPackageVersion(path: string, version: string): void { |
| 188 | } | 180 | } |
| 189 | 181 | ||
| 190 | function assertMissing(path: string, message: string): void { | 182 | function assertMissing(path: string, message: string): void { |
| 191 | if (existsSync(path)) { | 183 | if (NodeFS.existsSync(path)) { |
| 192 | throw new Error(message); | 184 | throw new Error(message); |
| 193 | } | 185 | } |
| 194 | } | 186 | } |
| 195 | 187 | ||
| 196 | const tempRoot = mkdtempSync(join(tmpdir(), "t3-release-smoke-")); | 188 | const tempRoot = NodeFS.mkdtempSync(NodePath.join(NodeOS.tmpdir(), "t3-release-smoke-")); |
| 197 | 189 | ||
| 198 | try { | 190 | try { |
| 199 | copyWorkspaceManifestFixture(tempRoot); | 191 | copyWorkspaceManifestFixture(tempRoot); |
| 200 | 192 | ||
| 201 | execFileSync( | 193 | NodeChildProcess.execFileSync( |
| 202 | process.execPath, | 194 | process.execPath, |
| 203 | [ | 195 | [ |
| 204 | resolve(repoRoot, "scripts/update-release-package-versions.ts"), | 196 | NodePath.resolve(repoRoot, "scripts/update-release-package-versions.ts"), |
| 205 | "9.9.9-smoke.0", | 197 | "9.9.9-smoke.0", |
| 206 | "--root", | 198 | "--root", |
| 207 | tempRoot, | 199 | tempRoot, |
| ... | @@ -212,14 +204,14 @@ try { | ... | @@ -212,14 +204,14 @@ try { |
| 212 | }, | 204 | }, |
| 213 | ); | 205 | ); |
| 214 | 206 | ||
| 215 | rmSync(resolve(tempRoot, "pnpm-lock.yaml"), { force: true }); | 207 | NodeFS.rmSync(NodePath.resolve(tempRoot, "pnpm-lock.yaml"), { force: true }); |
| 216 | 208 | ||
| 217 | execFileSync("vp", ["install", "--lockfile-only", "--ignore-scripts"], { | 209 | NodeChildProcess.execFileSync("vp", ["install", "--lockfile-only", "--ignore-scripts"], { |
| 218 | cwd: tempRoot, | 210 | cwd: tempRoot, |
| 219 | stdio: "inherit", | 211 | stdio: "inherit", |
| 220 | }); | 212 | }); |
| 221 | 213 | ||
| 222 | const lockfile = readFileSync(resolve(tempRoot, "pnpm-lock.yaml"), "utf8"); | 214 | const lockfile = NodeFS.readFileSync(NodePath.resolve(tempRoot, "pnpm-lock.yaml"), "utf8"); |
| 223 | assertContains(lockfile, "lockfileVersion:", "Expected pnpm-lock.yaml to be regenerated."); | 215 | assertContains(lockfile, "lockfileVersion:", "Expected pnpm-lock.yaml to be regenerated."); |
| 224 | 216 | ||
| 225 | for (const relativePath of [ | 217 | for (const relativePath of [ |
| ... | @@ -228,13 +220,13 @@ try { | ... | @@ -228,13 +220,13 @@ try { |
| 228 | "apps/web/package.json", | 220 | "apps/web/package.json", |
| 229 | "packages/contracts/package.json", | 221 | "packages/contracts/package.json", |
| 230 | ]) { | 222 | ]) { |
| 231 | assertPackageVersion(resolve(tempRoot, relativePath), "9.9.9-smoke.0"); | 223 | assertPackageVersion(NodePath.resolve(tempRoot, relativePath), "9.9.9-smoke.0"); |
| 232 | } | 224 | } |
| 233 | 225 | ||
| 234 | const nightlyReleaseMetadata = execFileSync( | 226 | const nightlyReleaseMetadata = NodeChildProcess.execFileSync( |
| 235 | process.execPath, | 227 | process.execPath, |
| 236 | [ | 228 | [ |
| 237 | resolve(repoRoot, "scripts/resolve-nightly-release.ts"), | 229 | NodePath.resolve(repoRoot, "scripts/resolve-nightly-release.ts"), |
| 238 | "--date", | 230 | "--date", |
| 239 | "20260413", | 231 | "20260413", |
| 240 | "--run-number", | 232 | "--run-number", |
| ... | @@ -266,10 +258,10 @@ try { | ... | @@ -266,10 +258,10 @@ try { |
| 266 | ); | 258 | ); |
| 267 | 259 | ||
| 268 | const { arm64Path, x64Path } = writeMacManifestFixtures(tempRoot); | 260 | const { arm64Path, x64Path } = writeMacManifestFixtures(tempRoot); |
| 269 | execFileSync( | 261 | NodeChildProcess.execFileSync( |
| 270 | process.execPath, | 262 | process.execPath, |
| 271 | [ | 263 | [ |
| 272 | resolve(repoRoot, "scripts/merge-update-manifests.ts"), | 264 | NodePath.resolve(repoRoot, "scripts/merge-update-manifests.ts"), |
| 273 | "--platform", | 265 | "--platform", |
| 274 | "mac", | 266 | "mac", |
| 275 | arm64Path, | 267 | arm64Path, |
| ... | @@ -281,7 +273,7 @@ try { | ... | @@ -281,7 +273,7 @@ try { |
| 281 | }, | 273 | }, |
| 282 | ); | 274 | ); |
| 283 | 275 | ||
| 284 | const mergedManifest = readFileSync(arm64Path, "utf8"); | 276 | const mergedManifest = NodeFS.readFileSync(arm64Path, "utf8"); |
| 285 | assertContains( | 277 | assertContains( |
| 286 | mergedManifest, | 278 | mergedManifest, |
| 287 | "T3-Code-9.9.9-smoke.0-arm64.zip", | 279 | "T3-Code-9.9.9-smoke.0-arm64.zip", |
| ... | @@ -297,21 +289,21 @@ try { | ... | @@ -297,21 +289,21 @@ try { |
| 297 | tempRoot, | 289 | tempRoot, |
| 298 | "latest", | 290 | "latest", |
| 299 | ); | 291 | ); |
| 300 | const mergedWindowsManifestPath = resolve(tempRoot, "release-assets/latest.yml"); | 292 | const mergedWindowsManifestPath = NodePath.resolve(tempRoot, "release-assets/latest.yml"); |
| 301 | const { arm64Path: nightlyWinArm64Path, x64Path: nightlyWinX64Path } = | 293 | const { arm64Path: nightlyWinArm64Path, x64Path: nightlyWinX64Path } = |
| 302 | writeWindowsManifestFixtures(tempRoot, "nightly"); | 294 | writeWindowsManifestFixtures(tempRoot, "nightly"); |
| 303 | const mergedNightlyWindowsManifestPath = resolve(tempRoot, "release-assets/nightly.yml"); | 295 | const mergedNightlyWindowsManifestPath = NodePath.resolve(tempRoot, "release-assets/nightly.yml"); |
| 304 | const { arm64Path: previewWinArm64Path, x64Path: previewWinX64Path } = | 296 | const { arm64Path: previewWinArm64Path, x64Path: previewWinX64Path } = |
| 305 | writeWindowsManifestFixtures(tempRoot, "preview"); | 297 | writeWindowsManifestFixtures(tempRoot, "preview"); |
| 306 | const mergedPreviewWindowsManifestPath = resolve(tempRoot, "release-assets/preview.yml"); | 298 | const mergedPreviewWindowsManifestPath = NodePath.resolve(tempRoot, "release-assets/preview.yml"); |
| 307 | const { arm64Path: winDebugArm64Path, x64Path: winDebugX64Path } = | 299 | const { arm64Path: winDebugArm64Path, x64Path: winDebugX64Path } = |
| 308 | writeWindowsBuilderDebugFixtures(tempRoot); | 300 | writeWindowsBuilderDebugFixtures(tempRoot); |
| 309 | execFileSync( | 301 | NodeChildProcess.execFileSync( |
| 310 | "bash", | 302 | "bash", |
| 311 | [ | 303 | [ |
| 312 | "-lc", | 304 | "-lc", |
| 313 | ` | 305 | ` |
| 314 | release_assets_dir=${JSON.stringify(resolve(tempRoot, "release-assets"))} | 306 | release_assets_dir=${JSON.stringify(NodePath.resolve(tempRoot, "release-assets"))} |
| 315 | shopt -s nullglob | 307 | shopt -s nullglob |
| 316 | found_windows_manifest=false | 308 | found_windows_manifest=false |
| 317 | for x64_manifest in "$release_assets_dir"/*-win-x64.yml; do | 309 | for x64_manifest in "$release_assets_dir"/*-win-x64.yml; do |
| ... | @@ -327,7 +319,7 @@ try { | ... | @@ -327,7 +319,7 @@ try { |
| 327 | fi | 319 | fi |
| 328 | 320 | ||
| 329 | found_windows_manifest=true | 321 | found_windows_manifest=true |
| 330 | ${JSON.stringify(process.execPath)} ${JSON.stringify(resolve(repoRoot, "scripts/merge-update-manifests.ts"))} --platform win \ | 322 | ${JSON.stringify(process.execPath)} ${JSON.stringify(NodePath.resolve(repoRoot, "scripts/merge-update-manifests.ts"))} --platform win \ |
| 331 | "$arm64_manifest" \ | 323 | "$arm64_manifest" \ |
| 332 | "$x64_manifest" \ | 324 | "$x64_manifest" \ |
| 333 | "$output_manifest" | 325 | "$output_manifest" |
| ... | @@ -346,7 +338,7 @@ try { | ... | @@ -346,7 +338,7 @@ try { |
| 346 | }, | 338 | }, |
| 347 | ); | 339 | ); |
| 348 | 340 | ||
| 349 | const mergedWindowsManifest = readFileSync(mergedWindowsManifestPath, "utf8"); | 341 | const mergedWindowsManifest = NodeFS.readFileSync(mergedWindowsManifestPath, "utf8"); |
| 350 | assertContains( | 342 | assertContains( |
| 351 | mergedWindowsManifest, | 343 | mergedWindowsManifest, |
| 352 | "T3-Code-9.9.9-smoke.0-arm64.exe", | 344 | "T3-Code-9.9.9-smoke.0-arm64.exe", |
| ... | @@ -357,7 +349,10 @@ try { | ... | @@ -357,7 +349,10 @@ try { |
| 357 | "T3-Code-9.9.9-smoke.0-x64.exe", | 349 | "T3-Code-9.9.9-smoke.0-x64.exe", |
| 358 | "Merged Windows manifest is missing the x64 asset.", | 350 | "Merged Windows manifest is missing the x64 asset.", |
| 359 | ); | 351 | ); |
| 360 | const mergedNightlyWindowsManifest = readFileSync(mergedNightlyWindowsManifestPath, "utf8"); | 352 | const mergedNightlyWindowsManifest = NodeFS.readFileSync( |
| 353 | mergedNightlyWindowsManifestPath, | ||
| 354 | "utf8", | ||
| 355 | ); | ||
| 361 | assertContains( | 356 | assertContains( |
| 362 | mergedNightlyWindowsManifest, | 357 | mergedNightlyWindowsManifest, |
| 363 | "T3-Code-9.9.9-smoke.0-arm64.exe", | 358 | "T3-Code-9.9.9-smoke.0-arm64.exe", |
| ... | @@ -368,7 +363,10 @@ try { | ... | @@ -368,7 +363,10 @@ try { |
| 368 | "T3-Code-9.9.9-smoke.0-x64.exe", | 363 | "T3-Code-9.9.9-smoke.0-x64.exe", |
| 369 | "Merged nightly Windows manifest is missing the x64 asset.", | 364 | "Merged nightly Windows manifest is missing the x64 asset.", |
| 370 | ); | 365 | ); |
| 371 | const mergedPreviewWindowsManifest = readFileSync(mergedPreviewWindowsManifestPath, "utf8"); | 366 | const mergedPreviewWindowsManifest = NodeFS.readFileSync( |
| 367 | mergedPreviewWindowsManifestPath, | ||
| 368 | "utf8", | ||
| 369 | ); | ||
| 372 | assertContains( | 370 | assertContains( |
| 373 | mergedPreviewWindowsManifest, | 371 | mergedPreviewWindowsManifest, |
| 374 | "T3-Code-9.9.9-smoke.0-arm64.exe", | 372 | "T3-Code-9.9.9-smoke.0-arm64.exe", |
| ... | @@ -411,5 +409,5 @@ try { | ... | @@ -411,5 +409,5 @@ try { |
| 411 | 409 | ||
| 412 | Effect.runSync(Console.log("Release smoke checks passed.")); | 410 | Effect.runSync(Console.log("Release smoke checks passed.")); |
| 413 | } finally { | 411 | } finally { |
| 414 | rmSync(tempRoot, { recursive: true, force: true }); | 412 | NodeFS.rmSync(tempRoot, { recursive: true, force: true }); |
| 415 | } | 413 | } |
vite.config.ts+3-2| ... | @@ -1,11 +1,11 @@ | ... | @@ -1,11 +1,11 @@ |
| 1 | import "vite-plus/test/config"; | 1 | import "vite-plus/test/config"; |
| 2 | import { defineConfig } from "vite-plus"; | 2 | import { defineConfig } from "vite-plus"; |
| 3 | import { fileURLToPath } from "node:url"; | 3 | import * as NodeURL from "node:url"; |
| 4 | 4 | ||
| 5 | export default defineConfig({ | 5 | export default defineConfig({ |
| 6 | resolve: { | 6 | resolve: { |
| 7 | alias: { | 7 | alias: { |
| 8 | "~": fileURLToPath(new URL("./apps/web/src", import.meta.url)), | 8 | "~": NodeURL.fileURLToPath(new URL("./apps/web/src", import.meta.url)), |
| 9 | }, | 9 | }, |
| 10 | }, | 10 | }, |
| 11 | test: { | 11 | test: { |
| ... | @@ -111,6 +111,7 @@ export default defineConfig({ | ... | @@ -111,6 +111,7 @@ export default defineConfig({ |
| 111 | "t3code/no-global-process-runtime": "error", | 111 | "t3code/no-global-process-runtime": "error", |
| 112 | "t3code/no-inline-schema-compile": "warn", | 112 | "t3code/no-inline-schema-compile": "warn", |
| 113 | "t3code/no-manual-effect-runtime-in-tests": "error", | 113 | "t3code/no-manual-effect-runtime-in-tests": "error", |
| 114 | "t3code/namespace-node-imports": "error", | ||
| 114 | }, | 115 | }, |
| 115 | options: { | 116 | options: { |
| 116 | // Revisit once Oxlint's tsgolint path can integrate with @effect/tsgo diagnostics. | 117 | // Revisit once Oxlint's tsgolint path can integrate with @effect/tsgo diagnostics. |