dsh-antigravity-auth 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/LICENSE +21 -0
  3. package/README.md +168 -0
  4. package/README.zh.md +159 -0
  5. package/cordis.patch.yml +12 -0
  6. package/lib/capability-lifecycle--tgGKajs.js +1896 -0
  7. package/lib/client.cjs +2123 -0
  8. package/lib/client.cjs.map +1 -0
  9. package/lib/image.js +564 -0
  10. package/lib/index.js +176 -0
  11. package/lib/invariant.js +2 -0
  12. package/lib/live-gate-runner.js +542 -0
  13. package/lib/live-gates.js +97 -0
  14. package/lib/llm-adapter.js +916 -0
  15. package/lib/media-admission.js +206 -0
  16. package/lib/private-failure-B9vzUkQ7.js +23 -0
  17. package/lib/private-transport-urF138qW.js +641 -0
  18. package/lib/private-transport.js +2 -0
  19. package/lib/project-context.js +133 -0
  20. package/lib/quota.js +283 -0
  21. package/lib/replay.js +156 -0
  22. package/lib/rpc-contract-BFWfdKKs.js +491 -0
  23. package/lib/rpc-contract.js +2 -0
  24. package/lib/safe-text-AlEyN8q_.js +12 -0
  25. package/lib/search.js +259 -0
  26. package/lib/status-D0-em3Ru.js +125 -0
  27. package/lib/types/auth-service.d.ts +64 -0
  28. package/lib/types/auth-service.d.ts.map +1 -0
  29. package/lib/types/auth-store.d.ts +45 -0
  30. package/lib/types/auth-store.d.ts.map +1 -0
  31. package/lib/types/bootstrap-service.d.ts +6 -0
  32. package/lib/types/bootstrap-service.d.ts.map +1 -0
  33. package/lib/types/capability-gates.d.ts +19 -0
  34. package/lib/types/capability-gates.d.ts.map +1 -0
  35. package/lib/types/capability-lifecycle.d.ts +26 -0
  36. package/lib/types/capability-lifecycle.d.ts.map +1 -0
  37. package/lib/types/client/AntigravityAuthSettings.d.ts +19 -0
  38. package/lib/types/client/AntigravityAuthSettings.d.ts.map +1 -0
  39. package/lib/types/client/index.d.ts +18 -0
  40. package/lib/types/client/index.d.ts.map +1 -0
  41. package/lib/types/client/locales.d.ts +121 -0
  42. package/lib/types/client/locales.d.ts.map +1 -0
  43. package/lib/types/client/styles.d.ts +4 -0
  44. package/lib/types/client/styles.d.ts.map +1 -0
  45. package/lib/types/credential-coordinator.d.ts +84 -0
  46. package/lib/types/credential-coordinator.d.ts.map +1 -0
  47. package/lib/types/image.d.ts +39 -0
  48. package/lib/types/image.d.ts.map +1 -0
  49. package/lib/types/index.d.ts +21 -0
  50. package/lib/types/index.d.ts.map +1 -0
  51. package/lib/types/invariant.d.ts +3 -0
  52. package/lib/types/invariant.d.ts.map +1 -0
  53. package/lib/types/live-gate-attachments.d.ts +6 -0
  54. package/lib/types/live-gate-attachments.d.ts.map +1 -0
  55. package/lib/types/live-gate-auth.d.ts +5 -0
  56. package/lib/types/live-gate-auth.d.ts.map +1 -0
  57. package/lib/types/live-gate-image.d.ts +5 -0
  58. package/lib/types/live-gate-image.d.ts.map +1 -0
  59. package/lib/types/live-gate-llm.d.ts +10 -0
  60. package/lib/types/live-gate-llm.d.ts.map +1 -0
  61. package/lib/types/live-gate-outcome.d.ts +8 -0
  62. package/lib/types/live-gate-outcome.d.ts.map +1 -0
  63. package/lib/types/live-gate-runner.d.ts +15 -0
  64. package/lib/types/live-gate-runner.d.ts.map +1 -0
  65. package/lib/types/live-gate-search.d.ts +5 -0
  66. package/lib/types/live-gate-search.d.ts.map +1 -0
  67. package/lib/types/live-gate-video.d.ts +8 -0
  68. package/lib/types/live-gate-video.d.ts.map +1 -0
  69. package/lib/types/live-gates.d.ts +25 -0
  70. package/lib/types/live-gates.d.ts.map +1 -0
  71. package/lib/types/llm-adapter.d.ts +65 -0
  72. package/lib/types/llm-adapter.d.ts.map +1 -0
  73. package/lib/types/login-types.d.ts +36 -0
  74. package/lib/types/login-types.d.ts.map +1 -0
  75. package/lib/types/media-admission.d.ts +54 -0
  76. package/lib/types/media-admission.d.ts.map +1 -0
  77. package/lib/types/model-catalog.d.ts +19 -0
  78. package/lib/types/model-catalog.d.ts.map +1 -0
  79. package/lib/types/oauth-flow.d.ts +87 -0
  80. package/lib/types/oauth-flow.d.ts.map +1 -0
  81. package/lib/types/private-failure.d.ts +6 -0
  82. package/lib/types/private-failure.d.ts.map +1 -0
  83. package/lib/types/private-transport-error.d.ts +13 -0
  84. package/lib/types/private-transport-error.d.ts.map +1 -0
  85. package/lib/types/private-transport.d.ts +48 -0
  86. package/lib/types/private-transport.d.ts.map +1 -0
  87. package/lib/types/project-context.d.ts +30 -0
  88. package/lib/types/project-context.d.ts.map +1 -0
  89. package/lib/types/quota.d.ts +43 -0
  90. package/lib/types/quota.d.ts.map +1 -0
  91. package/lib/types/raw-http.d.ts +11 -0
  92. package/lib/types/raw-http.d.ts.map +1 -0
  93. package/lib/types/replay.d.ts +30 -0
  94. package/lib/types/replay.d.ts.map +1 -0
  95. package/lib/types/rpc-contract.d.ts +33 -0
  96. package/lib/types/rpc-contract.d.ts.map +1 -0
  97. package/lib/types/rpc-vocabulary.d.ts +7 -0
  98. package/lib/types/rpc-vocabulary.d.ts.map +1 -0
  99. package/lib/types/rpc.d.ts +11 -0
  100. package/lib/types/rpc.d.ts.map +1 -0
  101. package/lib/types/safe-text.d.ts +3 -0
  102. package/lib/types/safe-text.d.ts.map +1 -0
  103. package/lib/types/search.d.ts +42 -0
  104. package/lib/types/search.d.ts.map +1 -0
  105. package/lib/types/status.d.ts +62 -0
  106. package/lib/types/status.d.ts.map +1 -0
  107. package/lib/types/video.d.ts +42 -0
  108. package/lib/types/video.d.ts.map +1 -0
  109. package/lib/types/wire-identity.d.ts +49 -0
  110. package/lib/types/wire-identity.d.ts.map +1 -0
  111. package/lib/video.js +320 -0
  112. package/lib/wire-identity.js +162 -0
  113. package/package.json +189 -0
  114. package/scripts/live-gates.mjs +4 -0
