@benjamolina/pi-antigravity-guard 0.4.8 → 0.4.10

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.
package/dist/context.d.ts CHANGED
@@ -26,6 +26,7 @@ export interface GenerationRequest {
26
26
  request: {
27
27
  contents: Content[];
28
28
  systemInstruction?: {
29
+ role?: "user";
29
30
  parts: Part[];
30
31
  };
31
32
  tools?: {
@@ -47,6 +48,8 @@ export interface GenerationRequest {
47
48
  includeThoughts: boolean;
48
49
  };
49
50
  };
51
+ sessionId?: string;
52
+ labels?: Record<string, string>;
50
53
  };
51
54
  requestType: "agent";
52
55
  userAgent: "antigravity";
package/dist/context.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { CLAUDE_CUSTOM_PARAMETERS_PROFILE, getCatalogEntry, resolveGenerationSelection } from "./catalog.js";
2
2
  import { normalizeCustomToolSchema } from "./tool-schema.js";
3
+ import { buildAntigravityEnvelope } from "./envelope.js";
3
4
  import { hasToolContext, prepareToolContext, replayToolHistory } from "./tool-context.js";
4
5
  const MAX_TEXT_BYTES = 8 * 1024 * 1024;
5
6
  const PROVIDER = "antigravity-guard";
@@ -36,6 +37,13 @@ export function serializeContext(input, injectedSelection, onDiagnostics) {
36
37
  } : undefined;
37
38
  const contents = replayToolHistory(isDenseArray(messages), (part, message) => messagePart(part, field(message, "role") === "assistant", sameModel(message)), onDiagnostics, toolReplayPolicy, prepared?.declarations.length ?? 0);
38
39
  const { systemInstruction, generationConfig } = text.request;
40
+ const envelope = buildAntigravityEnvelope({
41
+ wireModelId: selection.route.wireModel,
42
+ family: entry.response.family,
43
+ contentsCount: contents.length,
44
+ messages: isDenseArray(messages),
45
+ injectedRequestId: input.requestId,
46
+ });
39
47
  return { ...text, request: {
40
48
  contents,
41
49
  ...(systemInstruction ? { systemInstruction } : {}),
@@ -47,10 +55,16 @@ export function serializeContext(input, injectedSelection, onDiagnostics) {
47
55
  ? { parameters: normalizeCustomToolSchema(parameters) }
48
56
  : { parametersJsonSchema: parameters }),
49
57
  })) }],
50
- ...(prepared.mode === "NONE" ? { toolConfig: { functionCallingConfig: { mode: "NONE" } } } : {}),
58
+ ...(prepared.mode === "NONE"
59
+ ? { toolConfig: { functionCallingConfig: { mode: "NONE" } } }
60
+ : (entry.response.family === "claude" || entry.response.family === "gpt-oss"
61
+ ? { toolConfig: { functionCallingConfig: { mode: "AUTO" } } }
62
+ : {})),
51
63
  } : {}),
52
64
  generationConfig,
53
- } };
65
+ sessionId: envelope.sessionId,
66
+ labels: envelope.labels,
67
+ }, requestId: envelope.requestId };
54
68
  }
55
69
  export function serializeTextContext(input) {
56
70
  try {
@@ -94,9 +108,16 @@ export function serializeTextContext(input) {
94
108
  }
95
109
  if (!contents.length)
96
110
  fail("A text conversation is required.");
97
- const systemInstruction = systemPrompt === undefined ? undefined : { parts: [{ text: systemPrompt }] };
111
+ const systemInstruction = systemPrompt === undefined ? undefined : { role: "user", parts: [{ text: systemPrompt }] };
98
112
  const temperature = option(options, "temperature");
99
113
  const maxTokens = option(options, "maxTokens");
114
+ const envelope = buildAntigravityEnvelope({
115
+ wireModelId: route.wireModel,
116
+ family: entry.response.family,
117
+ contentsCount: contents.length,
118
+ messages: isDenseArray(field(context, "messages", true)),
119
+ injectedRequestId: requestId,
120
+ });
100
121
  return { project, model: route.wireModel, request: { contents, ...(systemInstruction ? { systemInstruction } : {}), generationConfig: {
101
122
  temperature: typeof temperature === "number" ? temperature : 1,
102
123
  maxOutputTokens: resolveOutputTokens(maxTokens, entry.descriptor.maxTokens, route.thinking),
@@ -104,7 +125,7 @@ export function serializeTextContext(input) {
104
125
  const thinkingConfig = serializeThinkingConfig(route.thinking);
105
126
  return thinkingConfig ? { thinkingConfig } : {};
106
127
  })(),
107
- } }, requestType: "agent", userAgent: "antigravity", requestId };
128
+ }, sessionId: envelope.sessionId, labels: envelope.labels }, requestType: "agent", userAgent: "antigravity", requestId: envelope.requestId };
108
129
  }
