diff --git a/packages/core/src/teleportation/TELEPORTATION.md b/packages/core/src/teleportation/TELEPORTATION.md index 97ab52ca88..a22527c8a8 100644 --- a/packages/core/src/teleportation/TELEPORTATION.md +++ b/packages/core/src/teleportation/TELEPORTATION.md @@ -69,11 +69,27 @@ compatibility. To keep the CLI up to date: -1. Update `trajectory_teleporter.ts` in the Antigravity workspace. -2. Re-bundle using `esbuild` or a similar tool to produce a new - `trajectory_teleporter.min.js`. -3. Copy the new `.min.js` into `packages/core/src/teleportation/`. -4. Rebuild the Gemini CLI. +1. Update `packages/core/src/teleportation/trajectory_teleporter.ts` with any + logic changes. +2. To build a new minified bundle, you must run it from within the Antigravity + `Exafunction` workspace because it depends on the complex Protobuf schema + definitions there + (`exa/proto_ts/dist/exa/gemini_coder/proto/trajectory_pb.js`). +3. If the Protobuf JS definitions haven't been generated in your `Exafunction` + project yet, build them first: + ```bash + pnpm --dir exa/proto_ts build + ``` +4. Inside the `Exafunction` project root, run: + ```bash + pnpm dlx esbuild /path/to/orions-belt/packages/core/src/teleportation/trajectory_teleporter.ts \ + --bundle \ + --minify \ + --format=esm \ + --platform=node \ + --outfile=/path/to/orions-belt/packages/core/src/teleportation/trajectory_teleporter.min.js + ``` +5. Verify the new `trajectory_teleporter.min.js` works locally in the CLI. > [!TIP] In the long term, this logic could be moved to a shared NPM package > published from the Antigravity repository, allowing the Gemini CLI to stay diff --git a/packages/core/src/teleportation/trajectory_teleporter.ts b/packages/core/src/teleportation/trajectory_teleporter.ts new file mode 100644 index 0000000000..48d288b9d9 --- /dev/null +++ b/packages/core/src/teleportation/trajectory_teleporter.ts @@ -0,0 +1,72 @@ +/** + * @license + * Copyright 2026 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-nocheck +import * as crypto from 'node:crypto'; +import { Trajectory } from './exa/proto_ts/dist/exa/gemini_coder/proto/trajectory_pb.js'; + +const DEFAULT_KEY = Buffer.from('safeCodeiumworldKeYsecretBalloon'); +const NONCE_SIZE = 12; // GCM default nonce size +const TAG_SIZE = 16; // GCM default tag size + +/** + * Decrypts data using AES-256-GCM. + * The data is expected to be in the format: [nonce (12b)][ciphertext][tag (16b)] + */ +export function decrypt(data: Buffer, key: Buffer = DEFAULT_KEY): Buffer { + if (data.length < NONCE_SIZE + TAG_SIZE) { + throw new Error('Data too short'); + } + + const nonce = data.subarray(0, NONCE_SIZE); + const tag = data.subarray(data.length - TAG_SIZE); + const ciphertext = data.subarray(NONCE_SIZE, data.length - TAG_SIZE); + + const decipher = crypto.createDecipheriv('aes-256-gcm', key, nonce); + decipher.setAuthTag(tag); + + return Buffer.concat([decipher.update(ciphertext), decipher.final()]); +} + +/** + * Encrypts data using AES-256-GCM. + * Returns data in the format: [nonce (12b)][ciphertext][tag (16b)] + */ +export function encrypt(data: Buffer, key: Buffer = DEFAULT_KEY): Buffer { + const nonce = crypto.randomBytes(NONCE_SIZE); + const cipher = crypto.createCipheriv('aes-256-gcm', key, nonce); + + const ciphertext = Buffer.concat([cipher.update(data), cipher.final()]); + const tag = cipher.getAuthTag(); + + return Buffer.concat([nonce, ciphertext, tag]); +} + +/** + * Converts Antigravity binary trajectory to JSON. + */ +export function trajectoryToJson(data: Buffer): unknown { + let pbData: Buffer; + try { + // Try to decrypt first + pbData = decrypt(data); + } catch (_e) { + // Fallback to plain protobuf if decryption fails + pbData = data; + } + + const trajectory = Trajectory.fromBinary(pbData); + return trajectory.toJson(); +} + +/** + * Converts JSON to Antigravity binary trajectory (encrypted). + */ +export function jsonToTrajectory(json: unknown): Buffer { + const trajectory = Trajectory.fromJson(json, { ignoreUnknownFields: true }); + const pbData = Buffer.from(trajectory.toBinary()); + return encrypt(pbData); +}