File size: 1,548 Bytes
f0634fb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/**
 * ACP protocol version negotiation.
 *
 * Tracks the (negotiation integer, spec tag, SDK version) tuple per supported
 * protocol revision and picks the highest mutually-supported one when the
 * client initializes.
 */

export interface AcpVersionSpec {
  /** Negotiation integer used in InitializeRequest/Response. */
  readonly protocolVersion: number;
  /** ACP specification tag, e.g. "v0.10.x". */
  readonly specTag: string;
  /** Corresponding npm SDK semver string, e.g. "0.23.0". */
  readonly sdkVersion: string;
}

export const CURRENT_VERSION: AcpVersionSpec = {
  protocolVersion: 1,
  specTag: 'v0.10.x',
  sdkVersion: '0.23.0',
};

const SUPPORTED_VERSIONS: ReadonlyMap<number, AcpVersionSpec> = new Map([
  [1, CURRENT_VERSION],
]);

export const MIN_PROTOCOL_VERSION = 1;

/**
 * Negotiate the protocol version with the client.
 *
 * Returns the highest server-supported version that does not exceed the
 * client's requested version. If the client version is lower than
 * {@link MIN_PROTOCOL_VERSION} the server still returns its own current
 * version so the client can decide whether to disconnect.
 */
export function negotiateVersion(clientProtocolVersion: number): AcpVersionSpec {
  if (clientProtocolVersion < MIN_PROTOCOL_VERSION) {
    return CURRENT_VERSION;
  }

  let best: AcpVersionSpec | undefined;
  for (const [ver, spec] of SUPPORTED_VERSIONS) {
    if (ver <= clientProtocolVersion && (best === undefined || ver > best.protocolVersion)) {
      best = spec;
    }
  }
  return best ?? CURRENT_VERSION;
}