pi-provider-antigravity 0.13.0 → 0.15.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.
- package/README.md +17 -1
- package/dist/index.js +156 -45
- package/dist/index.js.map +2 -2
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@ Use Google Antigravity models directly in [Pi](https://pi.dev).
|
|
|
22
22
|
|
|
23
23
|
## Requirements
|
|
24
24
|
|
|
25
|
-
- Pi >= 0.80.0
|
|
25
|
+
- Pi >= 0.86.0 (For Pi 0.80.0 ~ 0.85.x, see [Legacy Pi Support](#legacy-pi-support))
|
|
26
26
|
- A Google account with Antigravity access
|
|
27
27
|
|
|
28
28
|
## Installation
|
|
@@ -37,6 +37,22 @@ Or try it without installing:
|
|
|
37
37
|
pi -e npm:pi-provider-antigravity
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
+
### Legacy Pi Support
|
|
41
|
+
|
|
42
|
+
We strongly recommend upgrading to Pi >= 0.86.0 to take advantage of the latest SDK capabilities, streaming reliability improvements, and full feature parity.
|
|
43
|
+
|
|
44
|
+
However, if you are unable to upgrade your Pi installation just yet (for environment or workflow reasons), you can pin to the compatible `0.13.0` release for Pi 0.80.0 ~ 0.85.x:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pi install npm:pi-provider-antigravity@0.13.0
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Or try it without installing:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pi -e npm:pi-provider-antigravity@0.13.0
|
|
54
|
+
```
|
|
55
|
+
|
|
40
56
|
## Quick Start
|
|
41
57
|
|
|
42
58
|
1. Authenticate:
|
package/dist/index.js
CHANGED
|
@@ -28,13 +28,15 @@ function resolveToken(auth) {
|
|
|
28
28
|
async function postAntigravityRaw({
|
|
29
29
|
auth,
|
|
30
30
|
path: path2,
|
|
31
|
+
endpoint = DEFAULT_ENDPOINT,
|
|
32
|
+
headers,
|
|
31
33
|
body,
|
|
32
34
|
signal
|
|
33
35
|
}) {
|
|
34
36
|
const token = resolveToken(auth);
|
|
35
|
-
return fetch(`${
|
|
37
|
+
return fetch(`${endpoint}/${path2}`, {
|
|
36
38
|
method: "POST",
|
|
37
|
-
headers: buildAntigravityHeaders(token),
|
|
39
|
+
headers: { ...buildAntigravityHeaders(token), ...headers },
|
|
38
40
|
body: JSON.stringify(body),
|
|
39
41
|
signal
|
|
40
42
|
});
|
|
@@ -56,7 +58,7 @@ async function postAntigravityStream(params) {
|
|
|
56
58
|
if (!res.body) {
|
|
57
59
|
throw new Error(`No response stream received from Antigravity for ${params.path}.`);
|
|
58
60
|
}
|
|
59
|
-
return res.body;
|
|
61
|
+
return { response: res, stream: res.body };
|
|
60
62
|
}
|
|
61
63
|
function buildAntigravityHeaders(token, userAgent = DEFAULT_USER_AGENT) {
|
|
62
64
|
return {
|
|
@@ -122,7 +124,8 @@ async function fetchProjectId(token, signal) {
|
|
|
122
124
|
if (data.cloudaicompanionProject) {
|
|
123
125
|
return data.cloudaicompanionProject;
|
|
124
126
|
}
|
|
125
|
-
} catch {
|
|
127
|
+
} catch (err) {
|
|
128
|
+
if (signal?.aborted) throw err;
|
|
126
129
|
}
|
|
127
130
|
return FALLBACK_PROJECT_ID;
|
|
128
131
|
}
|
|
@@ -142,16 +145,37 @@ async function loginAntigravity(callbacks) {
|
|
|
142
145
|
});
|
|
143
146
|
const authUrl = `${AUTH_URL}?${authParams.toString()}`;
|
|
144
147
|
callbacks.onAuth({ url: authUrl });
|
|
148
|
+
let timer;
|
|
149
|
+
const abortPromise = new Promise((_, rej) => {
|
|
150
|
+
if (callbacks.signal?.aborted) {
|
|
151
|
+
rej(callbacks.signal.reason ?? new Error("Login cancelled"));
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
callbacks.signal?.addEventListener(
|
|
155
|
+
"abort",
|
|
156
|
+
() => rej(callbacks.signal?.reason ?? new Error("Login cancelled")),
|
|
157
|
+
{ once: true }
|
|
158
|
+
);
|
|
159
|
+
});
|
|
145
160
|
const manualPromptPromise = (async () => {
|
|
146
161
|
const input = await callbacks.onPrompt({
|
|
147
162
|
message: "Paste authorization code from browser:"
|
|
148
163
|
});
|
|
149
164
|
return extractCodeFromInput(input);
|
|
150
165
|
})();
|
|
151
|
-
const
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
166
|
+
const timeoutPromise = new Promise((_, rej) => {
|
|
167
|
+
timer = setTimeout(
|
|
168
|
+
() => rej(new Error("Timed out waiting for authorization code (5 minutes)")),
|
|
169
|
+
OAUTH_CALLBACK_TIMEOUT_MS
|
|
170
|
+
);
|
|
171
|
+
});
|
|
172
|
+
let code;
|
|
173
|
+
try {
|
|
174
|
+
code = await Promise.race([manualPromptPromise, timeoutPromise, abortPromise]);
|
|
175
|
+
} finally {
|
|
176
|
+
if (timer) clearTimeout(timer);
|
|
177
|
+
}
|
|
178
|
+
callbacks.onProgress?.("Exchanging authorization code for tokens...");
|
|
155
179
|
const tokenParams = new URLSearchParams({
|
|
156
180
|
client_id: CLIENT_ID,
|
|
157
181
|
client_secret: CLIENT_SECRET,
|
|
@@ -163,14 +187,16 @@ async function loginAntigravity(callbacks) {
|
|
|
163
187
|
const tokenRes = await fetch(TOKEN_URL, {
|
|
164
188
|
method: "POST",
|
|
165
189
|
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
166
|
-
body: tokenParams.toString()
|
|
190
|
+
body: tokenParams.toString(),
|
|
191
|
+
signal: callbacks.signal
|
|
167
192
|
});
|
|
168
193
|
if (!tokenRes.ok) {
|
|
169
194
|
const errText = await tokenRes.text();
|
|
170
195
|
throw new Error(`Failed to exchange token (${tokenRes.status}): ${errText}`);
|
|
171
196
|
}
|
|
172
197
|
const tokens = await tokenRes.json();
|
|
173
|
-
|
|
198
|
+
callbacks.onProgress?.("Resolving Code Assist project ID...");
|
|
199
|
+
const projectId = await fetchProjectId(tokens.access_token, callbacks.signal);
|
|
174
200
|
return {
|
|
175
201
|
refresh: tokens.refresh_token || "",
|
|
176
202
|
access: JSON.stringify({ token: tokens.access_token, projectId }),
|
|
@@ -527,6 +553,7 @@ function synthesizeDynamicModel(baseId, items) {
|
|
|
527
553
|
const isGpt = family === "gpt";
|
|
528
554
|
const defaultContext = isFlash ? 1048576 : isClaude ? 25e4 : isGpt ? 128e3 : 1048576;
|
|
529
555
|
const defaultMaxOutput = isClaude ? 64e3 : isGpt ? 32768 : 65536;
|
|
556
|
+
const promptCache = isClaude ? { short: 300, long: 3600 } : { short: 300 };
|
|
530
557
|
return {
|
|
531
558
|
id: baseId,
|
|
532
559
|
name: formatModelDisplayName(baseId, repItem?.displayName),
|
|
@@ -537,6 +564,7 @@ function synthesizeDynamicModel(baseId, items) {
|
|
|
537
564
|
thinkingLevelMap,
|
|
538
565
|
input: repItem?.supportsImages ? ["text", "image"] : ["text"],
|
|
539
566
|
cost: estimateModelCost(baseId),
|
|
567
|
+
promptCache,
|
|
540
568
|
contextWindow: repItem?.maxTokens || defaultContext,
|
|
541
569
|
maxTokens: repItem?.maxOutputTokens || defaultMaxOutput
|
|
542
570
|
};
|
|
@@ -1384,11 +1412,19 @@ var QuotaStatusCoordinator = class {
|
|
|
1384
1412
|
|
|
1385
1413
|
// src/stream.ts
|
|
1386
1414
|
import {
|
|
1415
|
+
calculateCost,
|
|
1387
1416
|
createAssistantMessageEventStream
|
|
1388
1417
|
} from "@earendil-works/pi-ai";
|
|
1389
1418
|
|
|
1390
1419
|
// src/builder.ts
|
|
1391
1420
|
import { createHash as createHash2, randomUUID } from "node:crypto";
|
|
1421
|
+
import {
|
|
1422
|
+
collapseSystemMessages,
|
|
1423
|
+
getCurrentSystemPrompt,
|
|
1424
|
+
getCurrentTools,
|
|
1425
|
+
normalizeContext,
|
|
1426
|
+
withoutInitialSystemMessage
|
|
1427
|
+
} from "@earendil-works/pi-ai";
|
|
1392
1428
|
var BASE64_SIGNATURE_PATTERN = /^[A-Za-z0-9+/_-]+={0,2}$/;
|
|
1393
1429
|
var SKIP_THOUGHT_SIGNATURE_VALIDATOR = "skip_thought_signature_validator";
|
|
1394
1430
|
function isValidThoughtSignature(sig) {
|
|
@@ -1400,11 +1436,11 @@ function resolveThoughtSignature(isSameProviderAndModel, sig) {
|
|
|
1400
1436
|
if (!isSameProviderAndModel) return void 0;
|
|
1401
1437
|
return isValidThoughtSignature(sig) ? sig : void 0;
|
|
1402
1438
|
}
|
|
1403
|
-
function deriveSessionId(
|
|
1439
|
+
function deriveSessionId(conversation, explicitSessionId) {
|
|
1404
1440
|
if (explicitSessionId && typeof explicitSessionId === "string" && explicitSessionId.trim().length > 0) {
|
|
1405
1441
|
return explicitSessionId.trim();
|
|
1406
1442
|
}
|
|
1407
|
-
const firstMsg =
|
|
1443
|
+
const firstMsg = conversation?.[0];
|
|
1408
1444
|
if (!firstMsg) {
|
|
1409
1445
|
return randomUUID();
|
|
1410
1446
|
}
|
|
@@ -1497,9 +1533,9 @@ function convertTools(tools) {
|
|
|
1497
1533
|
}
|
|
1498
1534
|
];
|
|
1499
1535
|
}
|
|
1500
|
-
function translateTurnTrace(
|
|
1536
|
+
function translateTurnTrace(conversation, runtimeModelId) {
|
|
1501
1537
|
const contents = [];
|
|
1502
|
-
const messages =
|
|
1538
|
+
const messages = conversation || [];
|
|
1503
1539
|
const isGeminiRequest = classifyModelFamily(runtimeModelId) === "gemini";
|
|
1504
1540
|
const isGptRequest = classifyModelFamily(runtimeModelId) === "gpt";
|
|
1505
1541
|
for (const msg of messages) {
|
|
@@ -1690,9 +1726,13 @@ function buildAntigravityRequestBody(params) {
|
|
|
1690
1726
|
maxOutputTokens = 65536
|
|
1691
1727
|
} = params;
|
|
1692
1728
|
const runtimeModelId = plan.runtimeModelId;
|
|
1693
|
-
const
|
|
1729
|
+
const transcript = collapseSystemMessages(context);
|
|
1730
|
+
const systemPrompt = getCurrentSystemPrompt(transcript.messages);
|
|
1731
|
+
const tools = convertTools(getCurrentTools(transcript.messages));
|
|
1732
|
+
const conversation = withoutInitialSystemMessage(transcript.messages);
|
|
1733
|
+
const sessionId = deriveSessionId(conversation, params.sessionId);
|
|
1694
1734
|
const trajectoryId = params.trajectoryId && typeof params.trajectoryId === "string" && params.trajectoryId.trim().length > 0 ? params.trajectoryId.trim() : resolveSessionTrajectory(sessionId);
|
|
1695
|
-
const contents = translateTurnTrace(
|
|
1735
|
+
const contents = translateTurnTrace(conversation, runtimeModelId);
|
|
1696
1736
|
const requestIndex = contents.filter(
|
|
1697
1737
|
(c) => c.role === "model" && !c.parts?.some((p) => p.functionResponse)
|
|
1698
1738
|
).length;
|
|
@@ -1714,13 +1754,12 @@ function buildAntigravityRequestBody(params) {
|
|
|
1714
1754
|
const request = {
|
|
1715
1755
|
contents
|
|
1716
1756
|
};
|
|
1717
|
-
if (
|
|
1757
|
+
if (systemPrompt) {
|
|
1718
1758
|
request.systemInstruction = {
|
|
1719
1759
|
role: "user",
|
|
1720
|
-
parts: [{ text:
|
|
1760
|
+
parts: [{ text: systemPrompt }]
|
|
1721
1761
|
};
|
|
1722
1762
|
}
|
|
1723
|
-
const tools = convertTools(context.tools);
|
|
1724
1763
|
if (tools) {
|
|
1725
1764
|
request.tools = tools;
|
|
1726
1765
|
}
|
|
@@ -1791,7 +1830,14 @@ function processLine(rawLine, state, onEvent) {
|
|
|
1791
1830
|
} catch {
|
|
1792
1831
|
return;
|
|
1793
1832
|
}
|
|
1833
|
+
const streamError = payload?.error ?? payload?.response?.error;
|
|
1834
|
+
if (streamError) {
|
|
1835
|
+
throw new Error(streamError.message ?? JSON.stringify(streamError));
|
|
1836
|
+
}
|
|
1794
1837
|
const response = payload.response || payload;
|
|
1838
|
+
if (response.responseId && !state.responseId) {
|
|
1839
|
+
state.responseId = response.responseId;
|
|
1840
|
+
}
|
|
1795
1841
|
if (response.usageMetadata) {
|
|
1796
1842
|
const um = response.usageMetadata;
|
|
1797
1843
|
const promptTokens = typeof um.promptTokenCount === "number" ? um.promptTokenCount : 0;
|
|
@@ -1808,8 +1854,14 @@ function processLine(rawLine, state, onEvent) {
|
|
|
1808
1854
|
if (!candidate) return;
|
|
1809
1855
|
if (candidate.finishReason === "MAX_TOKENS") {
|
|
1810
1856
|
state.stopReason = "length";
|
|
1811
|
-
|
|
1857
|
+
state.rawStopReason = "MAX_TOKENS";
|
|
1858
|
+
} else if (candidate.finishReason === "STOP") {
|
|
1859
|
+
if (state.stopReason === "pending") {
|
|
1860
|
+
state.stopReason = "stop";
|
|
1861
|
+
}
|
|
1862
|
+
} else if (typeof candidate.finishReason === "string") {
|
|
1812
1863
|
state.stopReason = "error";
|
|
1864
|
+
state.rawStopReason = candidate.finishReason;
|
|
1813
1865
|
}
|
|
1814
1866
|
const parts = candidate.content?.parts || [];
|
|
1815
1867
|
for (const part of parts) {
|
|
@@ -1838,7 +1890,9 @@ function processLine(rawLine, state, onEvent) {
|
|
|
1838
1890
|
});
|
|
1839
1891
|
} else if (part.functionCall) {
|
|
1840
1892
|
closeOpenBlock(state, onEvent);
|
|
1841
|
-
state.stopReason
|
|
1893
|
+
if (state.stopReason === "pending" || state.stopReason === "stop") {
|
|
1894
|
+
state.stopReason = "toolUse";
|
|
1895
|
+
}
|
|
1842
1896
|
const block = {
|
|
1843
1897
|
type: "toolCall",
|
|
1844
1898
|
id: part.functionCall.id || `call_${state.content.length}`,
|
|
@@ -1886,33 +1940,43 @@ function finishStream(state, onEvent) {
|
|
|
1886
1940
|
closeOpenBlock(state, onEvent);
|
|
1887
1941
|
attachLoneSignature(state.content, state.lastThoughtSignature);
|
|
1888
1942
|
}
|
|
1889
|
-
|
|
1943
|
+
var NON_OVERFLOW_PATTERN = /rate limit|too many requests|quota exceeded|resource_exhausted/i;
|
|
1944
|
+
var CONTEXT_OVERFLOW_PATTERN = /(?:(?:input|prompt) token count.*exceeds|prompt (?:is )?too long)/i;
|
|
1945
|
+
function normalizeOverflowError(rawMessage) {
|
|
1946
|
+
if (rawMessage.includes("context_length_exceeded")) return rawMessage;
|
|
1947
|
+
if (!NON_OVERFLOW_PATTERN.test(rawMessage) && CONTEXT_OVERFLOW_PATTERN.test(rawMessage)) {
|
|
1948
|
+
return `context_length_exceeded: ${rawMessage}`;
|
|
1949
|
+
}
|
|
1950
|
+
return rawMessage;
|
|
1951
|
+
}
|
|
1952
|
+
async function consumeAntigravityStream(streamBody, output, stream, model, signal) {
|
|
1890
1953
|
const state = {
|
|
1891
1954
|
content: output.content,
|
|
1892
1955
|
usage: { input: 0, output: 0, cacheRead: 0, reasoning: 0, total: 0 },
|
|
1893
|
-
stopReason: "
|
|
1956
|
+
stopReason: "pending",
|
|
1894
1957
|
openType: null,
|
|
1895
1958
|
buffer: ""
|
|
1896
1959
|
};
|
|
1960
|
+
let lastTotalTokens = -1;
|
|
1897
1961
|
const updateUsageAndCost = () => {
|
|
1898
1962
|
output.usage.input = state.usage.input;
|
|
1899
1963
|
output.usage.cacheRead = state.usage.cacheRead;
|
|
1900
1964
|
output.usage.output = state.usage.output;
|
|
1901
1965
|
output.usage.reasoning = state.usage.reasoning;
|
|
1902
1966
|
output.usage.totalTokens = state.usage.total;
|
|
1903
|
-
if (
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
cacheWrite: 0,
|
|
1912
|
-
total: inputCost + outputCost + cacheCost
|
|
1913
|
-
};
|
|
1967
|
+
if (state.usage.total !== lastTotalTokens) {
|
|
1968
|
+
lastTotalTokens = state.usage.total;
|
|
1969
|
+
if (model.cost) {
|
|
1970
|
+
calculateCost(model, output.usage);
|
|
1971
|
+
}
|
|
1972
|
+
}
|
|
1973
|
+
if (state.responseId) {
|
|
1974
|
+
output.responseId ||= state.responseId;
|
|
1914
1975
|
}
|
|
1915
1976
|
output.stopReason = state.stopReason;
|
|
1977
|
+
if (state.rawStopReason) {
|
|
1978
|
+
output.rawStopReason = state.rawStopReason;
|
|
1979
|
+
}
|
|
1916
1980
|
};
|
|
1917
1981
|
const dispatchEvent = (ev) => {
|
|
1918
1982
|
updateUsageAndCost();
|
|
@@ -1920,13 +1984,20 @@ async function consumeAntigravityStream(streamBody, output, stream, modelCost) {
|
|
|
1920
1984
|
};
|
|
1921
1985
|
const reader = streamBody.getReader();
|
|
1922
1986
|
const decoder = new TextDecoder();
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1987
|
+
try {
|
|
1988
|
+
while (true) {
|
|
1989
|
+
if (signal?.aborted) {
|
|
1990
|
+
throw new Error("Request was aborted");
|
|
1991
|
+
}
|
|
1992
|
+
const { done, value } = await reader.read();
|
|
1993
|
+
if (done) break;
|
|
1994
|
+
feedChunk(decoder.decode(value, { stream: true }), state, dispatchEvent);
|
|
1995
|
+
}
|
|
1996
|
+
finishStream(state, dispatchEvent);
|
|
1997
|
+
updateUsageAndCost();
|
|
1998
|
+
} finally {
|
|
1999
|
+
reader.releaseLock();
|
|
1927
2000
|
}
|
|
1928
|
-
finishStream(state, dispatchEvent);
|
|
1929
|
-
updateUsageAndCost();
|
|
1930
2001
|
}
|
|
1931
2002
|
function streamAntigravity(model, context, options, catalog) {
|
|
1932
2003
|
const stream = createAssistantMessageEventStream();
|
|
@@ -1954,22 +2025,60 @@ function streamAntigravity(model, context, options, catalog) {
|
|
|
1954
2025
|
const effort = options?.reasoning;
|
|
1955
2026
|
const trajectoryId = options && "trajectoryId" in options && typeof options.trajectoryId === "string" ? options.trajectoryId : void 0;
|
|
1956
2027
|
const plan = catalog.resolvePlan(model.id, effort);
|
|
1957
|
-
|
|
2028
|
+
let requestBody = buildAntigravityRequestBody({
|
|
1958
2029
|
projectId,
|
|
1959
2030
|
plan,
|
|
1960
2031
|
context,
|
|
1961
2032
|
sessionId: options?.sessionId,
|
|
1962
2033
|
trajectoryId,
|
|
1963
|
-
maxOutputTokens: model.maxTokens,
|
|
2034
|
+
maxOutputTokens: options?.maxTokens ?? model.maxTokens,
|
|
1964
2035
|
toolChoice: options?.toolChoice
|
|
1965
2036
|
});
|
|
1966
|
-
|
|
2037
|
+
if (options?.onPayload) {
|
|
2038
|
+
const replacement = await options.onPayload(requestBody, model);
|
|
2039
|
+
if (replacement !== void 0) {
|
|
2040
|
+
requestBody = replacement;
|
|
2041
|
+
}
|
|
2042
|
+
}
|
|
2043
|
+
const endpoint = model.baseUrl || DEFAULT_ENDPOINT;
|
|
2044
|
+
const mergedHeaders = {};
|
|
2045
|
+
if (model.headers) {
|
|
2046
|
+
for (const [k, v] of Object.entries(model.headers)) {
|
|
2047
|
+
if (typeof v === "string") mergedHeaders[k] = v;
|
|
2048
|
+
}
|
|
2049
|
+
}
|
|
2050
|
+
if (options?.headers) {
|
|
2051
|
+
for (const [k, v] of Object.entries(options.headers)) {
|
|
2052
|
+
if (typeof v === "string") mergedHeaders[k] = v;
|
|
2053
|
+
}
|
|
2054
|
+
}
|
|
2055
|
+
const { response, stream: streamBody } = await postAntigravityStream({
|
|
1967
2056
|
auth: token,
|
|
2057
|
+
endpoint,
|
|
1968
2058
|
path: "v1internal:streamGenerateContent?alt=sse",
|
|
2059
|
+
headers: mergedHeaders,
|
|
1969
2060
|
body: requestBody,
|
|
1970
2061
|
signal: options?.signal
|
|
1971
2062
|
});
|
|
1972
|
-
|
|
2063
|
+
if (options?.onResponse) {
|
|
2064
|
+
const resHeaders = {};
|
|
2065
|
+
response.headers.forEach((val, key) => {
|
|
2066
|
+
resHeaders[key] = val;
|
|
2067
|
+
});
|
|
2068
|
+
await options.onResponse({ status: response.status, headers: resHeaders }, model);
|
|
2069
|
+
}
|
|
2070
|
+
await consumeAntigravityStream(streamBody, output, stream, model, options?.signal);
|
|
2071
|
+
if (options?.signal?.aborted) {
|
|
2072
|
+
throw new Error("Request was aborted");
|
|
2073
|
+
}
|
|
2074
|
+
if (output.stopReason === "pending") {
|
|
2075
|
+
throw new Error("Provider stream ended without a stop reason");
|
|
2076
|
+
}
|
|
2077
|
+
if (output.stopReason === "error" || output.stopReason === "aborted") {
|
|
2078
|
+
throw new Error(
|
|
2079
|
+
output.rawStopReason ? `Provider stopped with: ${output.rawStopReason}` : output.errorMessage || "An unknown error occurred"
|
|
2080
|
+
);
|
|
2081
|
+
}
|
|
1973
2082
|
const doneReason = output.stopReason === "toolUse" || output.stopReason === "length" ? output.stopReason : "stop";
|
|
1974
2083
|
stream.push({
|
|
1975
2084
|
type: "done",
|
|
@@ -1979,7 +2088,8 @@ function streamAntigravity(model, context, options, catalog) {
|
|
|
1979
2088
|
stream.end();
|
|
1980
2089
|
} catch (error) {
|
|
1981
2090
|
output.stopReason = options?.signal?.aborted ? "aborted" : "error";
|
|
1982
|
-
|
|
2091
|
+
const rawMessage = error instanceof Error ? error.message : String(error);
|
|
2092
|
+
output.errorMessage = normalizeOverflowError(rawMessage);
|
|
1983
2093
|
stream.push({ type: "error", reason: output.stopReason, error: output });
|
|
1984
2094
|
stream.end();
|
|
1985
2095
|
}
|
|
@@ -2277,6 +2387,7 @@ function index_default(pi) {
|
|
|
2277
2387
|
// Purely dynamic provider per Pi SDK architecture
|
|
2278
2388
|
oauth: {
|
|
2279
2389
|
name: PROVIDER_NAME,
|
|
2390
|
+
isSubscription: true,
|
|
2280
2391
|
login: loginAntigravity,
|
|
2281
2392
|
refreshToken: refreshAntigravityToken,
|
|
2282
2393
|
getApiKey
|