109
130
  catch (error) {
110
131
  if (error instanceof ContextSerializationError)
@@ -175,7 +196,8 @@ function messagePart(part, assistant, sameProviderAndModel) {
175
196
  fail("Invalid image data.");
176
197
  const rawMime = field(part, "mimeType") ?? (isRecord(field(part, "source")) ? field(field(part, "source"), "media_type") : undefined);
177
198
  const mimeType = typeof rawMime === "string" && rawMime ? rawMime : "image/jpeg";
178
- return { inlineData: { mimeType, data: rawData } };
199
+ const cleanedData = rawData.replace(/^data:[^;]+;base64,/s, "").trim();
200
+ return { inlineData: { mimeType, data: cleanedData } };
179
201
  }
180
202
  fail("Only text context is supported by this provider.");
181
203
  }
@@ -0,0 +1,20 @@
1
+ export declare const ANTIGRAVITY_MODEL_ENUM: Readonly<Record<string, string>>;
2
+ export declare function stableUuid(seed: string): string;
3
+ export declare function resolveSessionTrajectory(messages?: readonly unknown[]): {
4
+ conversationId: string;
5
+ trajectoryId: string;
6
+ };
7
+ export declare function clearSessionTrajectoryMap(): void;
8
+ export interface AntigravityEnvelope {
9
+ readonly requestId: string;
10
+ readonly sessionId: string;
11
+ readonly labels: Record<string, string>;
12
+ }
13
+ export declare function buildAntigravityEnvelope(options: {
14
+ wireModelId: string;
15
+ family: "gemini" | "claude" | "gpt-oss";
16
+ contentsCount: number;
17
+ messages?: readonly unknown[];
18
+ explicitSessionId?: string;
19
+ injectedRequestId?: string;
20
+ }): AntigravityEnvelope;
@@ -0,0 +1,112 @@
1
+ import { createHash } from "node:crypto";
2
+ export const ANTIGRAVITY_MODEL_ENUM = Object.freeze({
3
+ // Gemini 3.8 Flash
4
+ "gemini-3.8-flash": "MODEL_PLACEHOLDER_M318",
5
+ "gemini-3.8-flash-high": "MODEL_PLACEHOLDER_M318",
6
+ "gemini-3.8-flash-medium": "MODEL_PLACEHOLDER_M319",
7
+ "gemini-3.8-flash-low": "MODEL_PLACEHOLDER_M320",
8
+ "gemini-3.8-flash-tiered": "MODEL_PLACEHOLDER_M322",
9
+ // Gemini 3.7 Flash
10
+ "gemini-3.7-flash": "MODEL_PLACEHOLDER_M298",
11
+ "gemini-3.7-flash-high": "MODEL_PLACEHOLDER_M298",
12
+ "gemini-3.7-flash-medium": "MODEL_PLACEHOLDER_M299",
13
+ "gemini-3.7-flash-low": "MODEL_PLACEHOLDER_M300",
14
+ "gemini-3.7-flash-tiered": "MODEL_PLACEHOLDER_M301",
15
+ // Gemini 3.6 Flash
16
+ "gemini-3.6-flash": "MODEL_PLACEHOLDER_M71",
17
+ "gemini-3.6-flash-high": "MODEL_PLACEHOLDER_M71",
18
+ "gemini-3.6-flash-medium": "MODEL_PLACEHOLDER_M72",
19
+ "gemini-3.6-flash-low": "MODEL_PLACEHOLDER_M73",
20
+ "gemini-3.6-flash-tiered": "MODEL_PLACEHOLDER_M196",
21
+ // Gemini 3.5 Flash
22
+ "gemini-3.5-flash": "MODEL_PLACEHOLDER_M20",
23
+ "gemini-3.5-flash-extra-low": "MODEL_PLACEHOLDER_M187",
24
+ "gemini-3.5-flash-low": "MODEL_PLACEHOLDER_M20",
25
+ "gemini-3-flash-agent": "MODEL_PLACEHOLDER_M84",
26
+ // Gemini 3.1 Pro
27
+ "gemini-3.1-pro": "MODEL_PLACEHOLDER_M36",
28
+ "gemini-3.1-pro-low": "MODEL_PLACEHOLDER_M36",
29
+ "gemini-3.1-pro-high": "MODEL_PLACEHOLDER_M37",
30
+ "gemini-pro-agent": "MODEL_PLACEHOLDER_M16",
31
+ // Claude
32
+ "claude-sonnet-4-6": "MODEL_PLACEHOLDER_M35",
33
+ "claude-opus-4-6": "MODEL_PLACEHOLDER_M26",
34
+ "claude-opus-4-6-thinking": "MODEL_PLACEHOLDER_M26",
35
+ // GPT-OSS
36
+ "gpt-oss-120b": "MODEL_OPENAI_GPT_OSS_120B_MEDIUM",
37
+ "gpt-oss-120b-medium": "MODEL_OPENAI_GPT_OSS_120B_MEDIUM",
38
+ });
39
+ export function stableUuid(seed) {
40
+ const bytes = createHash("sha1").update(seed).digest().subarray(0, 16);
41
+ bytes[6] = (bytes[6] & 0x0f) | 0x50;
42
+ bytes[8] = (bytes[8] & 0x3f) | 0x80;
43
+ const hex = [...bytes].map((b) => b.toString(16).padStart(2, "0")).join("");
44
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
45
+ }
46
+ const sessionTrajectoryMap = new Map();
47
+ export function resolveSessionTrajectory(messages) {
48
+ const firstMsg = Array.isArray(messages) ? messages[0] : undefined;
49
+ if (!isRecord(firstMsg)) {
50
+ return { conversationId: crypto.randomUUID(), trajectoryId: crypto.randomUUID() };
51
+ }
52
+ const role = typeof firstMsg.role === "string" ? firstMsg.role : "user";
53
+ const timestamp = typeof firstMsg.timestamp === "number" ? String(firstMsg.timestamp) : "";
54
+ const rawContent = firstMsg.content;
55
+ const contentSeed = typeof rawContent === "string"
56
+ ? rawContent.slice(0, 64)
57
+ : Array.isArray(rawContent)
58
+ ? JSON.stringify(rawContent[0] ?? "").slice(0, 64)
59
+ : "";
60
+ const seed = `${role}:${timestamp}:${contentSeed}`;
61
+ let entry = sessionTrajectoryMap.get(seed);
62
+ if (!entry) {
63
+ entry = {
64
+ conversationId: stableUuid(`antigravity:conv:${seed}`),
65
+ trajectoryId: stableUuid(`antigravity:traj:${seed}`),
66
+ };
67
+ sessionTrajectoryMap.set(seed, entry);
68
+ if (sessionTrajectoryMap.size > 64) {
69
+ const oldestKey = sessionTrajectoryMap.keys().next().value;
70
+ if (oldestKey !== undefined)
71
+ sessionTrajectoryMap.delete(oldestKey);
72
+ }
73
+ }
74
+ return entry;
75
+ }
76
+ export function clearSessionTrajectoryMap() {
77
+ sessionTrajectoryMap.clear();
78
+ }
79
+ const UUID_AGENT_REGEX = /^agent-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
80
+ export function buildAntigravityEnvelope(options) {
81
+ const isClaude = options.family === "claude";
82
+ const isNonGemini = options.family === "claude" || options.family === "gpt-oss";
83
+ const step = Math.max(1, options.contentsCount);
84
+ const lastStepIndex = String(Math.max(0, step - 1));
85
+ const assistantMsgCount = Array.isArray(options.messages)
86
+ ? options.messages.filter((m) => isRecord(m) && m.role === "assistant" && m.stopReason !== "error" && m.stopReason !== "aborted").length
87
+ : 0;
88
+ const requestIndex = Math.max(0, assistantMsgCount);
89
+ const { conversationId, trajectoryId } = resolveSessionTrajectory(options.messages);
90
+ const sessionHash = createHash("sha1").update(`session:${trajectoryId}`).digest().subarray(0, 8);
91
+ const generatedSessionId = String(new DataView(sessionHash.buffer, sessionHash.byteOffset, 8).getBigInt64(0, true));
92
+ const sessionId = options.explicitSessionId || generatedSessionId;
93
+ const labels = {
94
+ last_step_index: lastStepIndex,
95
+ request_id: `${trajectoryId}-${requestIndex}`,
96
+ trajectory_id: trajectoryId,
97
+ used_claude: isClaude ? "true" : "false",
98
+ used_claude_conservative: isClaude ? "true" : "false",
99
+ used_non_gemini_model: isNonGemini ? "true" : "false",
100
+ };
101
+ const modelEnum = ANTIGRAVITY_MODEL_ENUM[options.wireModelId];
102
+ if (modelEnum) {
103
+ labels.model_enum = modelEnum;
104
+ }
105
+ const requestId = options.injectedRequestId && !UUID_AGENT_REGEX.test(options.injectedRequestId)
106
+ ? options.injectedRequestId
107
+ : `agent/${conversationId}/${trajectoryId}/${step}`;
108
+ return { requestId, sessionId, labels };
109
+ }
110
+ function isRecord(value) {
111
+ return typeof value === "object" && value !== null;
112
+ }
@@ -105,7 +105,8 @@ export function replayToolHistory(messages, serializePart, onDiagnostics, policy
105
105
  if (typeof rawData === "string" && rawData) {
106
106
  const rawMime = value(part, "mimeType") ?? (isRecord(value(part, "source")) ? value(record(value(part, "source")), "media_type") : undefined);
107
107
  const mimeType = typeof rawMime === "string" && rawMime ? rawMime : "image/jpeg";
108
- imageParts.push({ inlineData: { mimeType, data: rawData } });
108
+ const cleanedData = rawData.replace(/^data:[^;]+;base64,/s, "").trim();
109
+ imageParts.push({ inlineData: { mimeType, data: cleanedData } });
109
110
  }
110
111
  }
111
112
  else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@benjamolina/pi-antigravity-guard",
3
- "version": "0.4.8",
3
+ "version": "0.4.10",
4
4
  "description": "Pi adapter for Antigravity Guard",
5
5
  "type": "module",
6
6
  "license": "MIT",