|
|
@@ -28,14 +28,13 @@
|
|
|
* Ideal for local development, testing, or lightweight E2E scenarios.
|
|
|
*/
|
|
|
|
|
|
+import * as fs from "node:fs"
|
|
|
import { mkdtempSync, rmSync } from "node:fs"
|
|
|
import * as os from "node:os"
|
|
|
import { ChildProcess, execSync, spawn } from "child_process"
|
|
|
-import * as fs from "fs"
|
|
|
import * as path from "path"
|
|
|
import { ClineApiServerMock } from "../src/test/e2e/fixtures/server/index"
|
|
|
|
|
|
-// Configuration
|
|
|
const PROTOBUS_PORT = process.env.PROTOBUS_PORT || "26040"
|
|
|
const HOSTBRIDGE_PORT = process.env.HOSTBRIDGE_PORT || "26041"
|
|
|
const WORKSPACE_DIR = process.env.WORKSPACE_DIR || process.cwd()
|
|
|
@@ -48,6 +47,8 @@ const distDir = process.env.CLINE_DIST_DIR || path.join(projectRoot, "dist-stand
|
|
|
const clineCoreFile = process.env.CLINE_CORE_FILE || "cline-core.js"
|
|
|
const coreFile = path.join(distDir, clineCoreFile)
|
|
|
|
|
|
+const childProcesses: ChildProcess[] = []
|
|
|
+
|
|
|
async function main(): Promise<void> {
|
|
|
console.log("Starting Simple Cline gRPC Server...")
|
|
|
console.log(`Workspace: ${WORKSPACE_DIR}`)
|
|
|
@@ -75,30 +76,24 @@ async function main(): Promise<void> {
|
|
|
process.exit(1)
|
|
|
}
|
|
|
|
|
|
- // Fixed extension directory
|
|
|
const extensionsDir = path.join(distDir, "vsce-extension")
|
|
|
-
|
|
|
- // Create temporary directories like e2e tests
|
|
|
const userDataDir = mkdtempSync(path.join(os.tmpdir(), "vsce"))
|
|
|
const clineTestWorkspace = mkdtempSync(path.join(os.tmpdir(), "cline-test-workspace-"))
|
|
|
|
|
|
- // Start hostbridge test server in background.
|
|
|
- // We run it as a child process to emulate how the extension currently operates
|
|
|
console.log("Starting HostBridge test server...")
|
|
|
const hostbridge: ChildProcess = spawn("npx", ["tsx", path.join(__dirname, "test-hostbridge-server.ts")], {
|
|
|
stdio: "pipe",
|
|
|
- detached: false,
|
|
|
env: {
|
|
|
...process.env,
|
|
|
TEST_HOSTBRIDGE_WORKSPACE_DIR: clineTestWorkspace,
|
|
|
HOST_BRIDGE_ADDRESS: `127.0.0.1:${HOSTBRIDGE_PORT}`,
|
|
|
},
|
|
|
})
|
|
|
+ childProcesses.push(hostbridge)
|
|
|
|
|
|
console.log(`Temp user data dir: ${userDataDir}`)
|
|
|
console.log(`Temp extensions dir: ${extensionsDir}`)
|
|
|
-
|
|
|
- // Extract standalone.zip to the extensions directory
|
|
|
+ // Extract standalone.zip if needed
|
|
|
const standaloneZipPath = path.join(distDir, "standalone.zip")
|
|
|
if (!fs.existsSync(standaloneZipPath)) {
|
|
|
console.error(`standalone.zip not found at: ${standaloneZipPath}`)
|
|
|
@@ -116,8 +111,6 @@ async function main(): Promise<void> {
|
|
|
process.exit(1)
|
|
|
}
|
|
|
|
|
|
- // Start the core service
|
|
|
- // We run it as a child process to emulate how the extension currently operates
|
|
|
console.log("Starting Cline Core Service...")
|
|
|
const coreService: ChildProcess = spawn("node", [clineCoreFile], {
|
|
|
cwd: distDir,
|
|
|
@@ -127,28 +120,31 @@ async function main(): Promise<void> {
|
|
|
DEV_WORKSPACE_FOLDER: WORKSPACE_DIR,
|
|
|
PROTOBUS_ADDRESS: `127.0.0.1:${PROTOBUS_PORT}`,
|
|
|
HOST_BRIDGE_ADDRESS: `localhost:${HOSTBRIDGE_PORT}`,
|
|
|
- E2E_TEST: E2E_TEST,
|
|
|
- CLINE_ENVIRONMENT: CLINE_ENVIRONMENT,
|
|
|
+ E2E_TEST,
|
|
|
+ CLINE_ENVIRONMENT,
|
|
|
CLINE_DIR: userDataDir,
|
|
|
INSTALL_DIR: extensionsDir,
|
|
|
},
|
|
|
stdio: "inherit",
|
|
|
})
|
|
|
+ childProcesses.push(coreService)
|
|
|
+
|
|
|
+ const shutdown = async () => {
|
|
|
+ console.log("\nShutting down services...")
|
|
|
+
|
|
|
+ while (childProcesses.length > 0) {
|
|
|
+ const child = childProcesses.pop()
|
|
|
+ if (child && !child.killed) child.kill("SIGINT")
|
|
|
+ }
|
|
|
|
|
|
- // Handle graceful shutdown
|
|
|
- const shutdown = async (): Promise<void> => {
|
|
|
- console.log(`\n Shutting down services...\n${userDataDir}\n${extensionsDir}\n${clineTestWorkspace}\n`)
|
|
|
- hostbridge.kill()
|
|
|
- coreService.kill()
|
|
|
await ClineApiServerMock.stopGlobalServer()
|
|
|
|
|
|
- // Cleanup temp directories
|
|
|
try {
|
|
|
rmSync(userDataDir, { recursive: true, force: true })
|
|
|
rmSync(clineTestWorkspace, { recursive: true, force: true })
|
|
|
console.log("Cleaned up temporary directories")
|
|
|
- } catch (error) {
|
|
|
- console.warn("Failed to cleanup temp directories:", error)
|
|
|
+ } catch (err) {
|
|
|
+ console.warn("Failed to cleanup temp directories:", err)
|
|
|
}
|
|
|
|
|
|
process.exit(0)
|
|
|
@@ -159,24 +155,20 @@ async function main(): Promise<void> {
|
|
|
|
|
|
coreService.on("exit", (code) => {
|
|
|
console.log(`Core service exited with code ${code}`)
|
|
|
- hostbridge.kill()
|
|
|
- process.exit(code || 0)
|
|
|
+ shutdown()
|
|
|
})
|
|
|
-
|
|
|
hostbridge.on("exit", (code) => {
|
|
|
console.log(`HostBridge exited with code ${code}`)
|
|
|
- coreService.kill()
|
|
|
- process.exit(code || 0)
|
|
|
+ shutdown()
|
|
|
})
|
|
|
|
|
|
- console.log("Cline gRPC Server is running!")
|
|
|
- console.log(`Connect to: 127.0.0.1:${PROTOBUS_PORT}`)
|
|
|
+ console.log(`Cline gRPC Server is running on 127.0.0.1:${PROTOBUS_PORT}`)
|
|
|
console.log("Press Ctrl+C to stop")
|
|
|
}
|
|
|
|
|
|
if (require.main === module) {
|
|
|
- main().catch((error) => {
|
|
|
- console.error("Failed to start simple Cline server:", error)
|
|
|
+ main().catch((err) => {
|
|
|
+ console.error("Failed to start simple Cline server:", err)
|
|
|
process.exit(1)
|
|
|
})
|
|
|
}
|