/ server / createDirectConnectSession.ts
createDirectConnectSession.ts
 1  /* eslint-disable eslint-plugin-n/no-unsupported-features/node-builtins */
 2  
 3  import { errorMessage } from '../utils/errors.js'
 4  import { jsonStringify } from '../utils/slowOperations.js'
 5  import type { DirectConnectConfig } from './directConnectManager.js'
 6  import { connectResponseSchema } from './types.js'
 7  
 8  /**
 9   * Errors thrown by createDirectConnectSession when the connection fails.
10   */
11  export class DirectConnectError extends Error {
12    constructor(message: string) {
13      super(message)
14      this.name = 'DirectConnectError'
15    }
16  }
17  
18  /**
19   * Create a session on a direct-connect server.
20   *
21   * Posts to `${serverUrl}/sessions`, validates the response, and returns
22   * a DirectConnectConfig ready for use by the REPL or headless runner.
23   *
24   * Throws DirectConnectError on network, HTTP, or response-parsing failures.
25   */
26  export async function createDirectConnectSession({
27    serverUrl,
28    authToken,
29    cwd,
30    dangerouslySkipPermissions,
31  }: {
32    serverUrl: string
33    authToken?: string
34    cwd: string
35    dangerouslySkipPermissions?: boolean
36  }): Promise<{
37    config: DirectConnectConfig
38    workDir?: string
39  }> {
40    const headers: Record<string, string> = {
41      'content-type': 'application/json',
42    }
43    if (authToken) {
44      headers['authorization'] = `Bearer ${authToken}`
45    }
46  
47    let resp: Response
48    try {
49      resp = await fetch(`${serverUrl}/sessions`, {
50        method: 'POST',
51        headers,
52        body: jsonStringify({
53          cwd,
54          ...(dangerouslySkipPermissions && {
55            dangerously_skip_permissions: true,
56          }),
57        }),
58      })
59    } catch (err) {
60      throw new DirectConnectError(
61        `Failed to connect to server at ${serverUrl}: ${errorMessage(err)}`,
62      )
63    }
64  
65    if (!resp.ok) {
66      throw new DirectConnectError(
67        `Failed to create session: ${resp.status} ${resp.statusText}`,
68      )
69    }
70  
71    const result = connectResponseSchema().safeParse(await resp.json())
72    if (!result.success) {
73      throw new DirectConnectError(
74        `Invalid session response: ${result.error.message}`,
75      )
76    }
77  
78    const data = result.data
79    return {
80      config: {
81        serverUrl,
82        sessionId: data.session_id,
83        wsUrl: data.ws_url,
84        authToken,
85      },
86      workDir: data.work_dir,
87    }
88  }