@@ -0,0 +1,542 @@
1
+ import { t as isBoundedSafeText } from "./safe-text-AlEyN8q_.js";
2
+ import { _ as defaultAuthStorePath, c as defaultCapabilityGatePath, i as createAntigravityAuthService, o as createFileCapabilityGates } from "./capability-lifecycle--tgGKajs.js";
3
+ import { ANTIGRAVITY_PROVIDER, AntigravityAdapter } from "./llm-adapter.js";
4
+ import { AntigravitySearchProvider } from "./search.js";
5
+ import { ANTIGRAVITY_IMAGE_MODEL, createAntigravityImageTools } from "./image.js";
6
+ import { ANTIGRAVITY_VIDEO_MODEL, createAntigravityVideoTools } from "./video.js";
7
+ import { createHash, randomUUID } from "node:crypto";
8
+ import { chmod, link, lstat, mkdir, readFile, realpath, rm, stat, writeFile } from "node:fs/promises";
9
+ import { dirname, isAbsolute, join, relative, resolve } from "node:path";
10
+ import { Buffer } from "node:buffer";
11
+ import { inflateSync } from "node:zlib";
12
+ //#region src/live-gate-auth.ts
13
+ const AUTH_WAIT_MS = 6e5;
14
+ const POLL_MS = 250;
15
+ async function runAuthGate(auth, output) {
16
+ await auth.acknowledgeRisk();
17
+ const started = await auth.startLogin();
18
+ output(JSON.stringify({
19
+ gate: "A",
20
+ action: "open-authorization",
21
+ authorizationUrl: started.authorizationUrl
22
+ }));
23
+ const deadline = Date.now() + AUTH_WAIT_MS;
24
+ while (Date.now() < deadline) {
25
+ const status = await auth.status();
26
+ if (status.login.phase === "success") return {
27
+ gate: "A",
28
+ outcome: await auth.credential(void 0, { forceRefresh: true }) === void 0 ? "unauthenticated" : "passed"
29
+ };
30
+ if (status.login.phase === "failed" || status.login.phase === "cancelled" || status.login.phase === "expired") return {
31
+ gate: "A",
32
+ outcome: status.login.phase === "cancelled" ? "cancelled" : "failed"
33
+ };
34
+ await new Promise((resolve) => setTimeout(resolve, POLL_MS));
35
+ }
36
+ await auth.cancelLogin();
37
+ return {
38
+ gate: "A",
39
+ outcome: "cancelled"
40
+ };
41
+ }
42
+ //#endregion
43
+ //#region src/live-gate-attachments.ts
44
+ /** Durable, content-addressed AttachmentStore seam used only by explicitly run Gate I. */
45
+ const MAX_LIVE_IMAGE_BYTES = 20971520;
46
+ const MAX_LIVE_IMAGE_DIMENSION = 16384;
47
+ const MAX_LIVE_IMAGE_PIXELS = 16777216;
48
+ const MAX_DECODED_IMAGE_BYTES = 67108864;
49
+ const ID_PREFIX = "live-sha256-";
50
+ const PNG_SIGNATURE = Uint8Array.from([
51
+ 137,
52
+ 80,
53
+ 78,
54
+ 71,
55
+ 13,
56
+ 10,
57
+ 26,
58
+ 10
59
+ ]);
60
+ /** Create a persistent, owner-only PNG store for controlled live image fixtures. */
61
+ function createDurableLiveAttachmentStore(root) {
62
+ const imageLimits = Object.freeze({
63
+ maxImageBytes: MAX_LIVE_IMAGE_BYTES,
64
+ maxImagesPerMessage: 2,
65
+ maxMessageImageBytes: MAX_LIVE_IMAGE_BYTES * 2,
66
+ maxImagePixels: MAX_LIVE_IMAGE_PIXELS,
67
+ maxImageDimension: MAX_LIVE_IMAGE_DIMENSION,
68
+ mediaTypes: Object.freeze(["image/png"])
69
+ });
70
+ const validateImage = async (input) => {
71
+ inspectPng(input);
72
+ };
73
+ const saveImage = async (input) => {
74
+ const dimensions = inspectPng(input);
75
+ await ensureRoot(root);
76
+ const data = Uint8Array.from(input.data);
77
+ const digest = createHash("sha256").update(data).digest("hex");
78
+ const target = join(root, `${digest}.png`);
79
+ const temporary = join(root, `.${digest}.${process.pid}.${randomUUID()}.tmp`);
80
+ try {
81
+ await writeFile(temporary, data, {
82
+ flag: "wx",
83
+ mode: 384
84
+ });
85
+ try {
86
+ await link(temporary, target);
87
+ } catch (error) {
88
+ if (error.code !== "EEXIST") throw error;
89
+ const existing = await readBounded(target);
90
+ if (createHash("sha256").update(existing).digest("hex") !== digest) throw new Error("collision");
91
+ }
92
+ await chmod(target, 384);
93
+ } catch {
94
+ throw admissionError();
95
+ } finally {
96
+ await rm(temporary, { force: true }).catch(() => {});
97
+ }
98
+ return {
99
+ attachmentId: `${ID_PREFIX}${digest}`,
100
+ mediaType: "image/png",
101
+ bytes: data.byteLength,
102
+ width: dimensions.width,
103
+ height: dimensions.height,
104
+ ...input.name === void 0 ? {} : { name: safeName(input.name) }
105
+ };
106
+ };
107
+ const readImage = async (ref, signal) => {
108
+ signal?.throwIfAborted();
109
+ const id = String(ref.attachmentId);
110
+ const digest = id.startsWith(ID_PREFIX) ? id.slice(12) : "";
111
+ if (!/^[a-f0-9]{64}$/u.test(digest) || ref.mediaType !== "image/png") throw admissionError();
112
+ let data;
113
+ try {
114
+ data = await readBounded(join(root, `${digest}.png`));
115
+ } catch {
116
+ throw admissionError();
117
+ }
118
+ signal?.throwIfAborted();
119
+ if (createHash("sha256").update(data).digest("hex") !== digest) throw admissionError();
120
+ const dimensions = inspectPng({
121
+ data,
122
+ mediaType: "image/png"
123
+ });
124
+ if (ref.bytes !== data.byteLength || ref.width !== dimensions.width || ref.height !== dimensions.height) throw admissionError();
125
+ return {
126
+ ref: { ...ref },
127
+ data: Uint8Array.from(data)
128
+ };
129
+ };
130
+ return {
131
+ imageLimits,
132
+ validateImage,
133
+ saveImage,
134
+ saveImages: async (inputs) => {
135
+ for (const input of inputs) await validateImage(input);
136
+ const output = [];
137
+ for (const input of inputs) output.push(await saveImage(input));
138
+ return output;
139
+ },
140
+ readImage
141
+ };
142
+ }
143
+ function inspectPng(input) {
144
+ try {
145
+ return decodePng(input);
146
+ } catch {
147
+ throw admissionError();
148
+ }
149
+ }
150
+ function decodePng(input) {
151
+ const data = input.data;
152
+ if (input.mediaType !== "image/png" || data.byteLength < 57 || data.byteLength > MAX_LIVE_IMAGE_BYTES) throw new Error("invalid PNG");
153
+ for (let index = 0; index < PNG_SIGNATURE.length; index += 1) if (data[index] !== PNG_SIGNATURE[index]) throw new Error("invalid PNG signature");
154
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
155
+ let offset = PNG_SIGNATURE.length;
156
+ let width = 0;
157
+ let height = 0;
158
+ let channels = 0;
159
+ let sawHeader = false;
160
+ let sawData = false;
161
+ let sawEnd = false;
162
+ const compressed = [];
163
+ while (offset < data.byteLength) {
164
+ if (offset + 12 > data.byteLength) throw new Error("truncated PNG chunk");
165
+ const length = view.getUint32(offset);
166
+ const typeOffset = offset + 4;
167
+ const payloadOffset = offset + 8;
168
+ const end = payloadOffset + length;
169
+ if (length > MAX_LIVE_IMAGE_BYTES || end + 4 > data.byteLength) throw new Error("oversized PNG chunk");
170
+ const type = String.fromCharCode(data[typeOffset], data[typeOffset + 1], data[typeOffset + 2], data[typeOffset + 3]);
171
+ if (!/^[A-Za-z]{4}$/u.test(type) || view.getUint32(end) !== crc32(data.subarray(typeOffset, end))) throw new Error("invalid PNG chunk");
172
+ const payload = data.subarray(payloadOffset, end);
173
+ if (!sawHeader && type !== "IHDR") throw new Error("missing PNG header");
174
+ if (type === "IHDR") {
175
+ if (sawHeader || length !== 13) throw new Error("duplicate PNG header");
176
+ width = view.getUint32(payloadOffset);
177
+ height = view.getUint32(payloadOffset + 4);
178
+ const bitDepth = data[payloadOffset + 8];
179
+ const colorType = data[payloadOffset + 9];
180
+ if (bitDepth !== 8 || colorType !== 2 && colorType !== 6 || data[payloadOffset + 10] !== 0 || data[payloadOffset + 11] !== 0 || data[payloadOffset + 12] !== 0) throw new Error("unsupported PNG encoding");
181
+ channels = colorType === 6 ? 4 : 3;
182
+ if (width < 1 || height < 1 || width > MAX_LIVE_IMAGE_DIMENSION || height > MAX_LIVE_IMAGE_DIMENSION || width * height > MAX_LIVE_IMAGE_PIXELS) throw new Error("invalid PNG dimensions");
183
+ sawHeader = true;
184
+ } else if (type === "IDAT") {
185
+ if (!sawHeader || sawEnd || length === 0) throw new Error("invalid PNG data");
186
+ sawData = true;
187
+ compressed.push(payload);
188
+ } else if (type === "IEND") {
189
+ if (!sawData || sawEnd || length !== 0 || end + 4 !== data.byteLength) throw new Error("invalid PNG end");
190
+ sawEnd = true;
191
+ } else if (type[0] === type[0]?.toUpperCase() && type !== "PLTE") throw new Error("unknown critical PNG chunk");
192
+ offset = end + 4;
193
+ }
194
+ if (!sawHeader || !sawData || !sawEnd || offset !== data.byteLength) throw new Error("incomplete PNG");
195
+ const rowBytes = width * channels;
196
+ const decodedBytes = (rowBytes + 1) * height;
197
+ if (!Number.isSafeInteger(decodedBytes) || decodedBytes > MAX_DECODED_IMAGE_BYTES) throw new Error("oversized decoded PNG");
198
+ const decoded = inflateSync(Buffer.concat(compressed.map((part) => Buffer.from(part))), { maxOutputLength: decodedBytes + 1 });
199
+ if (decoded.byteLength !== decodedBytes) throw new Error("invalid decoded PNG length");
200
+ for (let row = 0; row < height; row += 1) if (decoded[row * (rowBytes + 1)] > 4) throw new Error("invalid PNG row filter");
201
+ return {
202
+ width,
203
+ height
204
+ };
205
+ }
206
+ function crc32(data) {
207
+ let crc = 4294967295;
208
+ for (const byte of data) {
209
+ crc ^= byte;
210
+ for (let bit = 0; bit < 8; bit += 1) crc = crc >>> 1 ^ (crc & 1 ? 3988292384 : 0);
211
+ }
212
+ return (crc ^ 4294967295) >>> 0;
213
+ }
214
+ async function ensureRoot(root) {
215
+ try {
216
+ await mkdir(root, {
217
+ recursive: true,
218
+ mode: 448
219
+ });
220
+ const info = await lstat(root);
221
+ if (info.isSymbolicLink() || !info.isDirectory()) throw new Error("unsafe root");
222
+ await chmod(root, 448);
223
+ } catch {
224
+ throw admissionError();
225
+ }
226
+ }
227
+ async function readBounded(path) {
228
+ const info = await lstat(path);
229
+ if (info.isSymbolicLink() || !info.isFile() || info.size < 1 || info.size > MAX_LIVE_IMAGE_BYTES || (info.mode & 63) !== 0) throw admissionError();
230
+ const data = await readFile(path);
231
+ if (data.byteLength !== info.size) throw admissionError();
232
+ return data;
233
+ }
234
+ function safeName(value) {
235
+ const name = value.replaceAll("\\", "/").split("/").at(-1)?.slice(0, 128);
236
+ return name !== void 0 && isBoundedSafeText(name, 128) ? name : "live-gate-output.png";
237
+ }
238
+ function admissionError() {
239
+ return /* @__PURE__ */ new Error("The live image output could not be admitted durably");
240
+ }
241
+ //#endregion
242
+ //#region src/live-gate-image.ts
243
+ async function runImageGate(auth, attachmentRoot) {
244
+ const attachments = createDurableLiveAttachmentStore(attachmentRoot);
245
+ const events = [];
246
+ const context = {
247
+ agent: { session: {
248
+ header: { cwd: process.cwd() },
249
+ events
250
+ } },
251
+ signal: new AbortController().signal
252
+ };
253
+ const tool = createAntigravityImageTools({
254
+ auth,
255
+ attachments,
256
+ fs: createUnavailableFileSystem(),
257
+ settings: () => ({
258
+ enabled: true,
259
+ model: ANTIGRAVITY_IMAGE_MODEL,
260
+ n: 1
261
+ })
262
+ })[0];
263
+ if (tool === void 0) throw new Error("The image gate tool is unavailable");
264
+ const reference = (await tool.execute({
265
+ prompt: "A single small blue circle on a plain white background.",
266
+ n: 1
267
+ }, context)).images[0];
268
+ if (reference === void 0) throw new Error("The image generation gate returned no image");
269
+ events.push({
270
+ type: "tool/result",
271
+ data: { message: { content: [{
272
+ type: "image",
273
+ attachment: reference.attachment
274
+ }] } }
275
+ });
276
+ const edited = await tool.execute({
277
+ prompt: "Keep the image simple and change the blue circle to green.",
278
+ references: [{
279
+ kind: "session",
280
+ handle: reference.handle
281
+ }],
282
+ n: 1
283
+ }, context);
284
+ if (edited.images.length === 0 || edited.references.length !== 1) throw new Error("The image edit gate returned no admitted output");
285
+ await auth.recordCapabilityGate("image", "passed");
286
+ return {
287
+ gate: "I",
288
+ outcome: "passed"
289
+ };
290
+ }
291
+ function createUnavailableFileSystem() {
292
+ const unavailable = async () => {
293
+ throw new Error("Workspace media is unavailable in Gate I");
294
+ };
295
+ return {
296
+ resolve: unavailable,
297
+ contains: () => false,
298
+ readBytes: unavailable,
299
+ lstat: unavailable,
300
+ stat: unavailable
301
+ };
302
+ }
303
+ //#endregion
304
+ //#region src/live-gate-outcome.ts
305
+ const CAPABILITY_BY_GATE = Object.freeze({
306
+ S: "search",
307
+ I: "image",
308
+ V: "video"
309
+ });
310
+ async function recordGateFailure(auth, gate, outcome, family) {
311
+ if (gate === "0L") {
312
+ if (family === void 0) await auth.recordGate0(outcome);
313
+ else await auth.recordLlmFamilyGate(family, outcome);
314
+ return;
315
+ }
316
+ const id = CAPABILITY_BY_GATE[gate];
317
+ if (id !== void 0) await auth.recordCapabilityGate(id, outcome);
318
+ }
319
+ function classifyGate0Outcome(error) {
320
+ const code = errorCode(error);
321
+ if (code === "GATE_0_ATTRIBUTION" || code.includes("ATTRIBUTION_REJECTED")) return "attribution-rejected";
322
+ return classifyOutcome(error);
323
+ }
324
+ function classifyOutcome(error) {
325
+ const code = errorCode(error);
326
+ if (code === "GATE_0_ATTRIBUTION" || code.includes("ATTRIBUTION_REJECTED")) return "attribution-rejected";
327
+ if (code.includes("AUTH") || code.includes("GRANT") || code.includes("LOGIN")) return "unauthenticated";
328
+ if (code.includes("RATE") || code.includes("RESOURCE_EXHAUSTED")) return "rate-limited";
329
+ if (code.includes("CANCEL") || code.includes("ABORT")) return "cancelled";
330
+ if (code.includes("UNSUPPORTED_VIDEO") || code.includes("VIDEO_UNSUPPORTED")) return "unsupported-video";
331
+ if (code.includes("PROTOCOL") || code.includes("MALFORMED") || code.includes("RESPONSE")) return "protocol-drift";
332
+ return "failed";
333
+ }
334
+ function errorCode(error) {
335
+ return typeof error === "object" && error !== null && "code" in error ? String(error.code).toUpperCase() : "";
336
+ }
337
+ //#endregion
338
+ //#region src/live-gate-llm.ts
339
+ const LIVE_TEXT_MODEL = "antigravity-gemini-3.7-flash";
340
+ const LIVE_TEXT_MODEL_BY_FAMILY = Object.freeze({
341
+ gemini: LIVE_TEXT_MODEL,
342
+ claude: "antigravity-claude-sonnet-4-6-thinking",
343
+ "gpt-oss": "antigravity-gpt-oss-120b-medium"
344
+ });
345
+ async function runLlmGate(auth, gates, family, adapter = new AntigravityAdapter({ auth })) {
346
+ if (family === void 0) await gates.clear();
347
+ const model = family === void 0 ? LIVE_TEXT_MODEL : LIVE_TEXT_MODEL_BY_FAMILY[family];
348
+ try {
349
+ const chunks = [];
350
+ for await (const chunk of adapter.stream(minimalGenerateOptions(model))) chunks.push(chunk);
351
+ const finish = chunks.at(-1);
352
+ if (finish?.type !== "finish") throw new Error("The live text gate did not finish normally");
353
+ if (finish.reason.kind === "error" || finish.reason.kind === "aborted") throw Object.assign(/* @__PURE__ */ new Error("The live text gate did not finish normally"), { code: finish.reason.failure.code });
354
+ if (!chunks.some((chunk) => chunk.type === "text-delta" || chunk.type === "reasoning-delta" || chunk.type === "block-end")) throw new Error("The live text gate returned no content");
355
+ } catch (error) {
356
+ const outcome = classifyGate0Outcome(error);
357
+ if (family === void 0) await auth.recordGate0(outcome);
358
+ else await auth.recordLlmFamilyGate(family, outcome);
359
+ return {
360
+ gate: "0L",
361
+ outcome
362
+ };
363
+ }
364
+ if (family === void 0) await auth.recordGate0("passed");
365
+ else await auth.recordLlmFamilyGate(family, "passed");
366
+ return {
367
+ gate: "0L",
368
+ outcome: "passed"
369
+ };
370
+ }
371
+ function minimalGenerateOptions(model) {
372
+ return {
373
+ provider: ANTIGRAVITY_PROVIDER,
374
+ model,
375
+ messages: [{
376
+ id: "antigravity-live-gate-message",
377
+ role: "user",
378
+ source: { kind: "user" },
379
+ content: [{
380
+ type: "text",
381
+ text: "Reply with exactly: OK"
382
+ }]
383
+ }]
384
+ };
385
+ }
386
+ //#endregion
387
+ //#region src/live-gate-search.ts
388
+ async function runSearchGate(auth) {
389
+ if ((await new AntigravitySearchProvider({
390
+ auth,
391
+ settings: () => ({
392
+ enabled: true,
393
+ model: "antigravity-gemini-3.7-flash",
394
+ maxResults: 3
395
+ })
396
+ }).search({
397
+ query: "What is the official Google domain?",
398
+ maxResults: 3
399
+ })).sources.length === 0) throw new Error("The grounded search gate returned no sources");
400
+ await auth.recordCapabilityGate("search", "passed");
401
+ return {
402
+ gate: "S",
403
+ outcome: "passed"
404
+ };
405
+ }
406
+ //#endregion
407
+ //#region src/live-gate-video.ts
408
+ /** Controlled pixel-fact verification for explicit live Gate V. */
409
+ const LIVE_VIDEO_BYTES = 33554432;
410
+ const LIVE_VIDEO_QUESTION = "What exact uppercase word is visibly shown in the center of the video? Reply with that word only.";
411
+ const LIVE_VIDEO_EXPECTED_ANSWER = "KUMQUAT";
412
+ async function runVideoGate(auth, options) {
413
+ if (options.videoFile === void 0) return {
414
+ gate: "V",
415
+ outcome: "failed"
416
+ };
417
+ const absolute = resolve(options.videoFile);
418
+ const workspace = dirname(absolute);
419
+ const path = relative(workspace, absolute);
420
+ const context = {
421
+ agent: { session: {
422
+ header: { cwd: workspace },
423
+ events: []
424
+ } },
425
+ signal: new AbortController().signal
426
+ };
427
+ const tool = createAntigravityVideoTools({
428
+ auth,
429
+ fs: createNodeFileSystem(workspace),
430
+ settings: () => ({
431
+ enabled: true,
432
+ model: ANTIGRAVITY_VIDEO_MODEL,
433
+ maxBytes: LIVE_VIDEO_BYTES
434
+ })
435
+ })[0];
436
+ if (tool === void 0) throw new Error("The video gate tool is unavailable");
437
+ if (!isDeterministicVideoAnswer((await tool.execute({
438
+ path,
439
+ prompt: "What exact uppercase word is visibly shown in the center of the video? Reply with that word only."
440
+ }, context)).text)) throw new Error("The video gate did not verify the fixture pixel fact");
441
+ await auth.recordCapabilityGate("video", "passed");
442
+ return {
443
+ gate: "V",
444
+ outcome: "passed"
445
+ };
446
+ }
447
+ function isDeterministicVideoAnswer(value) {
448
+ return typeof value === "string" && value === "KUMQUAT";
449
+ }
450
+ function createNodeFileSystem(workspace) {
451
+ const target = (path) => ({
452
+ targetKey: path,
453
+ displayPath: path
454
+ });
455
+ const resolveTarget = async (path, options) => {
456
+ const absolute = isAbsolute(path) ? path : join(options?.cwd ?? workspace, path);
457
+ return target(await realpath(absolute));
458
+ };
459
+ const version = (value) => `${String(value.dev)}:${String(value.ino)}:${String(value.size)}:${String(value.mtimeMs)}`;
460
+ return {
461
+ resolve: resolveTarget,
462
+ contains: (parent, child) => {
463
+ const childRelative = relative(String(parent.targetKey), String(child.targetKey));
464
+ return childRelative === "" || !childRelative.startsWith("..") && !isAbsolute(childRelative);
465
+ },
466
+ lstat: async (path, options) => {
467
+ const absolute = isAbsolute(path) ? path : join(options?.cwd ?? workspace, path);
468
+ const info = await lstat(absolute, { bigint: true });
469
+ return {
470
+ type: info.isSymbolicLink() ? "symlink" : info.isFile() ? "file" : info.isDirectory() ? "directory" : "other",
471
+ version: version(info),
472
+ size: Number(info.size)
473
+ };
474
+ },
475
+ stat: async (value) => {
476
+ const info = await stat(String(value.targetKey), { bigint: true });
477
+ return {
478
+ type: info.isFile() ? "file" : info.isDirectory() ? "directory" : "other",
479
+ version: version(info),
480
+ size: Number(info.size)
481
+ };
482
+ },
483
+ readBytes: async (value, signal, maxBytes) => {
484
+ signal?.throwIfAborted();
485
+ if ((await stat(String(value.targetKey))).size > maxBytes) throw new Error("Fixture exceeds gate bound");
486
+ const data = await readFile(String(value.targetKey));
487
+ signal?.throwIfAborted();
488
+ if (data.byteLength > maxBytes) throw new Error("Fixture exceeds gate bound");
489
+ return new Uint8Array(data);
490
+ }
491
+ };
492
+ }
493
+ //#endregion
494
+ //#region src/live-gate-runner.ts
495
+ /** Small production dispatcher for explicitly authorized, one-at-a-time live gates. */
496
+ function createProductionLiveGateRunner(options = {}) {
497
+ const authPath = defaultAuthStorePath();
498
+ const gates = options.gates ?? createFileCapabilityGates(defaultCapabilityGatePath(authPath));
499
+ const auth = options.auth ?? createAntigravityAuthService({
500
+ storePath: authPath,
501
+ gates
502
+ });
503
+ const ownsAuth = options.auth === void 0;
504
+ const output = options.output ?? (() => {});
505
+ const attachmentRoot = options.attachmentRoot ?? join(dirname(authPath), "live-gate-attachments");
506
+ return {
507
+ run: async (gate, runOptions) => {
508
+ try {
509
+ if (gate === "A") return await runAuthGate(auth, output);
510
+ if (gate === "0L") {
511
+ if (runOptions.llmFamily !== void 0 && !await auth.gate0Passed()) return {
512
+ gate,
513
+ outcome: "failed"
514
+ };
515
+ return await runLlmGate(auth, gates, runOptions.llmFamily);
516
+ }
517
+ if (!await auth.gate0Passed()) {
518
+ await recordGateFailure(auth, gate, "failed");
519
+ return {
520
+ gate,
521
+ outcome: "failed"
522
+ };
523
+ }
524
+ if (gate === "S") return await runSearchGate(auth);
525
+ if (gate === "I") return await runImageGate(auth, attachmentRoot);
526
+ return await runVideoGate(auth, runOptions);
527
+ } catch (error) {
528
+ const outcome = gate === "0L" ? classifyGate0Outcome(error) : classifyOutcome(error);
529
+ await recordGateFailure(auth, gate, outcome, runOptions.llmFamily).catch(() => {});
530
+ return {
531
+ gate,
532
+ outcome
533
+ };
534
+ }
535
+ },
536
+ dispose: async () => {
537
+ if (ownsAuth) await auth.dispose();
538
+ }
539
+ };
540
+ }
541
+ //#endregion
542
+ export { LIVE_TEXT_MODEL, LIVE_TEXT_MODEL_BY_FAMILY, LIVE_VIDEO_EXPECTED_ANSWER, LIVE_VIDEO_QUESTION, classifyGate0Outcome, createProductionLiveGateRunner, isDeterministicVideoAnswer, runLlmGate };
@@ -0,0 +1,97 @@
1
+ import { i as LLM_FAMILY_IDS } from "./status-D0-em3Ru.js";
2
+ //#region src/live-gates.ts
3
+ /** Explicit, one-gate-at-a-time CLI boundary for live private endpoint verification. */
4
+ const LIVE_ACKNOWLEDGEMENT = "I_ACKNOWLEDGE_UNOFFICIAL_ANTIGRAVITY_PRIVATE_ENDPOINT_RISK";
5
+ const LIVE_GATE_IDS = [
6
+ "A",
7
+ "0L",
8
+ "S",
9
+ "I",
10
+ "V"
11
+ ];
12
+ /** Parse and enforce opt-in before constructing anything that can read credentials or use the network. */
13
+ async function runLiveGateCli(argv, env = process.env, dependencies = {}) {
14
+ const output = dependencies.output ?? ((line) => {
15
+ process.stdout.write(`${line}\n`);
16
+ });
17
+ const error = dependencies.error ?? ((line) => {
18
+ process.stderr.write(`${line}\n`);
19
+ });
20
+ const parsed = parseArguments(argv);
21
+ if (parsed.error !== void 0) {
22
+ error(parsed.error);
23
+ return 2;
24
+ }
25
+ if (!parsed.acknowledged || env.DSH_ANTIGRAVITY_LIVE_ACK !== "I_ACKNOWLEDGE_UNOFFICIAL_ANTIGRAVITY_PRIVATE_ENDPOINT_RISK") {
26
+ error("Live gates require explicit acknowledgement via both --acknowledge-private-risk and DSH_ANTIGRAVITY_LIVE_ACK.");
27
+ return 2;
28
+ }
29
+ const createRunner = dependencies.createRunner ?? (async () => {
30
+ return (await import("./live-gate-runner.js")).createProductionLiveGateRunner({ output });
31
+ });
32
+ let runner;
33
+ try {
34
+ runner = await createRunner();
35
+ const result = await runner.run(parsed.gate, parsed.options);
36
+ output(JSON.stringify(result));
37
+ return result.outcome === "passed" ? 0 : 1;
38
+ } catch {
39
+ error("The selected Antigravity live gate failed safely.");
40
+ return 1;
41
+ } finally {
42
+ await runner?.dispose().catch(() => {});
43
+ }
44
+ }
45
+ function parseArguments(argv) {
46
+ let acknowledged = false;
47
+ let gate;
48
+ let videoFile;
49
+ let llmFamily;
50
+ for (let index = 0; index < argv.length; index += 1) {
51
+ const value = argv[index];
52
+ if (value === "--acknowledge-private-risk") {
53
+ if (acknowledged) return { error: "The acknowledgement flag may be supplied only once." };
54
+ acknowledged = true;
55
+ continue;
56
+ }
57
+ if (value === "--gate") {
58
+ if (gate !== void 0) return { error: "Select exactly one live gate per invocation." };
59
+ const candidate = argv[index + 1];
60
+ if (candidate === void 0 || !LIVE_GATE_IDS.includes(candidate)) return { error: "Select one live gate: A, 0L, S, I, or V." };
61
+ gate = candidate;
62
+ index += 1;
63
+ continue;
64
+ }
65
+ if (value === "--family") {
66
+ if (llmFamily !== void 0) return { error: "The LLM family may be supplied only once." };
67
+ const candidate = argv[index + 1];
68
+ if (candidate === void 0 || !LLM_FAMILY_IDS.includes(candidate)) return { error: "Select one LLM family: gemini, claude, or gpt-oss." };
69
+ llmFamily = candidate;
70
+ index += 1;
71
+ continue;
72
+ }
73
+ if (value === "--video-file") {
74
+ if (videoFile !== void 0) return { error: "The video fixture may be supplied only once." };
75
+ const candidate = argv[index + 1];
76
+ if (candidate === void 0 || candidate.length === 0 || candidate.length > 4096) return { error: "Gate V requires a bounded video fixture path." };
77
+ videoFile = candidate;
78
+ index += 1;
79
+ continue;
80
+ }
81
+ return { error: "The live gate arguments are invalid." };
82
+ }
83
+ if (gate === void 0) return { error: "Select exactly one live gate per invocation." };
84
+ if (gate === "V" && videoFile === void 0) return { error: "Gate V requires --video-file." };
85
+ if (gate !== "V" && videoFile !== void 0) return { error: "--video-file is valid only for Gate V." };
86
+ if (gate !== "0L" && llmFamily !== void 0) return { error: "--family is valid only for Gate 0/L." };
87
+ return {
88
+ acknowledged,
89
+ gate,
90
+ options: {
91
+ ...videoFile === void 0 ? {} : { videoFile },
92
+ ...llmFamily === void 0 ? {} : { llmFamily }
93
+ }
94
+ };
95
+ }
96
+ //#endregion
97
+ export { LIVE_ACKNOWLEDGEMENT, LIVE_GATE_IDS, runLiveGateCli };