@anthonyhaussman/opencode-agy-auth 1.0.11-alpha.5 → 1.0.11-beta.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 +0 -27
- package/dist/index.d.ts +1 -6
- package/dist/index.js +939 -1313
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1285,1152 +1285,6 @@ function getLatestSignature(sessionId) {
|
|
|
1285
1285
|
return void 0;
|
|
1286
1286
|
}
|
|
1287
1287
|
|
|
1288
|
-
// src/sdk/request/turn-state-tracker.ts
|
|
1289
|
-
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2, renameSync as renameSync2, unlinkSync as unlinkSync2 } from "fs";
|
|
1290
|
-
import { join as join2, dirname as dirname2 } from "path";
|
|
1291
|
-
import { homedir as homedir2, tmpdir as tmpdir2 } from "os";
|
|
1292
|
-
|
|
1293
|
-
// src/sdk/request/thinking.ts
|
|
1294
|
-
import { createHash as createHash2 } from "crypto";
|
|
1295
|
-
function createSignatureStore() {
|
|
1296
|
-
const store = /* @__PURE__ */ new Map();
|
|
1297
|
-
return {
|
|
1298
|
-
get: (key) => store.get(key),
|
|
1299
|
-
set: (key, value) => {
|
|
1300
|
-
store.set(key, value);
|
|
1301
|
-
},
|
|
1302
|
-
has: (key) => store.has(key),
|
|
1303
|
-
delete: (key) => {
|
|
1304
|
-
store.delete(key);
|
|
1305
|
-
}
|
|
1306
|
-
};
|
|
1307
|
-
}
|
|
1308
|
-
function createThoughtBuffer() {
|
|
1309
|
-
const buffer = /* @__PURE__ */ new Map();
|
|
1310
|
-
return {
|
|
1311
|
-
get: (index) => buffer.get(index),
|
|
1312
|
-
set: (index, text) => {
|
|
1313
|
-
buffer.set(index, text);
|
|
1314
|
-
},
|
|
1315
|
-
clear: () => buffer.clear()
|
|
1316
|
-
};
|
|
1317
|
-
}
|
|
1318
|
-
var defaultSignatureStore = createSignatureStore();
|
|
1319
|
-
var THINKING_HASH_HEX_LEN = 16;
|
|
1320
|
-
function hashString(str) {
|
|
1321
|
-
return createHash2("sha256").update(str, "utf8").digest("hex").slice(0, THINKING_HASH_HEX_LEN);
|
|
1322
|
-
}
|
|
1323
|
-
function isThinkingPart(part) {
|
|
1324
|
-
if (!part || typeof part !== "object") return false;
|
|
1325
|
-
return part.thought === true || part.type === "thinking" || part.type === "redacted_thinking";
|
|
1326
|
-
}
|
|
1327
|
-
function isFunctionResponsePart(part) {
|
|
1328
|
-
return part && typeof part === "object" && "functionResponse" in part;
|
|
1329
|
-
}
|
|
1330
|
-
function isFunctionCallPart(part) {
|
|
1331
|
-
return part && typeof part === "object" && "functionCall" in part;
|
|
1332
|
-
}
|
|
1333
|
-
function isToolResultMessage(msg) {
|
|
1334
|
-
if (!msg || msg.role !== "user") return false;
|
|
1335
|
-
const parts = msg.parts || [];
|
|
1336
|
-
return parts.some(isFunctionResponsePart);
|
|
1337
|
-
}
|
|
1338
|
-
function messageHasThinking(msg) {
|
|
1339
|
-
if (!msg || typeof msg !== "object") return false;
|
|
1340
|
-
if (Array.isArray(msg.parts)) {
|
|
1341
|
-
return msg.parts.some(isThinkingPart);
|
|
1342
|
-
}
|
|
1343
|
-
if (Array.isArray(msg.content)) {
|
|
1344
|
-
return msg.content.some(
|
|
1345
|
-
(block) => block?.type === "thinking" || block?.type === "redacted_thinking"
|
|
1346
|
-
);
|
|
1347
|
-
}
|
|
1348
|
-
return false;
|
|
1349
|
-
}
|
|
1350
|
-
function messageHasToolCalls(msg) {
|
|
1351
|
-
if (!msg || typeof msg !== "object") return false;
|
|
1352
|
-
if (Array.isArray(msg.parts)) {
|
|
1353
|
-
return msg.parts.some(isFunctionCallPart);
|
|
1354
|
-
}
|
|
1355
|
-
if (Array.isArray(msg.content)) {
|
|
1356
|
-
return msg.content.some((block) => block?.type === "tool_use");
|
|
1357
|
-
}
|
|
1358
|
-
return false;
|
|
1359
|
-
}
|
|
1360
|
-
function analyzeConversationState(contents) {
|
|
1361
|
-
const state = {
|
|
1362
|
-
inToolLoop: false,
|
|
1363
|
-
turnStartIdx: -1,
|
|
1364
|
-
turnHasThinking: false,
|
|
1365
|
-
lastModelIdx: -1,
|
|
1366
|
-
lastModelHasThinking: false,
|
|
1367
|
-
lastModelHasToolCalls: false
|
|
1368
|
-
};
|
|
1369
|
-
if (!Array.isArray(contents) || contents.length === 0) {
|
|
1370
|
-
return state;
|
|
1371
|
-
}
|
|
1372
|
-
let lastRealUserIdx = -1;
|
|
1373
|
-
for (let i = 0; i < contents.length; i++) {
|
|
1374
|
-
const msg = contents[i];
|
|
1375
|
-
if (msg?.role === "user" && !isToolResultMessage(msg)) {
|
|
1376
|
-
lastRealUserIdx = i;
|
|
1377
|
-
}
|
|
1378
|
-
}
|
|
1379
|
-
for (let i = 0; i < contents.length; i++) {
|
|
1380
|
-
const msg = contents[i];
|
|
1381
|
-
const role = msg?.role;
|
|
1382
|
-
if (role === "model" || role === "assistant") {
|
|
1383
|
-
const hasThinking = messageHasThinking(msg);
|
|
1384
|
-
const hasToolCalls = messageHasToolCalls(msg);
|
|
1385
|
-
if (i > lastRealUserIdx && state.turnStartIdx === -1) {
|
|
1386
|
-
state.turnStartIdx = i;
|
|
1387
|
-
state.turnHasThinking = hasThinking;
|
|
1388
|
-
}
|
|
1389
|
-
state.lastModelIdx = i;
|
|
1390
|
-
state.lastModelHasToolCalls = hasToolCalls;
|
|
1391
|
-
state.lastModelHasThinking = hasThinking;
|
|
1392
|
-
}
|
|
1393
|
-
}
|
|
1394
|
-
if (contents.length > 0) {
|
|
1395
|
-
const lastMsg = contents[contents.length - 1];
|
|
1396
|
-
if (lastMsg?.role === "user" && isToolResultMessage(lastMsg)) {
|
|
1397
|
-
state.inToolLoop = true;
|
|
1398
|
-
}
|
|
1399
|
-
}
|
|
1400
|
-
return state;
|
|
1401
|
-
}
|
|
1402
|
-
function countTrailingToolResults(contents) {
|
|
1403
|
-
let count = 0;
|
|
1404
|
-
for (let i = contents.length - 1; i >= 0; i--) {
|
|
1405
|
-
const msg = contents[i];
|
|
1406
|
-
if (msg?.role === "user") {
|
|
1407
|
-
const parts = msg.parts || [];
|
|
1408
|
-
const functionResponses = parts.filter(isFunctionResponsePart);
|
|
1409
|
-
if (functionResponses.length > 0) {
|
|
1410
|
-
count += functionResponses.length;
|
|
1411
|
-
} else {
|
|
1412
|
-
break;
|
|
1413
|
-
}
|
|
1414
|
-
} else if (msg?.role === "model" || msg?.role === "assistant") {
|
|
1415
|
-
break;
|
|
1416
|
-
}
|
|
1417
|
-
}
|
|
1418
|
-
return count;
|
|
1419
|
-
}
|
|
1420
|
-
function closeToolLoopForThinking(contents) {
|
|
1421
|
-
const strippedContents = contents;
|
|
1422
|
-
const toolResultCount = countTrailingToolResults(strippedContents);
|
|
1423
|
-
let syntheticModelContent;
|
|
1424
|
-
if (toolResultCount === 0) {
|
|
1425
|
-
syntheticModelContent = "[Processing prev ctx.]";
|
|
1426
|
-
} else if (toolResultCount === 1) {
|
|
1427
|
-
syntheticModelContent = "[Tool exec completed.]";
|
|
1428
|
-
} else {
|
|
1429
|
-
syntheticModelContent = `[${toolResultCount} tool executions completed.]`;
|
|
1430
|
-
}
|
|
1431
|
-
const syntheticModel = {
|
|
1432
|
-
role: "model",
|
|
1433
|
-
parts: [{ text: syntheticModelContent }]
|
|
1434
|
-
};
|
|
1435
|
-
const syntheticUser = {
|
|
1436
|
-
role: "user",
|
|
1437
|
-
parts: [{ text: "[Continue]" }]
|
|
1438
|
-
};
|
|
1439
|
-
return [...strippedContents, syntheticModel, syntheticUser];
|
|
1440
|
-
}
|
|
1441
|
-
function deduplicateThinkingText(response, sentBuffer, displayedThinkingHashes) {
|
|
1442
|
-
if (!response || typeof response !== "object") return response;
|
|
1443
|
-
const resp = response;
|
|
1444
|
-
if (Array.isArray(resp.candidates)) {
|
|
1445
|
-
const newCandidates = resp.candidates.map((candidate, index) => {
|
|
1446
|
-
const cand = candidate;
|
|
1447
|
-
if (!cand?.content) return candidate;
|
|
1448
|
-
const content = cand.content;
|
|
1449
|
-
if (!Array.isArray(content.parts)) return candidate;
|
|
1450
|
-
const newParts = content.parts.map((part) => {
|
|
1451
|
-
const p = part;
|
|
1452
|
-
if (p.thought === true || p.type === "thinking") {
|
|
1453
|
-
const fullText = p.text || p.thinking || "";
|
|
1454
|
-
if (displayedThinkingHashes) {
|
|
1455
|
-
const hash2 = hashString(fullText);
|
|
1456
|
-
if (displayedThinkingHashes.has(hash2)) {
|
|
1457
|
-
sentBuffer.set(index, fullText);
|
|
1458
|
-
return null;
|
|
1459
|
-
}
|
|
1460
|
-
displayedThinkingHashes.add(hash2);
|
|
1461
|
-
}
|
|
1462
|
-
const sentText = sentBuffer.get(index) ?? "";
|
|
1463
|
-
if (fullText.startsWith(sentText)) {
|
|
1464
|
-
const delta = fullText.slice(sentText.length);
|
|
1465
|
-
sentBuffer.set(index, fullText);
|
|
1466
|
-
if (delta) {
|
|
1467
|
-
return { ...p, text: delta, thinking: delta };
|
|
1468
|
-
}
|
|
1469
|
-
return null;
|
|
1470
|
-
}
|
|
1471
|
-
sentBuffer.set(index, fullText);
|
|
1472
|
-
return part;
|
|
1473
|
-
}
|
|
1474
|
-
return part;
|
|
1475
|
-
});
|
|
1476
|
-
const filteredParts = newParts.filter((p) => p !== null);
|
|
1477
|
-
return {
|
|
1478
|
-
...cand,
|
|
1479
|
-
content: { ...content, parts: filteredParts }
|
|
1480
|
-
};
|
|
1481
|
-
});
|
|
1482
|
-
return { ...resp, candidates: newCandidates };
|
|
1483
|
-
}
|
|
1484
|
-
if (Array.isArray(resp.content)) {
|
|
1485
|
-
let thinkingIndex = 0;
|
|
1486
|
-
const newContent = resp.content.map((block) => {
|
|
1487
|
-
const b = block;
|
|
1488
|
-
if (b?.type === "thinking") {
|
|
1489
|
-
const fullText = b.thinking || b.text || "";
|
|
1490
|
-
if (displayedThinkingHashes) {
|
|
1491
|
-
const hash2 = hashString(fullText);
|
|
1492
|
-
if (displayedThinkingHashes.has(hash2)) {
|
|
1493
|
-
sentBuffer.set(thinkingIndex, fullText);
|
|
1494
|
-
thinkingIndex++;
|
|
1495
|
-
return null;
|
|
1496
|
-
}
|
|
1497
|
-
displayedThinkingHashes.add(hash2);
|
|
1498
|
-
}
|
|
1499
|
-
const sentText = sentBuffer.get(thinkingIndex) ?? "";
|
|
1500
|
-
if (fullText.startsWith(sentText)) {
|
|
1501
|
-
const delta = fullText.slice(sentText.length);
|
|
1502
|
-
sentBuffer.set(thinkingIndex, fullText);
|
|
1503
|
-
thinkingIndex++;
|
|
1504
|
-
if (delta) {
|
|
1505
|
-
return { ...b, thinking: delta, text: delta };
|
|
1506
|
-
}
|
|
1507
|
-
return null;
|
|
1508
|
-
}
|
|
1509
|
-
sentBuffer.set(thinkingIndex, fullText);
|
|
1510
|
-
thinkingIndex++;
|
|
1511
|
-
return block;
|
|
1512
|
-
}
|
|
1513
|
-
return block;
|
|
1514
|
-
});
|
|
1515
|
-
const filteredContent = newContent.filter((b) => b !== null);
|
|
1516
|
-
if (filteredContent.length === 0) {
|
|
1517
|
-
return { ...resp, content: [] };
|
|
1518
|
-
}
|
|
1519
|
-
return { ...resp, content: filteredContent };
|
|
1520
|
-
}
|
|
1521
|
-
return response;
|
|
1522
|
-
}
|
|
1523
|
-
function cacheThinkingSignaturesFromResponse(response, signatureSessionKey, signatureStore, thoughtBuffer, onCacheSignature) {
|
|
1524
|
-
if (!response || typeof response !== "object") return;
|
|
1525
|
-
const resp = response;
|
|
1526
|
-
if (Array.isArray(resp.candidates)) {
|
|
1527
|
-
resp.candidates.forEach((candidate, index) => {
|
|
1528
|
-
const cand = candidate;
|
|
1529
|
-
if (!cand?.content) return;
|
|
1530
|
-
const content = cand.content;
|
|
1531
|
-
if (!Array.isArray(content.parts)) return;
|
|
1532
|
-
content.parts.forEach((part) => {
|
|
1533
|
-
const p = part;
|
|
1534
|
-
if (p.thought === true || p.type === "thinking") {
|
|
1535
|
-
const text = p.text || p.thinking || "";
|
|
1536
|
-
if (text) {
|
|
1537
|
-
const current = thoughtBuffer.get(index) ?? "";
|
|
1538
|
-
thoughtBuffer.set(index, current + text);
|
|
1539
|
-
}
|
|
1540
|
-
}
|
|
1541
|
-
if (p.thoughtSignature) {
|
|
1542
|
-
const fullText = thoughtBuffer.get(index) ?? "";
|
|
1543
|
-
if (fullText) {
|
|
1544
|
-
const signature = p.thoughtSignature;
|
|
1545
|
-
onCacheSignature?.(signatureSessionKey, fullText, signature);
|
|
1546
|
-
signatureStore.set(signatureSessionKey, { text: fullText, signature });
|
|
1547
|
-
}
|
|
1548
|
-
}
|
|
1549
|
-
});
|
|
1550
|
-
});
|
|
1551
|
-
}
|
|
1552
|
-
if (Array.isArray(resp.content)) {
|
|
1553
|
-
const CLAUDE_BUFFER_KEY = 0;
|
|
1554
|
-
resp.content.forEach((block) => {
|
|
1555
|
-
const b = block;
|
|
1556
|
-
if (b?.type === "thinking") {
|
|
1557
|
-
const text = b.thinking || b.text || "";
|
|
1558
|
-
if (text) {
|
|
1559
|
-
const current = thoughtBuffer.get(CLAUDE_BUFFER_KEY) ?? "";
|
|
1560
|
-
thoughtBuffer.set(CLAUDE_BUFFER_KEY, current + text);
|
|
1561
|
-
}
|
|
1562
|
-
}
|
|
1563
|
-
if (b?.signature) {
|
|
1564
|
-
const fullText = thoughtBuffer.get(CLAUDE_BUFFER_KEY) ?? "";
|
|
1565
|
-
if (fullText) {
|
|
1566
|
-
const signature = b.signature;
|
|
1567
|
-
onCacheSignature?.(signatureSessionKey, fullText, signature);
|
|
1568
|
-
signatureStore.set(signatureSessionKey, { text: fullText, signature });
|
|
1569
|
-
}
|
|
1570
|
-
}
|
|
1571
|
-
});
|
|
1572
|
-
}
|
|
1573
|
-
}
|
|
1574
|
-
function transformSseEvent(eventText, signatureStore, thoughtBuffer, sentThinkingBuffer, callbacks, options, debugState) {
|
|
1575
|
-
const dataLines = [];
|
|
1576
|
-
const lines = eventText.split(/\r?\n/);
|
|
1577
|
-
let isDataEvent = false;
|
|
1578
|
-
for (const line of lines) {
|
|
1579
|
-
if (line.startsWith("data:")) {
|
|
1580
|
-
isDataEvent = true;
|
|
1581
|
-
dataLines.push(line.slice(5).trim());
|
|
1582
|
-
}
|
|
1583
|
-
}
|
|
1584
|
-
if (!isDataEvent) {
|
|
1585
|
-
return eventText;
|
|
1586
|
-
}
|
|
1587
|
-
const jsonString = dataLines.join("\n").trim();
|
|
1588
|
-
if (!jsonString) {
|
|
1589
|
-
return eventText;
|
|
1590
|
-
}
|
|
1591
|
-
try {
|
|
1592
|
-
const parsed = JSON.parse(jsonString);
|
|
1593
|
-
if (parsed && typeof parsed === "object" && parsed.response !== void 0) {
|
|
1594
|
-
if (options.cacheSignatures && options.signatureSessionKey) {
|
|
1595
|
-
cacheThinkingSignaturesFromResponse(
|
|
1596
|
-
parsed.response,
|
|
1597
|
-
options.signatureSessionKey,
|
|
1598
|
-
signatureStore,
|
|
1599
|
-
thoughtBuffer,
|
|
1600
|
-
callbacks.onCacheSignature
|
|
1601
|
-
);
|
|
1602
|
-
}
|
|
1603
|
-
let response = deduplicateThinkingText(
|
|
1604
|
-
parsed.response,
|
|
1605
|
-
sentThinkingBuffer,
|
|
1606
|
-
options.displayedThinkingHashes
|
|
1607
|
-
);
|
|
1608
|
-
if (options.debugText && callbacks.onInjectDebug && !debugState.injected) {
|
|
1609
|
-
response = callbacks.onInjectDebug(response, options.debugText);
|
|
1610
|
-
debugState.injected = true;
|
|
1611
|
-
}
|
|
1612
|
-
const transformed = callbacks.transformThinkingParts ? callbacks.transformThinkingParts(response) : response;
|
|
1613
|
-
return `data: ${JSON.stringify(transformed)}`;
|
|
1614
|
-
}
|
|
1615
|
-
} catch (_) {
|
|
1616
|
-
}
|
|
1617
|
-
return eventText;
|
|
1618
|
-
}
|
|
1619
|
-
function createStreamingTransformer(signatureStore, callbacks, options = {}) {
|
|
1620
|
-
const decoder2 = new TextDecoder();
|
|
1621
|
-
const encoder2 = new TextEncoder();
|
|
1622
|
-
let buffer = "";
|
|
1623
|
-
const thoughtBuffer = createThoughtBuffer();
|
|
1624
|
-
const sentThinkingBuffer = createThoughtBuffer();
|
|
1625
|
-
const debugState = { injected: false };
|
|
1626
|
-
let hasSeenUsageMetadata = false;
|
|
1627
|
-
let streamHasThinking = false;
|
|
1628
|
-
let streamHasToolCalls = false;
|
|
1629
|
-
const displayedThinkingHashes = options.displayedThinkingHashes ?? /* @__PURE__ */ new Set();
|
|
1630
|
-
const mergedOptions = { ...options, displayedThinkingHashes };
|
|
1631
|
-
return new TransformStream({
|
|
1632
|
-
transform(chunk, controller) {
|
|
1633
|
-
buffer += decoder2.decode(chunk, { stream: true });
|
|
1634
|
-
const events = buffer.split(/\r?\n\r?\n/);
|
|
1635
|
-
buffer = events.pop() || "";
|
|
1636
|
-
for (const event of events) {
|
|
1637
|
-
if (!event.trim()) continue;
|
|
1638
|
-
if (event.includes("usageMetadata")) {
|
|
1639
|
-
hasSeenUsageMetadata = true;
|
|
1640
|
-
}
|
|
1641
|
-
if (!streamHasThinking) {
|
|
1642
|
-
streamHasThinking = event.includes('"thought":true') || event.includes('"type":"thinking"');
|
|
1643
|
-
}
|
|
1644
|
-
if (!streamHasToolCalls) {
|
|
1645
|
-
streamHasToolCalls = event.includes('"functionCall"');
|
|
1646
|
-
}
|
|
1647
|
-
const transformedEvent = transformSseEvent(
|
|
1648
|
-
event,
|
|
1649
|
-
signatureStore,
|
|
1650
|
-
thoughtBuffer,
|
|
1651
|
-
sentThinkingBuffer,
|
|
1652
|
-
callbacks,
|
|
1653
|
-
mergedOptions,
|
|
1654
|
-
debugState
|
|
1655
|
-
);
|
|
1656
|
-
controller.enqueue(encoder2.encode(transformedEvent + "\n\n"));
|
|
1657
|
-
}
|
|
1658
|
-
},
|
|
1659
|
-
flush(controller) {
|
|
1660
|
-
buffer += decoder2.decode();
|
|
1661
|
-
if (buffer.trim()) {
|
|
1662
|
-
if (buffer.includes("usageMetadata")) {
|
|
1663
|
-
hasSeenUsageMetadata = true;
|
|
1664
|
-
}
|
|
1665
|
-
if (!streamHasThinking) {
|
|
1666
|
-
streamHasThinking = buffer.includes('"thought":true') || buffer.includes('"type":"thinking"');
|
|
1667
|
-
}
|
|
1668
|
-
if (!streamHasToolCalls) {
|
|
1669
|
-
streamHasToolCalls = buffer.includes('"functionCall"');
|
|
1670
|
-
}
|
|
1671
|
-
const transformedEvent = transformSseEvent(
|
|
1672
|
-
buffer,
|
|
1673
|
-
signatureStore,
|
|
1674
|
-
thoughtBuffer,
|
|
1675
|
-
sentThinkingBuffer,
|
|
1676
|
-
callbacks,
|
|
1677
|
-
mergedOptions,
|
|
1678
|
-
debugState
|
|
1679
|
-
);
|
|
1680
|
-
controller.enqueue(encoder2.encode(transformedEvent + "\n\n"));
|
|
1681
|
-
}
|
|
1682
|
-
if (!hasSeenUsageMetadata) {
|
|
1683
|
-
const syntheticUsage = {
|
|
1684
|
-
candidates: [
|
|
1685
|
-
{
|
|
1686
|
-
finishReason: "STOP"
|
|
1687
|
-
}
|
|
1688
|
-
],
|
|
1689
|
-
usageMetadata: {
|
|
1690
|
-
promptTokenCount: 0,
|
|
1691
|
-
candidatesTokenCount: 0,
|
|
1692
|
-
totalTokenCount: 0
|
|
1693
|
-
}
|
|
1694
|
-
};
|
|
1695
|
-
controller.enqueue(encoder2.encode(`data: ${JSON.stringify(syntheticUsage)}
|
|
1696
|
-
|
|
1697
|
-
`));
|
|
1698
|
-
}
|
|
1699
|
-
if (callbacks.onTurnStateUpdate && options.signatureSessionKey) {
|
|
1700
|
-
callbacks.onTurnStateUpdate(options.signatureSessionKey, {
|
|
1701
|
-
turnHasThinking: streamHasThinking,
|
|
1702
|
-
lastModelHasToolCalls: streamHasToolCalls
|
|
1703
|
-
});
|
|
1704
|
-
}
|
|
1705
|
-
}
|
|
1706
|
-
});
|
|
1707
|
-
}
|
|
1708
|
-
|
|
1709
|
-
// src/sdk/request/turn-state-tracker.ts
|
|
1710
|
-
var WRITE_THROTTLE_MS = 5e3;
|
|
1711
|
-
function getConfigDir2() {
|
|
1712
|
-
const platform2 = process.platform;
|
|
1713
|
-
if (platform2 === "win32") {
|
|
1714
|
-
return join2(process.env.APPDATA || join2(homedir2(), "AppData", "Roaming"), "opencode");
|
|
1715
|
-
}
|
|
1716
|
-
const xdgConfig = process.env.XDG_CONFIG_HOME || join2(homedir2(), ".config");
|
|
1717
|
-
return join2(xdgConfig, "opencode");
|
|
1718
|
-
}
|
|
1719
|
-
function getTurnStateFilePath() {
|
|
1720
|
-
return join2(getConfigDir2(), "antigravity-turn-states.json");
|
|
1721
|
-
}
|
|
1722
|
-
function loadTurnStatesFromDisk() {
|
|
1723
|
-
const result = /* @__PURE__ */ new Map();
|
|
1724
|
-
try {
|
|
1725
|
-
const filePath = getTurnStateFilePath();
|
|
1726
|
-
if (!existsSync2(filePath)) {
|
|
1727
|
-
return result;
|
|
1728
|
-
}
|
|
1729
|
-
const content = readFileSync2(filePath, "utf-8");
|
|
1730
|
-
const data = JSON.parse(content);
|
|
1731
|
-
if (data.version !== "1.0") {
|
|
1732
|
-
return result;
|
|
1733
|
-
}
|
|
1734
|
-
const now = Date.now();
|
|
1735
|
-
const maxAge = 24 * 60 * 60 * 1e3;
|
|
1736
|
-
for (const [key, record2] of Object.entries(data.entries)) {
|
|
1737
|
-
if (record2.state && typeof record2.state === "object" && now - record2.updatedAt < maxAge) {
|
|
1738
|
-
result.set(key, record2);
|
|
1739
|
-
}
|
|
1740
|
-
}
|
|
1741
|
-
} catch {
|
|
1742
|
-
}
|
|
1743
|
-
return result;
|
|
1744
|
-
}
|
|
1745
|
-
function saveTurnStatesToDisk(entries) {
|
|
1746
|
-
try {
|
|
1747
|
-
const filePath = getTurnStateFilePath();
|
|
1748
|
-
const dir = dirname2(filePath);
|
|
1749
|
-
if (!existsSync2(dir)) {
|
|
1750
|
-
mkdirSync2(dir, { recursive: true });
|
|
1751
|
-
}
|
|
1752
|
-
const now = Date.now();
|
|
1753
|
-
const maxAge = 24 * 60 * 60 * 1e3;
|
|
1754
|
-
const serializable = {};
|
|
1755
|
-
for (const [key, record2] of entries.entries()) {
|
|
1756
|
-
if (now - record2.updatedAt < maxAge) {
|
|
1757
|
-
serializable[key] = record2;
|
|
1758
|
-
}
|
|
1759
|
-
}
|
|
1760
|
-
const data = {
|
|
1761
|
-
version: "1.0",
|
|
1762
|
-
entries: serializable,
|
|
1763
|
-
updatedAt: now
|
|
1764
|
-
};
|
|
1765
|
-
const tmpPath = join2(tmpdir2(), `antigravity-turn-states-${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`);
|
|
1766
|
-
writeFileSync2(tmpPath, JSON.stringify(data), "utf-8");
|
|
1767
|
-
try {
|
|
1768
|
-
renameSync2(tmpPath, filePath);
|
|
1769
|
-
} catch {
|
|
1770
|
-
writeFileSync2(filePath, readFileSync2(tmpPath));
|
|
1771
|
-
try {
|
|
1772
|
-
unlinkSync2(tmpPath);
|
|
1773
|
-
} catch {
|
|
1774
|
-
}
|
|
1775
|
-
}
|
|
1776
|
-
return true;
|
|
1777
|
-
} catch {
|
|
1778
|
-
return false;
|
|
1779
|
-
}
|
|
1780
|
-
}
|
|
1781
|
-
var TurnStateTracker = class {
|
|
1782
|
-
entries = /* @__PURE__ */ new Map();
|
|
1783
|
-
dirty = false;
|
|
1784
|
-
lastWriteTime = 0;
|
|
1785
|
-
writeTimer = null;
|
|
1786
|
-
diskEnabled;
|
|
1787
|
-
constructor(diskEnabled = true) {
|
|
1788
|
-
this.diskEnabled = diskEnabled;
|
|
1789
|
-
if (diskEnabled) {
|
|
1790
|
-
this.entries = loadTurnStatesFromDisk();
|
|
1791
|
-
}
|
|
1792
|
-
}
|
|
1793
|
-
getState(sessionId) {
|
|
1794
|
-
const record2 = this.entries.get(sessionId);
|
|
1795
|
-
if (!record2) return void 0;
|
|
1796
|
-
return record2.state;
|
|
1797
|
-
}
|
|
1798
|
-
needsThinkingRecovery(sessionId) {
|
|
1799
|
-
const state = this.entries.get(sessionId);
|
|
1800
|
-
if (!state) return false;
|
|
1801
|
-
return state.state.inToolLoop && !state.state.turnHasThinking;
|
|
1802
|
-
}
|
|
1803
|
-
updateAfterResponse(sessionId, newState) {
|
|
1804
|
-
this.entries.set(sessionId, { state: newState, updatedAt: Date.now() });
|
|
1805
|
-
this.dirty = true;
|
|
1806
|
-
this.scheduleThrottledWrite();
|
|
1807
|
-
}
|
|
1808
|
-
recoverFromContents(sessionId, contents) {
|
|
1809
|
-
const fullState = analyzeConversationState(contents);
|
|
1810
|
-
const turnState = {
|
|
1811
|
-
inToolLoop: fullState.inToolLoop,
|
|
1812
|
-
turnHasThinking: fullState.turnHasThinking,
|
|
1813
|
-
lastModelHasThinking: fullState.lastModelHasThinking,
|
|
1814
|
-
lastModelHasToolCalls: fullState.lastModelHasToolCalls
|
|
1815
|
-
};
|
|
1816
|
-
this.entries.set(sessionId, { state: turnState, updatedAt: Date.now() });
|
|
1817
|
-
this.dirty = true;
|
|
1818
|
-
this.scheduleThrottledWrite();
|
|
1819
|
-
return turnState;
|
|
1820
|
-
}
|
|
1821
|
-
clear(sessionId) {
|
|
1822
|
-
this.entries.delete(sessionId);
|
|
1823
|
-
this.dirty = true;
|
|
1824
|
-
this.scheduleThrottledWrite();
|
|
1825
|
-
}
|
|
1826
|
-
shutdown() {
|
|
1827
|
-
this.clearWriteTimer();
|
|
1828
|
-
if (this.dirty && this.diskEnabled) {
|
|
1829
|
-
saveTurnStatesToDisk(this.entries);
|
|
1830
|
-
this.dirty = false;
|
|
1831
|
-
}
|
|
1832
|
-
}
|
|
1833
|
-
scheduleThrottledWrite() {
|
|
1834
|
-
if (!this.diskEnabled) return;
|
|
1835
|
-
if (this.writeTimer) {
|
|
1836
|
-
return;
|
|
1837
|
-
}
|
|
1838
|
-
const elapsed = Date.now() - this.lastWriteTime;
|
|
1839
|
-
const remaining = Math.max(0, WRITE_THROTTLE_MS - elapsed);
|
|
1840
|
-
this.writeTimer = setTimeout(() => {
|
|
1841
|
-
this.writeTimer = null;
|
|
1842
|
-
this.lastWriteTime = Date.now();
|
|
1843
|
-
if (this.dirty) {
|
|
1844
|
-
this.dirty = false;
|
|
1845
|
-
saveTurnStatesToDisk(this.entries);
|
|
1846
|
-
}
|
|
1847
|
-
}, remaining);
|
|
1848
|
-
if (this.writeTimer && typeof this.writeTimer === "object" && "unref" in this.writeTimer) {
|
|
1849
|
-
this.writeTimer.unref();
|
|
1850
|
-
}
|
|
1851
|
-
}
|
|
1852
|
-
clearWriteTimer() {
|
|
1853
|
-
if (this.writeTimer) {
|
|
1854
|
-
clearTimeout(this.writeTimer);
|
|
1855
|
-
this.writeTimer = null;
|
|
1856
|
-
}
|
|
1857
|
-
}
|
|
1858
|
-
};
|
|
1859
|
-
var trackerInstance = null;
|
|
1860
|
-
function initTurnStateTracker() {
|
|
1861
|
-
if (!trackerInstance) {
|
|
1862
|
-
try {
|
|
1863
|
-
trackerInstance = new TurnStateTracker(true);
|
|
1864
|
-
if (typeof process !== "undefined") {
|
|
1865
|
-
process.on("exit", () => {
|
|
1866
|
-
trackerInstance?.shutdown();
|
|
1867
|
-
});
|
|
1868
|
-
}
|
|
1869
|
-
} catch {
|
|
1870
|
-
trackerInstance = new TurnStateTracker(false);
|
|
1871
|
-
}
|
|
1872
|
-
}
|
|
1873
|
-
return trackerInstance;
|
|
1874
|
-
}
|
|
1875
|
-
function getTurnStateTracker() {
|
|
1876
|
-
return trackerInstance;
|
|
1877
|
-
}
|
|
1878
|
-
|
|
1879
|
-
// src/sdk/retry/quota.ts
|
|
1880
|
-
var CLOUDCODE_DOMAINS = /* @__PURE__ */ new Set([
|
|
1881
|
-
"cloudcode-pa.googleapis.com",
|
|
1882
|
-
"staging-cloudcode-pa.googleapis.com",
|
|
1883
|
-
"autopush-cloudcode-pa.googleapis.com",
|
|
1884
|
-
"cloudaicompanion.googleapis.com",
|
|
1885
|
-
"daily-cloudcode-pa.googleapis.com"
|
|
1886
|
-
]);
|
|
1887
|
-
async function classifyQuotaResponse(response) {
|
|
1888
|
-
const payload = await parseErrorBody(response);
|
|
1889
|
-
if (!payload) {
|
|
1890
|
-
return null;
|
|
1891
|
-
}
|
|
1892
|
-
const details = Array.isArray(payload.details) ? payload.details : [];
|
|
1893
|
-
const retryInfo = details.find(
|
|
1894
|
-
(detail) => isObject(detail) && detail["@type"] === "type.googleapis.com/google.rpc.RetryInfo"
|
|
1895
|
-
);
|
|
1896
|
-
const retryDelayMs = (retryInfo?.retryDelay ? parseRetryDelayValue(retryInfo.retryDelay) : null) ?? parseRetryDelayFromMessage(payload.message ?? "") ?? void 0;
|
|
1897
|
-
const errorInfo = details.find(
|
|
1898
|
-
(detail) => isObject(detail) && detail["@type"] === "type.googleapis.com/google.rpc.ErrorInfo"
|
|
1899
|
-
);
|
|
1900
|
-
if (errorInfo?.domain && !CLOUDCODE_DOMAINS.has(errorInfo.domain)) {
|
|
1901
|
-
return null;
|
|
1902
|
-
}
|
|
1903
|
-
if (errorInfo?.reason === "QUOTA_EXHAUSTED") {
|
|
1904
|
-
return { terminal: true, retryDelayMs, reason: errorInfo.reason };
|
|
1905
|
-
}
|
|
1906
|
-
if (errorInfo?.reason === "RATE_LIMIT_EXCEEDED") {
|
|
1907
|
-
return { terminal: false, retryDelayMs: retryDelayMs ?? 1e4, reason: errorInfo.reason };
|
|
1908
|
-
}
|
|
1909
|
-
if (errorInfo?.reason === "MODEL_CAPACITY_EXHAUSTED") {
|
|
1910
|
-
return {
|
|
1911
|
-
terminal: retryDelayMs === void 0,
|
|
1912
|
-
retryDelayMs,
|
|
1913
|
-
reason: errorInfo.reason
|
|
1914
|
-
};
|
|
1915
|
-
}
|
|
1916
|
-
const quotaFailure = details.find(
|
|
1917
|
-
(detail) => isObject(detail) && detail["@type"] === "type.googleapis.com/google.rpc.QuotaFailure"
|
|
1918
|
-
);
|
|
1919
|
-
if (quotaFailure?.violations?.length) {
|
|
1920
|
-
const allTexts = quotaFailure.violations.flatMap((violation) => [violation.quotaId ?? "", violation.description ?? ""]).join(" ").toLowerCase();
|
|
1921
|
-
if (allTexts.includes("perday") || allTexts.includes("daily") || allTexts.includes("per day")) {
|
|
1922
|
-
return { terminal: true, retryDelayMs, reason: errorInfo?.reason };
|
|
1923
|
-
}
|
|
1924
|
-
if (allTexts.includes("perminute") || allTexts.includes("per minute")) {
|
|
1925
|
-
return { terminal: false, retryDelayMs: retryDelayMs ?? 6e4, reason: errorInfo?.reason };
|
|
1926
|
-
}
|
|
1927
|
-
return { terminal: false, retryDelayMs, reason: errorInfo?.reason };
|
|
1928
|
-
}
|
|
1929
|
-
const quotaLimit = errorInfo?.metadata?.quota_limit?.toLowerCase() ?? "";
|
|
1930
|
-
if (quotaLimit.includes("perminute") || quotaLimit.includes("per minute")) {
|
|
1931
|
-
return { terminal: false, retryDelayMs: retryDelayMs ?? 6e4, reason: errorInfo?.reason };
|
|
1932
|
-
}
|
|
1933
|
-
return { terminal: false, retryDelayMs, reason: errorInfo?.reason };
|
|
1934
|
-
}
|
|
1935
|
-
async function parseRetryDelayFromBody(response) {
|
|
1936
|
-
const payload = await parseErrorBody(response);
|
|
1937
|
-
if (!payload) {
|
|
1938
|
-
return null;
|
|
1939
|
-
}
|
|
1940
|
-
const details = Array.isArray(payload.details) ? payload.details : [];
|
|
1941
|
-
const retryInfo = details.find(
|
|
1942
|
-
(detail) => isObject(detail) && detail["@type"] === "type.googleapis.com/google.rpc.RetryInfo"
|
|
1943
|
-
);
|
|
1944
|
-
if (retryInfo?.retryDelay) {
|
|
1945
|
-
const delayMs = parseRetryDelayValue(retryInfo.retryDelay);
|
|
1946
|
-
if (delayMs !== null) {
|
|
1947
|
-
return delayMs;
|
|
1948
|
-
}
|
|
1949
|
-
}
|
|
1950
|
-
if (typeof payload.message === "string") {
|
|
1951
|
-
return parseRetryDelayFromMessage(payload.message);
|
|
1952
|
-
}
|
|
1953
|
-
return null;
|
|
1954
|
-
}
|
|
1955
|
-
function parseRetryDelayValue(value) {
|
|
1956
|
-
if (typeof value === "string") {
|
|
1957
|
-
const trimmed = value.trim();
|
|
1958
|
-
if (!trimmed) {
|
|
1959
|
-
return null;
|
|
1960
|
-
}
|
|
1961
|
-
if (trimmed.endsWith("ms")) {
|
|
1962
|
-
const milliseconds = Number(trimmed.slice(0, -2));
|
|
1963
|
-
return Number.isFinite(milliseconds) && milliseconds > 0 ? Math.round(milliseconds) : null;
|
|
1964
|
-
}
|
|
1965
|
-
const match = trimmed.match(/^([\d.]+)s$/);
|
|
1966
|
-
if (!match?.[1]) {
|
|
1967
|
-
return null;
|
|
1968
|
-
}
|
|
1969
|
-
const seconds2 = Number(match[1]);
|
|
1970
|
-
return Number.isFinite(seconds2) && seconds2 > 0 ? Math.round(seconds2 * 1e3) : null;
|
|
1971
|
-
}
|
|
1972
|
-
const seconds = typeof value.seconds === "number" ? value.seconds : 0;
|
|
1973
|
-
const nanos = typeof value.nanos === "number" ? value.nanos : 0;
|
|
1974
|
-
if (!Number.isFinite(seconds) || !Number.isFinite(nanos)) {
|
|
1975
|
-
return null;
|
|
1976
|
-
}
|
|
1977
|
-
const totalMs = Math.round(seconds * 1e3 + nanos / 1e6);
|
|
1978
|
-
return totalMs > 0 ? totalMs : null;
|
|
1979
|
-
}
|
|
1980
|
-
function parseRetryDelayFromMessage(message) {
|
|
1981
|
-
const retryMatch = message.match(/Please retry in ([0-9.]+(?:ms|s))/i);
|
|
1982
|
-
if (retryMatch?.[1]) {
|
|
1983
|
-
return parseRetryDelayValue(retryMatch[1]);
|
|
1984
|
-
}
|
|
1985
|
-
const afterMatch = message.match(/after\s+([0-9.]+(?:ms|s))/i);
|
|
1986
|
-
if (afterMatch?.[1]) {
|
|
1987
|
-
return parseRetryDelayValue(afterMatch[1]);
|
|
1988
|
-
}
|
|
1989
|
-
return null;
|
|
1990
|
-
}
|
|
1991
|
-
async function parseErrorBody(response) {
|
|
1992
|
-
let text = "";
|
|
1993
|
-
try {
|
|
1994
|
-
text = await response.clone().text();
|
|
1995
|
-
} catch {
|
|
1996
|
-
return null;
|
|
1997
|
-
}
|
|
1998
|
-
if (!text) {
|
|
1999
|
-
return null;
|
|
2000
|
-
}
|
|
2001
|
-
let parsed;
|
|
2002
|
-
try {
|
|
2003
|
-
parsed = JSON.parse(text);
|
|
2004
|
-
} catch {
|
|
2005
|
-
return null;
|
|
2006
|
-
}
|
|
2007
|
-
const normalized = normalizeErrorEnvelope(parsed);
|
|
2008
|
-
if (!normalized || !isObject(normalized.error)) {
|
|
2009
|
-
return null;
|
|
2010
|
-
}
|
|
2011
|
-
const error45 = normalized.error;
|
|
2012
|
-
return {
|
|
2013
|
-
message: typeof error45.message === "string" ? error45.message : void 0,
|
|
2014
|
-
details: Array.isArray(error45.details) ? error45.details : void 0
|
|
2015
|
-
};
|
|
2016
|
-
}
|
|
2017
|
-
function isObject(value) {
|
|
2018
|
-
return !!value && typeof value === "object";
|
|
2019
|
-
}
|
|
2020
|
-
function normalizeErrorEnvelope(parsed) {
|
|
2021
|
-
if (Array.isArray(parsed)) {
|
|
2022
|
-
const first = parsed[0];
|
|
2023
|
-
return isObject(first) ? first : null;
|
|
2024
|
-
}
|
|
2025
|
-
return isObject(parsed) ? parsed : null;
|
|
2026
|
-
}
|
|
2027
|
-
|
|
2028
|
-
// src/sdk/retry/helpers.ts
|
|
2029
|
-
var DEFAULT_MAX_ATTEMPTS = 3;
|
|
2030
|
-
var DEFAULT_INITIAL_DELAY_MS = 5e3;
|
|
2031
|
-
var DEFAULT_MAX_DELAY_MS = 3e4;
|
|
2032
|
-
var RETRYABLE_NETWORK_CODES = /* @__PURE__ */ new Set([
|
|
2033
|
-
"ECONNRESET",
|
|
2034
|
-
"ETIMEDOUT",
|
|
2035
|
-
"EPIPE",
|
|
2036
|
-
"ENOTFOUND",
|
|
2037
|
-
"EAI_AGAIN",
|
|
2038
|
-
"ECONNREFUSED",
|
|
2039
|
-
"ERR_SSL_SSLV3_ALERT_BAD_RECORD_MAC",
|
|
2040
|
-
"ERR_SSL_WRONG_VERSION_NUMBER",
|
|
2041
|
-
"ERR_SSL_DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
|
|
2042
|
-
"ERR_SSL_BAD_RECORD_MAC",
|
|
2043
|
-
"EPROTO"
|
|
2044
|
-
]);
|
|
2045
|
-
function canRetryRequest(init) {
|
|
2046
|
-
if (!init?.body) {
|
|
2047
|
-
return true;
|
|
2048
|
-
}
|
|
2049
|
-
const body = init.body;
|
|
2050
|
-
if (typeof body === "string") {
|
|
2051
|
-
return true;
|
|
2052
|
-
}
|
|
2053
|
-
if (typeof URLSearchParams !== "undefined" && body instanceof URLSearchParams) {
|
|
2054
|
-
return true;
|
|
2055
|
-
}
|
|
2056
|
-
if (typeof ArrayBuffer !== "undefined" && body instanceof ArrayBuffer) {
|
|
2057
|
-
return true;
|
|
2058
|
-
}
|
|
2059
|
-
if (typeof ArrayBuffer !== "undefined" && ArrayBuffer.isView(body)) {
|
|
2060
|
-
return true;
|
|
2061
|
-
}
|
|
2062
|
-
if (typeof Blob !== "undefined" && body instanceof Blob) {
|
|
2063
|
-
return true;
|
|
2064
|
-
}
|
|
2065
|
-
return false;
|
|
2066
|
-
}
|
|
2067
|
-
function isRetryableStatus(status) {
|
|
2068
|
-
return status === 429 || status >= 500 && status < 600;
|
|
2069
|
-
}
|
|
2070
|
-
function isRetryableNetworkError(error45) {
|
|
2071
|
-
const code = getNetworkErrorCode(error45);
|
|
2072
|
-
if (code && RETRYABLE_NETWORK_CODES.has(code)) {
|
|
2073
|
-
return true;
|
|
2074
|
-
}
|
|
2075
|
-
return error45 instanceof Error && error45.message.toLowerCase().includes("fetch failed");
|
|
2076
|
-
}
|
|
2077
|
-
async function resolveRetryDelayMs(response, attempt, quotaDelayMs) {
|
|
2078
|
-
const retryAfterMsHeader = parseRetryAfterMs(response.headers.get("retry-after-ms"));
|
|
2079
|
-
if (retryAfterMsHeader !== null) {
|
|
2080
|
-
return clampDelay(retryAfterMsHeader);
|
|
2081
|
-
}
|
|
2082
|
-
const retryAfterHeader = parseRetryAfter(response.headers.get("retry-after"));
|
|
2083
|
-
if (retryAfterHeader !== null) {
|
|
2084
|
-
return clampDelay(retryAfterHeader);
|
|
2085
|
-
}
|
|
2086
|
-
if (quotaDelayMs !== void 0) {
|
|
2087
|
-
return clampDelay(quotaDelayMs);
|
|
2088
|
-
}
|
|
2089
|
-
const bodyDelay = await parseRetryDelayFromBody(response);
|
|
2090
|
-
if (bodyDelay !== null) {
|
|
2091
|
-
return clampDelay(bodyDelay);
|
|
2092
|
-
}
|
|
2093
|
-
return getExponentialDelayWithJitter(attempt);
|
|
2094
|
-
}
|
|
2095
|
-
function getExponentialDelayWithJitter(attempt) {
|
|
2096
|
-
const base = Math.min(DEFAULT_MAX_DELAY_MS, DEFAULT_INITIAL_DELAY_MS * Math.pow(2, attempt - 1));
|
|
2097
|
-
const jitter = base * 0.3 * (Math.random() * 2 - 1);
|
|
2098
|
-
return clampDelay(base + jitter);
|
|
2099
|
-
}
|
|
2100
|
-
function wait2(ms) {
|
|
2101
|
-
return new Promise((resolve) => {
|
|
2102
|
-
setTimeout(resolve, ms);
|
|
2103
|
-
});
|
|
2104
|
-
}
|
|
2105
|
-
function getNetworkErrorCode(error45) {
|
|
2106
|
-
const readCode = (value) => {
|
|
2107
|
-
if (!value || typeof value !== "object") {
|
|
2108
|
-
return void 0;
|
|
2109
|
-
}
|
|
2110
|
-
if ("code" in value && typeof value.code === "string") {
|
|
2111
|
-
return value.code;
|
|
2112
|
-
}
|
|
2113
|
-
return void 0;
|
|
2114
|
-
};
|
|
2115
|
-
const direct = readCode(error45);
|
|
2116
|
-
if (direct) {
|
|
2117
|
-
return direct;
|
|
2118
|
-
}
|
|
2119
|
-
let cursor = error45;
|
|
2120
|
-
for (let depth = 0; depth < 5; depth += 1) {
|
|
2121
|
-
if (!cursor || typeof cursor !== "object" || !("cause" in cursor)) {
|
|
2122
|
-
break;
|
|
2123
|
-
}
|
|
2124
|
-
cursor = cursor.cause;
|
|
2125
|
-
const code = readCode(cursor);
|
|
2126
|
-
if (code) {
|
|
2127
|
-
return code;
|
|
2128
|
-
}
|
|
2129
|
-
}
|
|
2130
|
-
return void 0;
|
|
2131
|
-
}
|
|
2132
|
-
function parseRetryAfterMs(value) {
|
|
2133
|
-
if (!value) {
|
|
2134
|
-
return null;
|
|
2135
|
-
}
|
|
2136
|
-
const parsed = Number(value.trim());
|
|
2137
|
-
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
2138
|
-
return null;
|
|
2139
|
-
}
|
|
2140
|
-
return Math.round(parsed);
|
|
2141
|
-
}
|
|
2142
|
-
function parseRetryAfter(value) {
|
|
2143
|
-
if (!value) {
|
|
2144
|
-
return null;
|
|
2145
|
-
}
|
|
2146
|
-
const trimmed = value.trim();
|
|
2147
|
-
if (!trimmed) {
|
|
2148
|
-
return null;
|
|
2149
|
-
}
|
|
2150
|
-
const seconds = Number(trimmed);
|
|
2151
|
-
if (Number.isFinite(seconds)) {
|
|
2152
|
-
return Math.max(0, Math.round(seconds * 1e3));
|
|
2153
|
-
}
|
|
2154
|
-
const parsedDate = Date.parse(trimmed);
|
|
2155
|
-
if (!Number.isNaN(parsedDate)) {
|
|
2156
|
-
return Math.max(0, parsedDate - Date.now());
|
|
2157
|
-
}
|
|
2158
|
-
return null;
|
|
2159
|
-
}
|
|
2160
|
-
function clampDelay(delayMs) {
|
|
2161
|
-
if (!Number.isFinite(delayMs)) {
|
|
2162
|
-
return DEFAULT_MAX_DELAY_MS;
|
|
2163
|
-
}
|
|
2164
|
-
return Math.min(Math.max(0, Math.round(delayMs)), DEFAULT_MAX_DELAY_MS);
|
|
2165
|
-
}
|
|
2166
|
-
|
|
2167
|
-
// src/sdk/retry/cooldown-store.ts
|
|
2168
|
-
import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3, renameSync as renameSync3, unlinkSync as unlinkSync3 } from "fs";
|
|
2169
|
-
import { join as join3, dirname as dirname3 } from "path";
|
|
2170
|
-
import { homedir as homedir3, tmpdir as tmpdir3 } from "os";
|
|
2171
|
-
var WRITE_THROTTLE_MS2 = 5e3;
|
|
2172
|
-
function getConfigDir3() {
|
|
2173
|
-
const platform2 = process.platform;
|
|
2174
|
-
if (platform2 === "win32") {
|
|
2175
|
-
return join3(process.env.APPDATA || join3(homedir3(), "AppData", "Roaming"), "opencode");
|
|
2176
|
-
}
|
|
2177
|
-
const xdgConfig = process.env.XDG_CONFIG_HOME || join3(homedir3(), ".config");
|
|
2178
|
-
return join3(xdgConfig, "opencode");
|
|
2179
|
-
}
|
|
2180
|
-
function getCooldownFilePath() {
|
|
2181
|
-
return join3(getConfigDir3(), "antigravity-retry-cooldowns.json");
|
|
2182
|
-
}
|
|
2183
|
-
function loadCooldowns() {
|
|
2184
|
-
const result = /* @__PURE__ */ new Map();
|
|
2185
|
-
try {
|
|
2186
|
-
const filePath = getCooldownFilePath();
|
|
2187
|
-
if (!existsSync3(filePath)) {
|
|
2188
|
-
return result;
|
|
2189
|
-
}
|
|
2190
|
-
const content = readFileSync3(filePath, "utf-8");
|
|
2191
|
-
const data = JSON.parse(content);
|
|
2192
|
-
if (data.version !== "1.0") {
|
|
2193
|
-
return result;
|
|
2194
|
-
}
|
|
2195
|
-
const now = Date.now();
|
|
2196
|
-
for (const [key, expiresAt] of Object.entries(data.entries)) {
|
|
2197
|
-
if (typeof expiresAt === "number" && expiresAt > now) {
|
|
2198
|
-
result.set(key, expiresAt);
|
|
2199
|
-
}
|
|
2200
|
-
}
|
|
2201
|
-
} catch {
|
|
2202
|
-
}
|
|
2203
|
-
return result;
|
|
2204
|
-
}
|
|
2205
|
-
function saveCooldowns(entries) {
|
|
2206
|
-
try {
|
|
2207
|
-
const filePath = getCooldownFilePath();
|
|
2208
|
-
const dir = dirname3(filePath);
|
|
2209
|
-
if (!existsSync3(dir)) {
|
|
2210
|
-
mkdirSync3(dir, { recursive: true });
|
|
2211
|
-
}
|
|
2212
|
-
const now = Date.now();
|
|
2213
|
-
const serializable = {};
|
|
2214
|
-
for (const [key, expiresAt] of entries.entries()) {
|
|
2215
|
-
if (expiresAt > now) {
|
|
2216
|
-
serializable[key] = expiresAt;
|
|
2217
|
-
}
|
|
2218
|
-
}
|
|
2219
|
-
const data = {
|
|
2220
|
-
version: "1.0",
|
|
2221
|
-
entries: serializable,
|
|
2222
|
-
updatedAt: now
|
|
2223
|
-
};
|
|
2224
|
-
const tmpPath = join3(tmpdir3(), `antigravity-cooldowns-${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`);
|
|
2225
|
-
writeFileSync3(tmpPath, JSON.stringify(data), "utf-8");
|
|
2226
|
-
try {
|
|
2227
|
-
renameSync3(tmpPath, filePath);
|
|
2228
|
-
} catch {
|
|
2229
|
-
writeFileSync3(filePath, readFileSync3(tmpPath));
|
|
2230
|
-
try {
|
|
2231
|
-
unlinkSync3(tmpPath);
|
|
2232
|
-
} catch {
|
|
2233
|
-
}
|
|
2234
|
-
}
|
|
2235
|
-
return true;
|
|
2236
|
-
} catch {
|
|
2237
|
-
return false;
|
|
2238
|
-
}
|
|
2239
|
-
}
|
|
2240
|
-
var CooldownStore = class {
|
|
2241
|
-
dirty = false;
|
|
2242
|
-
lastWriteTime = 0;
|
|
2243
|
-
writeTimer = null;
|
|
2244
|
-
entries = /* @__PURE__ */ new Map();
|
|
2245
|
-
bind(entries) {
|
|
2246
|
-
this.entries = entries;
|
|
2247
|
-
}
|
|
2248
|
-
markDirty() {
|
|
2249
|
-
this.dirty = true;
|
|
2250
|
-
this.scheduleThrottledWrite();
|
|
2251
|
-
}
|
|
2252
|
-
flush() {
|
|
2253
|
-
this.dirty = false;
|
|
2254
|
-
this.clearWriteTimer();
|
|
2255
|
-
this.lastWriteTime = Date.now();
|
|
2256
|
-
return saveCooldowns(this.entries);
|
|
2257
|
-
}
|
|
2258
|
-
shutdown() {
|
|
2259
|
-
this.clearWriteTimer();
|
|
2260
|
-
if (this.dirty) {
|
|
2261
|
-
saveCooldowns(this.entries);
|
|
2262
|
-
this.dirty = false;
|
|
2263
|
-
}
|
|
2264
|
-
}
|
|
2265
|
-
scheduleThrottledWrite() {
|
|
2266
|
-
if (this.writeTimer) {
|
|
2267
|
-
return;
|
|
2268
|
-
}
|
|
2269
|
-
const elapsed = Date.now() - this.lastWriteTime;
|
|
2270
|
-
const remaining = Math.max(0, WRITE_THROTTLE_MS2 - elapsed);
|
|
2271
|
-
this.writeTimer = setTimeout(() => {
|
|
2272
|
-
this.writeTimer = null;
|
|
2273
|
-
this.lastWriteTime = Date.now();
|
|
2274
|
-
if (this.dirty) {
|
|
2275
|
-
this.dirty = false;
|
|
2276
|
-
saveCooldowns(this.entries);
|
|
2277
|
-
}
|
|
2278
|
-
}, remaining);
|
|
2279
|
-
if (this.writeTimer && typeof this.writeTimer === "object" && "unref" in this.writeTimer) {
|
|
2280
|
-
this.writeTimer.unref();
|
|
2281
|
-
}
|
|
2282
|
-
}
|
|
2283
|
-
clearWriteTimer() {
|
|
2284
|
-
if (this.writeTimer) {
|
|
2285
|
-
clearTimeout(this.writeTimer);
|
|
2286
|
-
this.writeTimer = null;
|
|
2287
|
-
}
|
|
2288
|
-
}
|
|
2289
|
-
};
|
|
2290
|
-
|
|
2291
|
-
// src/sdk/retry/index.ts
|
|
2292
|
-
var retryCooldownByKey = /* @__PURE__ */ new Map();
|
|
2293
|
-
var cooldownStore = new CooldownStore();
|
|
2294
|
-
var cooldownPersistenceInitialized = false;
|
|
2295
|
-
function initCooldownPersistence() {
|
|
2296
|
-
if (cooldownPersistenceInitialized) return;
|
|
2297
|
-
cooldownPersistenceInitialized = true;
|
|
2298
|
-
try {
|
|
2299
|
-
const persisted = loadCooldowns();
|
|
2300
|
-
for (const [key, expiresAt] of persisted.entries()) {
|
|
2301
|
-
retryCooldownByKey.set(key, expiresAt);
|
|
2302
|
-
}
|
|
2303
|
-
cooldownStore.bind(retryCooldownByKey);
|
|
2304
|
-
if (typeof process !== "undefined") {
|
|
2305
|
-
process.on("exit", () => {
|
|
2306
|
-
cooldownStore.shutdown();
|
|
2307
|
-
});
|
|
2308
|
-
}
|
|
2309
|
-
} catch {
|
|
2310
|
-
cooldownStore.bind(retryCooldownByKey);
|
|
2311
|
-
}
|
|
2312
|
-
}
|
|
2313
|
-
var MODEL_CAPACITY_COOLDOWN_MS = 8e3;
|
|
2314
|
-
async function fetchWithRetry(input, init) {
|
|
2315
|
-
if (!cooldownPersistenceInitialized) initCooldownPersistence();
|
|
2316
|
-
if (!canRetryRequest(init)) {
|
|
2317
|
-
return agyFetch(input, init);
|
|
2318
|
-
}
|
|
2319
|
-
const retryInit = cloneRetryableInit(init);
|
|
2320
|
-
const throttleKey = buildRetryThrottleKey(input, retryInit);
|
|
2321
|
-
await waitForRetryCooldown(throttleKey, retryInit.signal);
|
|
2322
|
-
let attempt = 1;
|
|
2323
|
-
const url2 = readRequestUrl(input);
|
|
2324
|
-
while (attempt <= DEFAULT_MAX_ATTEMPTS) {
|
|
2325
|
-
let response;
|
|
2326
|
-
try {
|
|
2327
|
-
response = await agyFetch(input, retryInit);
|
|
2328
|
-
} catch (error45) {
|
|
2329
|
-
if (attempt >= DEFAULT_MAX_ATTEMPTS || !isRetryableNetworkError(error45)) {
|
|
2330
|
-
throw error45;
|
|
2331
|
-
}
|
|
2332
|
-
if (retryInit.signal?.aborted) {
|
|
2333
|
-
throw error45;
|
|
2334
|
-
}
|
|
2335
|
-
const delayMs2 = getExponentialDelayWithJitter(attempt);
|
|
2336
|
-
await wait2(delayMs2);
|
|
2337
|
-
attempt += 1;
|
|
2338
|
-
continue;
|
|
2339
|
-
}
|
|
2340
|
-
if (!isRetryableStatus(response.status)) {
|
|
2341
|
-
return response;
|
|
2342
|
-
}
|
|
2343
|
-
const quotaContext = response.status === 429 ? await classifyQuotaResponse(response) : null;
|
|
2344
|
-
if (response.status === 429 && quotaContext?.terminal) {
|
|
2345
|
-
if (quotaContext.reason === "MODEL_CAPACITY_EXHAUSTED") {
|
|
2346
|
-
const cooldownMs = quotaContext.retryDelayMs ?? MODEL_CAPACITY_COOLDOWN_MS;
|
|
2347
|
-
setRetryCooldown(throttleKey, cooldownMs);
|
|
2348
|
-
}
|
|
2349
|
-
return response;
|
|
2350
|
-
}
|
|
2351
|
-
if (attempt >= DEFAULT_MAX_ATTEMPTS || retryInit.signal?.aborted) {
|
|
2352
|
-
return response;
|
|
2353
|
-
}
|
|
2354
|
-
const delayMs = await resolveRetryDelayMs(response, attempt, quotaContext?.retryDelayMs);
|
|
2355
|
-
if (delayMs > 0 && response.status === 429) {
|
|
2356
|
-
setRetryCooldown(throttleKey, delayMs);
|
|
2357
|
-
}
|
|
2358
|
-
if (delayMs > 0) {
|
|
2359
|
-
await wait2(delayMs);
|
|
2360
|
-
}
|
|
2361
|
-
attempt += 1;
|
|
2362
|
-
}
|
|
2363
|
-
return agyFetch(input, retryInit);
|
|
2364
|
-
}
|
|
2365
|
-
function cloneRetryableInit(init) {
|
|
2366
|
-
if (!init) {
|
|
2367
|
-
return {};
|
|
2368
|
-
}
|
|
2369
|
-
return {
|
|
2370
|
-
...init,
|
|
2371
|
-
headers: new Headers(init.headers ?? {})
|
|
2372
|
-
};
|
|
2373
|
-
}
|
|
2374
|
-
function buildRetryThrottleKey(input, init) {
|
|
2375
|
-
const url2 = readRequestUrl(input);
|
|
2376
|
-
const body = typeof init.body === "string" ? safeParseBody(init.body) : null;
|
|
2377
|
-
const project = readString(body?.project);
|
|
2378
|
-
const model = readString(body?.model);
|
|
2379
|
-
return `${url2}|${project ?? ""}|${model ?? ""}`;
|
|
2380
|
-
}
|
|
2381
|
-
async function waitForRetryCooldown(key, signal) {
|
|
2382
|
-
const until = retryCooldownByKey.get(key);
|
|
2383
|
-
if (!until) {
|
|
2384
|
-
return;
|
|
2385
|
-
}
|
|
2386
|
-
const remaining = until - Date.now();
|
|
2387
|
-
if (remaining <= 0) {
|
|
2388
|
-
retryCooldownByKey.delete(key);
|
|
2389
|
-
return;
|
|
2390
|
-
}
|
|
2391
|
-
if (signal?.aborted) {
|
|
2392
|
-
return;
|
|
2393
|
-
}
|
|
2394
|
-
await wait2(remaining);
|
|
2395
|
-
retryCooldownByKey.delete(key);
|
|
2396
|
-
}
|
|
2397
|
-
function setRetryCooldown(key, delayMs) {
|
|
2398
|
-
if (!cooldownPersistenceInitialized) initCooldownPersistence();
|
|
2399
|
-
const next = Date.now() + delayMs;
|
|
2400
|
-
const current = retryCooldownByKey.get(key) ?? 0;
|
|
2401
|
-
retryCooldownByKey.set(key, Math.max(current, next));
|
|
2402
|
-
cooldownStore.markDirty();
|
|
2403
|
-
}
|
|
2404
|
-
function readRequestUrl(input) {
|
|
2405
|
-
if (typeof input === "string") {
|
|
2406
|
-
return input;
|
|
2407
|
-
}
|
|
2408
|
-
if (input instanceof URL) {
|
|
2409
|
-
return input.toString();
|
|
2410
|
-
}
|
|
2411
|
-
const request = input;
|
|
2412
|
-
if (request.url) {
|
|
2413
|
-
return request.url;
|
|
2414
|
-
}
|
|
2415
|
-
return input.toString();
|
|
2416
|
-
}
|
|
2417
|
-
function safeParseBody(body) {
|
|
2418
|
-
if (!body) {
|
|
2419
|
-
return null;
|
|
2420
|
-
}
|
|
2421
|
-
try {
|
|
2422
|
-
const parsed = JSON.parse(body);
|
|
2423
|
-
if (parsed && typeof parsed === "object") {
|
|
2424
|
-
return parsed;
|
|
2425
|
-
}
|
|
2426
|
-
} catch {
|
|
2427
|
-
}
|
|
2428
|
-
return null;
|
|
2429
|
-
}
|
|
2430
|
-
function readString(value) {
|
|
2431
|
-
return typeof value === "string" && value.trim() ? value : void 0;
|
|
2432
|
-
}
|
|
2433
|
-
|
|
2434
1288
|
// node_modules/zod/v4/classic/external.js
|
|
2435
1289
|
var external_exports = {};
|
|
2436
1290
|
__export(external_exports, {
|
|
@@ -3026,7 +1880,7 @@ __export(util_exports, {
|
|
|
3026
1880
|
getParsedType: () => getParsedType,
|
|
3027
1881
|
getSizableOrigin: () => getSizableOrigin,
|
|
3028
1882
|
hexToUint8Array: () => hexToUint8Array,
|
|
3029
|
-
isObject: () =>
|
|
1883
|
+
isObject: () => isObject,
|
|
3030
1884
|
isPlainObject: () => isPlainObject,
|
|
3031
1885
|
issue: () => issue,
|
|
3032
1886
|
joinValues: () => joinValues,
|
|
@@ -3191,7 +2045,7 @@ function esc(str) {
|
|
|
3191
2045
|
}
|
|
3192
2046
|
var captureStackTrace = "captureStackTrace" in Error ? Error.captureStackTrace : (..._args) => {
|
|
3193
2047
|
};
|
|
3194
|
-
function
|
|
2048
|
+
function isObject(data) {
|
|
3195
2049
|
return typeof data === "object" && data !== null && !Array.isArray(data);
|
|
3196
2050
|
}
|
|
3197
2051
|
var allowsEval = cached(() => {
|
|
@@ -3207,13 +2061,13 @@ var allowsEval = cached(() => {
|
|
|
3207
2061
|
}
|
|
3208
2062
|
});
|
|
3209
2063
|
function isPlainObject(o) {
|
|
3210
|
-
if (
|
|
2064
|
+
if (isObject(o) === false)
|
|
3211
2065
|
return false;
|
|
3212
2066
|
const ctor = o.constructor;
|
|
3213
2067
|
if (ctor === void 0)
|
|
3214
2068
|
return true;
|
|
3215
2069
|
const prot = ctor.prototype;
|
|
3216
|
-
if (
|
|
2070
|
+
if (isObject(prot) === false)
|
|
3217
2071
|
return false;
|
|
3218
2072
|
if (Object.prototype.hasOwnProperty.call(prot, "isPrototypeOf") === false) {
|
|
3219
2073
|
return false;
|
|
@@ -5316,7 +4170,7 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
|
|
|
5316
4170
|
}
|
|
5317
4171
|
return propValues;
|
|
5318
4172
|
});
|
|
5319
|
-
const isObject3 =
|
|
4173
|
+
const isObject3 = isObject;
|
|
5320
4174
|
const catchall = def.catchall;
|
|
5321
4175
|
let value;
|
|
5322
4176
|
inst._zod.parse = (payload, ctx) => {
|
|
@@ -5396,7 +4250,7 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
|
|
|
5396
4250
|
return (payload, ctx) => fn(shape, payload, ctx);
|
|
5397
4251
|
};
|
|
5398
4252
|
let fastpass;
|
|
5399
|
-
const isObject3 =
|
|
4253
|
+
const isObject3 = isObject;
|
|
5400
4254
|
const jit = !globalConfig.jitless;
|
|
5401
4255
|
const allowsEval2 = allowsEval;
|
|
5402
4256
|
const fastEnabled = jit && allowsEval2.value;
|
|
@@ -5528,7 +4382,7 @@ var $ZodDiscriminatedUnion = /* @__PURE__ */ $constructor("$ZodDiscriminatedUnio
|
|
|
5528
4382
|
});
|
|
5529
4383
|
inst._zod.parse = (payload, ctx) => {
|
|
5530
4384
|
const input = payload.value;
|
|
5531
|
-
if (!
|
|
4385
|
+
if (!isObject(input)) {
|
|
5532
4386
|
payload.issues.push({
|
|
5533
4387
|
code: "invalid_type",
|
|
5534
4388
|
expected: "object",
|
|
@@ -14815,43 +13669,331 @@ function setErrorMap(map2) {
|
|
|
14815
13669
|
function getErrorMap() {
|
|
14816
13670
|
return config().customError;
|
|
14817
13671
|
}
|
|
14818
|
-
var ZodFirstPartyTypeKind;
|
|
14819
|
-
/* @__PURE__ */ (function(ZodFirstPartyTypeKind2) {
|
|
14820
|
-
})(ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {}));
|
|
14821
|
-
|
|
14822
|
-
// node_modules/zod/v4/classic/coerce.js
|
|
14823
|
-
var coerce_exports = {};
|
|
14824
|
-
__export(coerce_exports, {
|
|
14825
|
-
bigint: () => bigint3,
|
|
14826
|
-
boolean: () => boolean3,
|
|
14827
|
-
date: () => date4,
|
|
14828
|
-
number: () => number3,
|
|
14829
|
-
string: () => string3
|
|
14830
|
-
});
|
|
14831
|
-
function string3(params) {
|
|
14832
|
-
return _coercedString(ZodString, params);
|
|
13672
|
+
var ZodFirstPartyTypeKind;
|
|
13673
|
+
/* @__PURE__ */ (function(ZodFirstPartyTypeKind2) {
|
|
13674
|
+
})(ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {}));
|
|
13675
|
+
|
|
13676
|
+
// node_modules/zod/v4/classic/coerce.js
|
|
13677
|
+
var coerce_exports = {};
|
|
13678
|
+
__export(coerce_exports, {
|
|
13679
|
+
bigint: () => bigint3,
|
|
13680
|
+
boolean: () => boolean3,
|
|
13681
|
+
date: () => date4,
|
|
13682
|
+
number: () => number3,
|
|
13683
|
+
string: () => string3
|
|
13684
|
+
});
|
|
13685
|
+
function string3(params) {
|
|
13686
|
+
return _coercedString(ZodString, params);
|
|
13687
|
+
}
|
|
13688
|
+
function number3(params) {
|
|
13689
|
+
return _coercedNumber(ZodNumber, params);
|
|
13690
|
+
}
|
|
13691
|
+
function boolean3(params) {
|
|
13692
|
+
return _coercedBoolean(ZodBoolean, params);
|
|
13693
|
+
}
|
|
13694
|
+
function bigint3(params) {
|
|
13695
|
+
return _coercedBigint(ZodBigInt, params);
|
|
13696
|
+
}
|
|
13697
|
+
function date4(params) {
|
|
13698
|
+
return _coercedDate(ZodDate, params);
|
|
13699
|
+
}
|
|
13700
|
+
|
|
13701
|
+
// node_modules/zod/v4/classic/external.js
|
|
13702
|
+
config(en_default());
|
|
13703
|
+
|
|
13704
|
+
// node_modules/@opencode-ai/plugin/dist/tool.js
|
|
13705
|
+
function tool(input) {
|
|
13706
|
+
return input;
|
|
13707
|
+
}
|
|
13708
|
+
tool.schema = external_exports;
|
|
13709
|
+
|
|
13710
|
+
// src/sdk/retry/quota.ts
|
|
13711
|
+
var CLOUDCODE_DOMAINS = /* @__PURE__ */ new Set([
|
|
13712
|
+
"cloudcode-pa.googleapis.com",
|
|
13713
|
+
"staging-cloudcode-pa.googleapis.com",
|
|
13714
|
+
"autopush-cloudcode-pa.googleapis.com",
|
|
13715
|
+
"cloudaicompanion.googleapis.com",
|
|
13716
|
+
"daily-cloudcode-pa.googleapis.com"
|
|
13717
|
+
]);
|
|
13718
|
+
async function classifyQuotaResponse(response) {
|
|
13719
|
+
const payload = await parseErrorBody(response);
|
|
13720
|
+
if (!payload) {
|
|
13721
|
+
return null;
|
|
13722
|
+
}
|
|
13723
|
+
const details = Array.isArray(payload.details) ? payload.details : [];
|
|
13724
|
+
const retryInfo = details.find(
|
|
13725
|
+
(detail) => isObject2(detail) && detail["@type"] === "type.googleapis.com/google.rpc.RetryInfo"
|
|
13726
|
+
);
|
|
13727
|
+
const retryDelayMs = (retryInfo?.retryDelay ? parseRetryDelayValue(retryInfo.retryDelay) : null) ?? parseRetryDelayFromMessage(payload.message ?? "") ?? void 0;
|
|
13728
|
+
const errorInfo = details.find(
|
|
13729
|
+
(detail) => isObject2(detail) && detail["@type"] === "type.googleapis.com/google.rpc.ErrorInfo"
|
|
13730
|
+
);
|
|
13731
|
+
if (errorInfo?.domain && !CLOUDCODE_DOMAINS.has(errorInfo.domain)) {
|
|
13732
|
+
return null;
|
|
13733
|
+
}
|
|
13734
|
+
if (errorInfo?.reason === "QUOTA_EXHAUSTED") {
|
|
13735
|
+
return { terminal: true, retryDelayMs, reason: errorInfo.reason };
|
|
13736
|
+
}
|
|
13737
|
+
if (errorInfo?.reason === "RATE_LIMIT_EXCEEDED") {
|
|
13738
|
+
return { terminal: false, retryDelayMs: retryDelayMs ?? 1e4, reason: errorInfo.reason };
|
|
13739
|
+
}
|
|
13740
|
+
if (errorInfo?.reason === "MODEL_CAPACITY_EXHAUSTED") {
|
|
13741
|
+
return {
|
|
13742
|
+
terminal: retryDelayMs === void 0,
|
|
13743
|
+
retryDelayMs,
|
|
13744
|
+
reason: errorInfo.reason
|
|
13745
|
+
};
|
|
13746
|
+
}
|
|
13747
|
+
const quotaFailure = details.find(
|
|
13748
|
+
(detail) => isObject2(detail) && detail["@type"] === "type.googleapis.com/google.rpc.QuotaFailure"
|
|
13749
|
+
);
|
|
13750
|
+
if (quotaFailure?.violations?.length) {
|
|
13751
|
+
const allTexts = quotaFailure.violations.flatMap((violation) => [violation.quotaId ?? "", violation.description ?? ""]).join(" ").toLowerCase();
|
|
13752
|
+
if (allTexts.includes("perday") || allTexts.includes("daily") || allTexts.includes("per day")) {
|
|
13753
|
+
return { terminal: true, retryDelayMs, reason: errorInfo?.reason };
|
|
13754
|
+
}
|
|
13755
|
+
if (allTexts.includes("perminute") || allTexts.includes("per minute")) {
|
|
13756
|
+
return { terminal: false, retryDelayMs: retryDelayMs ?? 6e4, reason: errorInfo?.reason };
|
|
13757
|
+
}
|
|
13758
|
+
return { terminal: false, retryDelayMs, reason: errorInfo?.reason };
|
|
13759
|
+
}
|
|
13760
|
+
const quotaLimit = errorInfo?.metadata?.quota_limit?.toLowerCase() ?? "";
|
|
13761
|
+
if (quotaLimit.includes("perminute") || quotaLimit.includes("per minute")) {
|
|
13762
|
+
return { terminal: false, retryDelayMs: retryDelayMs ?? 6e4, reason: errorInfo?.reason };
|
|
13763
|
+
}
|
|
13764
|
+
return { terminal: false, retryDelayMs, reason: errorInfo?.reason };
|
|
13765
|
+
}
|
|
13766
|
+
async function parseRetryDelayFromBody(response) {
|
|
13767
|
+
const payload = await parseErrorBody(response);
|
|
13768
|
+
if (!payload) {
|
|
13769
|
+
return null;
|
|
13770
|
+
}
|
|
13771
|
+
const details = Array.isArray(payload.details) ? payload.details : [];
|
|
13772
|
+
const retryInfo = details.find(
|
|
13773
|
+
(detail) => isObject2(detail) && detail["@type"] === "type.googleapis.com/google.rpc.RetryInfo"
|
|
13774
|
+
);
|
|
13775
|
+
if (retryInfo?.retryDelay) {
|
|
13776
|
+
const delayMs = parseRetryDelayValue(retryInfo.retryDelay);
|
|
13777
|
+
if (delayMs !== null) {
|
|
13778
|
+
return delayMs;
|
|
13779
|
+
}
|
|
13780
|
+
}
|
|
13781
|
+
if (typeof payload.message === "string") {
|
|
13782
|
+
return parseRetryDelayFromMessage(payload.message);
|
|
13783
|
+
}
|
|
13784
|
+
return null;
|
|
13785
|
+
}
|
|
13786
|
+
function parseRetryDelayValue(value) {
|
|
13787
|
+
if (typeof value === "string") {
|
|
13788
|
+
const trimmed = value.trim();
|
|
13789
|
+
if (!trimmed) {
|
|
13790
|
+
return null;
|
|
13791
|
+
}
|
|
13792
|
+
if (trimmed.endsWith("ms")) {
|
|
13793
|
+
const milliseconds = Number(trimmed.slice(0, -2));
|
|
13794
|
+
return Number.isFinite(milliseconds) && milliseconds > 0 ? Math.round(milliseconds) : null;
|
|
13795
|
+
}
|
|
13796
|
+
const match = trimmed.match(/^([\d.]+)s$/);
|
|
13797
|
+
if (!match?.[1]) {
|
|
13798
|
+
return null;
|
|
13799
|
+
}
|
|
13800
|
+
const seconds2 = Number(match[1]);
|
|
13801
|
+
return Number.isFinite(seconds2) && seconds2 > 0 ? Math.round(seconds2 * 1e3) : null;
|
|
13802
|
+
}
|
|
13803
|
+
const seconds = typeof value.seconds === "number" ? value.seconds : 0;
|
|
13804
|
+
const nanos = typeof value.nanos === "number" ? value.nanos : 0;
|
|
13805
|
+
if (!Number.isFinite(seconds) || !Number.isFinite(nanos)) {
|
|
13806
|
+
return null;
|
|
13807
|
+
}
|
|
13808
|
+
const totalMs = Math.round(seconds * 1e3 + nanos / 1e6);
|
|
13809
|
+
return totalMs > 0 ? totalMs : null;
|
|
13810
|
+
}
|
|
13811
|
+
function parseRetryDelayFromMessage(message) {
|
|
13812
|
+
const retryMatch = message.match(/Please retry in ([0-9.]+(?:ms|s))/i);
|
|
13813
|
+
if (retryMatch?.[1]) {
|
|
13814
|
+
return parseRetryDelayValue(retryMatch[1]);
|
|
13815
|
+
}
|
|
13816
|
+
const afterMatch = message.match(/after\s+([0-9.]+(?:ms|s))/i);
|
|
13817
|
+
if (afterMatch?.[1]) {
|
|
13818
|
+
return parseRetryDelayValue(afterMatch[1]);
|
|
13819
|
+
}
|
|
13820
|
+
return null;
|
|
13821
|
+
}
|
|
13822
|
+
async function parseErrorBody(response) {
|
|
13823
|
+
let text = "";
|
|
13824
|
+
try {
|
|
13825
|
+
text = await response.clone().text();
|
|
13826
|
+
} catch {
|
|
13827
|
+
return null;
|
|
13828
|
+
}
|
|
13829
|
+
if (!text) {
|
|
13830
|
+
return null;
|
|
13831
|
+
}
|
|
13832
|
+
let parsed;
|
|
13833
|
+
try {
|
|
13834
|
+
parsed = JSON.parse(text);
|
|
13835
|
+
} catch {
|
|
13836
|
+
return null;
|
|
13837
|
+
}
|
|
13838
|
+
const normalized = normalizeErrorEnvelope(parsed);
|
|
13839
|
+
if (!normalized || !isObject2(normalized.error)) {
|
|
13840
|
+
return null;
|
|
13841
|
+
}
|
|
13842
|
+
const error45 = normalized.error;
|
|
13843
|
+
return {
|
|
13844
|
+
message: typeof error45.message === "string" ? error45.message : void 0,
|
|
13845
|
+
details: Array.isArray(error45.details) ? error45.details : void 0
|
|
13846
|
+
};
|
|
13847
|
+
}
|
|
13848
|
+
function isObject2(value) {
|
|
13849
|
+
return !!value && typeof value === "object";
|
|
13850
|
+
}
|
|
13851
|
+
function normalizeErrorEnvelope(parsed) {
|
|
13852
|
+
if (Array.isArray(parsed)) {
|
|
13853
|
+
const first = parsed[0];
|
|
13854
|
+
return isObject2(first) ? first : null;
|
|
13855
|
+
}
|
|
13856
|
+
return isObject2(parsed) ? parsed : null;
|
|
13857
|
+
}
|
|
13858
|
+
|
|
13859
|
+
// src/sdk/retry/helpers.ts
|
|
13860
|
+
var DEFAULT_MAX_ATTEMPTS = 3;
|
|
13861
|
+
var DEFAULT_INITIAL_DELAY_MS = 5e3;
|
|
13862
|
+
var DEFAULT_MAX_DELAY_MS = 3e4;
|
|
13863
|
+
var RETRYABLE_NETWORK_CODES = /* @__PURE__ */ new Set([
|
|
13864
|
+
"ECONNRESET",
|
|
13865
|
+
"ETIMEDOUT",
|
|
13866
|
+
"EPIPE",
|
|
13867
|
+
"ENOTFOUND",
|
|
13868
|
+
"EAI_AGAIN",
|
|
13869
|
+
"ECONNREFUSED",
|
|
13870
|
+
"ERR_SSL_SSLV3_ALERT_BAD_RECORD_MAC",
|
|
13871
|
+
"ERR_SSL_WRONG_VERSION_NUMBER",
|
|
13872
|
+
"ERR_SSL_DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
|
|
13873
|
+
"ERR_SSL_BAD_RECORD_MAC",
|
|
13874
|
+
"EPROTO"
|
|
13875
|
+
]);
|
|
13876
|
+
function canRetryRequest(init) {
|
|
13877
|
+
if (!init?.body) {
|
|
13878
|
+
return true;
|
|
13879
|
+
}
|
|
13880
|
+
const body = init.body;
|
|
13881
|
+
if (typeof body === "string") {
|
|
13882
|
+
return true;
|
|
13883
|
+
}
|
|
13884
|
+
if (typeof URLSearchParams !== "undefined" && body instanceof URLSearchParams) {
|
|
13885
|
+
return true;
|
|
13886
|
+
}
|
|
13887
|
+
if (typeof ArrayBuffer !== "undefined" && body instanceof ArrayBuffer) {
|
|
13888
|
+
return true;
|
|
13889
|
+
}
|
|
13890
|
+
if (typeof ArrayBuffer !== "undefined" && ArrayBuffer.isView(body)) {
|
|
13891
|
+
return true;
|
|
13892
|
+
}
|
|
13893
|
+
if (typeof Blob !== "undefined" && body instanceof Blob) {
|
|
13894
|
+
return true;
|
|
13895
|
+
}
|
|
13896
|
+
return false;
|
|
13897
|
+
}
|
|
13898
|
+
function isRetryableStatus(status) {
|
|
13899
|
+
return status === 429 || status >= 500 && status < 600;
|
|
13900
|
+
}
|
|
13901
|
+
function isRetryableNetworkError(error45) {
|
|
13902
|
+
const code = getNetworkErrorCode(error45);
|
|
13903
|
+
if (code && RETRYABLE_NETWORK_CODES.has(code)) {
|
|
13904
|
+
return true;
|
|
13905
|
+
}
|
|
13906
|
+
return error45 instanceof Error && error45.message.toLowerCase().includes("fetch failed");
|
|
13907
|
+
}
|
|
13908
|
+
async function resolveRetryDelayMs(response, attempt, quotaDelayMs) {
|
|
13909
|
+
const retryAfterMsHeader = parseRetryAfterMs(response.headers.get("retry-after-ms"));
|
|
13910
|
+
if (retryAfterMsHeader !== null) {
|
|
13911
|
+
return clampDelay(retryAfterMsHeader);
|
|
13912
|
+
}
|
|
13913
|
+
const retryAfterHeader = parseRetryAfter(response.headers.get("retry-after"));
|
|
13914
|
+
if (retryAfterHeader !== null) {
|
|
13915
|
+
return clampDelay(retryAfterHeader);
|
|
13916
|
+
}
|
|
13917
|
+
if (quotaDelayMs !== void 0) {
|
|
13918
|
+
return clampDelay(quotaDelayMs);
|
|
13919
|
+
}
|
|
13920
|
+
const bodyDelay = await parseRetryDelayFromBody(response);
|
|
13921
|
+
if (bodyDelay !== null) {
|
|
13922
|
+
return clampDelay(bodyDelay);
|
|
13923
|
+
}
|
|
13924
|
+
return getExponentialDelayWithJitter(attempt);
|
|
13925
|
+
}
|
|
13926
|
+
function getExponentialDelayWithJitter(attempt) {
|
|
13927
|
+
const base = Math.min(DEFAULT_MAX_DELAY_MS, DEFAULT_INITIAL_DELAY_MS * Math.pow(2, attempt - 1));
|
|
13928
|
+
const jitter = base * 0.3 * (Math.random() * 2 - 1);
|
|
13929
|
+
return clampDelay(base + jitter);
|
|
14833
13930
|
}
|
|
14834
|
-
function
|
|
14835
|
-
return
|
|
13931
|
+
function wait2(ms) {
|
|
13932
|
+
return new Promise((resolve) => {
|
|
13933
|
+
setTimeout(resolve, ms);
|
|
13934
|
+
});
|
|
14836
13935
|
}
|
|
14837
|
-
function
|
|
14838
|
-
|
|
13936
|
+
function getNetworkErrorCode(error45) {
|
|
13937
|
+
const readCode = (value) => {
|
|
13938
|
+
if (!value || typeof value !== "object") {
|
|
13939
|
+
return void 0;
|
|
13940
|
+
}
|
|
13941
|
+
if ("code" in value && typeof value.code === "string") {
|
|
13942
|
+
return value.code;
|
|
13943
|
+
}
|
|
13944
|
+
return void 0;
|
|
13945
|
+
};
|
|
13946
|
+
const direct = readCode(error45);
|
|
13947
|
+
if (direct) {
|
|
13948
|
+
return direct;
|
|
13949
|
+
}
|
|
13950
|
+
let cursor = error45;
|
|
13951
|
+
for (let depth = 0; depth < 5; depth += 1) {
|
|
13952
|
+
if (!cursor || typeof cursor !== "object" || !("cause" in cursor)) {
|
|
13953
|
+
break;
|
|
13954
|
+
}
|
|
13955
|
+
cursor = cursor.cause;
|
|
13956
|
+
const code = readCode(cursor);
|
|
13957
|
+
if (code) {
|
|
13958
|
+
return code;
|
|
13959
|
+
}
|
|
13960
|
+
}
|
|
13961
|
+
return void 0;
|
|
14839
13962
|
}
|
|
14840
|
-
function
|
|
14841
|
-
|
|
13963
|
+
function parseRetryAfterMs(value) {
|
|
13964
|
+
if (!value) {
|
|
13965
|
+
return null;
|
|
13966
|
+
}
|
|
13967
|
+
const parsed = Number(value.trim());
|
|
13968
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
13969
|
+
return null;
|
|
13970
|
+
}
|
|
13971
|
+
return Math.round(parsed);
|
|
14842
13972
|
}
|
|
14843
|
-
function
|
|
14844
|
-
|
|
13973
|
+
function parseRetryAfter(value) {
|
|
13974
|
+
if (!value) {
|
|
13975
|
+
return null;
|
|
13976
|
+
}
|
|
13977
|
+
const trimmed = value.trim();
|
|
13978
|
+
if (!trimmed) {
|
|
13979
|
+
return null;
|
|
13980
|
+
}
|
|
13981
|
+
const seconds = Number(trimmed);
|
|
13982
|
+
if (Number.isFinite(seconds)) {
|
|
13983
|
+
return Math.max(0, Math.round(seconds * 1e3));
|
|
13984
|
+
}
|
|
13985
|
+
const parsedDate = Date.parse(trimmed);
|
|
13986
|
+
if (!Number.isNaN(parsedDate)) {
|
|
13987
|
+
return Math.max(0, parsedDate - Date.now());
|
|
13988
|
+
}
|
|
13989
|
+
return null;
|
|
14845
13990
|
}
|
|
14846
|
-
|
|
14847
|
-
|
|
14848
|
-
|
|
14849
|
-
|
|
14850
|
-
|
|
14851
|
-
function tool(input) {
|
|
14852
|
-
return input;
|
|
13991
|
+
function clampDelay(delayMs) {
|
|
13992
|
+
if (!Number.isFinite(delayMs)) {
|
|
13993
|
+
return DEFAULT_MAX_DELAY_MS;
|
|
13994
|
+
}
|
|
13995
|
+
return Math.min(Math.max(0, Math.round(delayMs)), DEFAULT_MAX_DELAY_MS);
|
|
14853
13996
|
}
|
|
14854
|
-
tool.schema = external_exports;
|
|
14855
13997
|
|
|
14856
13998
|
// src/plugin/token.ts
|
|
14857
13999
|
var refreshInFlight = /* @__PURE__ */ new Map();
|
|
@@ -16938,7 +16080,7 @@ function parseGenerativeLanguageRequest(input) {
|
|
|
16938
16080
|
function isRecord(value) {
|
|
16939
16081
|
return !!value && typeof value === "object";
|
|
16940
16082
|
}
|
|
16941
|
-
function
|
|
16083
|
+
function readString(value) {
|
|
16942
16084
|
if (typeof value !== "string") {
|
|
16943
16085
|
return void 0;
|
|
16944
16086
|
}
|
|
@@ -16947,7 +16089,7 @@ function readString2(value) {
|
|
|
16947
16089
|
}
|
|
16948
16090
|
function pickString(...values) {
|
|
16949
16091
|
for (const value of values) {
|
|
16950
|
-
const str =
|
|
16092
|
+
const str = readString(value);
|
|
16951
16093
|
if (str) {
|
|
16952
16094
|
return str;
|
|
16953
16095
|
}
|
|
@@ -16955,7 +16097,7 @@ function pickString(...values) {
|
|
|
16955
16097
|
return void 0;
|
|
16956
16098
|
}
|
|
16957
16099
|
function injectResponseIdFromTrace(body) {
|
|
16958
|
-
const traceId =
|
|
16100
|
+
const traceId = readString(body.traceId);
|
|
16959
16101
|
if (!traceId) {
|
|
16960
16102
|
return body;
|
|
16961
16103
|
}
|
|
@@ -16963,7 +16105,7 @@ function injectResponseIdFromTrace(body) {
|
|
|
16963
16105
|
if (!isRecord(response)) {
|
|
16964
16106
|
return body;
|
|
16965
16107
|
}
|
|
16966
|
-
if (
|
|
16108
|
+
if (readString(response.responseId)) {
|
|
16967
16109
|
return body;
|
|
16968
16110
|
}
|
|
16969
16111
|
return {
|
|
@@ -17050,95 +16192,497 @@ function normalizeRequestPayloadIdentifiers(payload) {
|
|
|
17050
16192
|
stripPromptIdentifierAliases(payload);
|
|
17051
16193
|
return { userPromptId, sessionId, requestId };
|
|
17052
16194
|
}
|
|
17053
|
-
|
|
17054
|
-
// src/sdk/request/openai.ts
|
|
17055
|
-
function transformOpenAIToolCalls(requestPayload) {
|
|
17056
|
-
const messages = requestPayload.messages;
|
|
17057
|
-
if (!messages || !Array.isArray(messages)) {
|
|
17058
|
-
return;
|
|
16195
|
+
|
|
16196
|
+
// src/sdk/request/openai.ts
|
|
16197
|
+
function transformOpenAIToolCalls(requestPayload) {
|
|
16198
|
+
const messages = requestPayload.messages;
|
|
16199
|
+
if (!messages || !Array.isArray(messages)) {
|
|
16200
|
+
return;
|
|
16201
|
+
}
|
|
16202
|
+
for (const message of messages) {
|
|
16203
|
+
if (!message || typeof message !== "object") {
|
|
16204
|
+
continue;
|
|
16205
|
+
}
|
|
16206
|
+
const msgObj = message;
|
|
16207
|
+
const toolCalls = msgObj.tool_calls;
|
|
16208
|
+
if (!toolCalls || !Array.isArray(toolCalls) || toolCalls.length === 0) {
|
|
16209
|
+
continue;
|
|
16210
|
+
}
|
|
16211
|
+
const parts = [];
|
|
16212
|
+
if (typeof msgObj.content === "string" && msgObj.content.length > 0) {
|
|
16213
|
+
parts.push({ text: msgObj.content });
|
|
16214
|
+
}
|
|
16215
|
+
for (const toolCall of toolCalls) {
|
|
16216
|
+
if (!toolCall || typeof toolCall !== "object") {
|
|
16217
|
+
continue;
|
|
16218
|
+
}
|
|
16219
|
+
const fn = toolCall.function;
|
|
16220
|
+
if (!fn || typeof fn !== "object") {
|
|
16221
|
+
continue;
|
|
16222
|
+
}
|
|
16223
|
+
const name = fn.name;
|
|
16224
|
+
const args = parseJsonObject(fn.arguments);
|
|
16225
|
+
const functionCallPart = {
|
|
16226
|
+
name: name ?? "",
|
|
16227
|
+
args
|
|
16228
|
+
};
|
|
16229
|
+
if (typeof toolCall.id === "string" && toolCall.id.length > 0) {
|
|
16230
|
+
functionCallPart.id = toolCall.id;
|
|
16231
|
+
}
|
|
16232
|
+
parts.push({
|
|
16233
|
+
functionCall: functionCallPart,
|
|
16234
|
+
thoughtSignature: "skip_thought_signature_validator"
|
|
16235
|
+
});
|
|
16236
|
+
}
|
|
16237
|
+
msgObj.parts = parts;
|
|
16238
|
+
delete msgObj.tool_calls;
|
|
16239
|
+
delete msgObj.content;
|
|
16240
|
+
}
|
|
16241
|
+
}
|
|
16242
|
+
function addThoughtSignaturesToFunctionCalls(requestPayload) {
|
|
16243
|
+
const processContents = (contents) => {
|
|
16244
|
+
if (!contents || !Array.isArray(contents)) {
|
|
16245
|
+
return;
|
|
16246
|
+
}
|
|
16247
|
+
for (const content of contents) {
|
|
16248
|
+
if (!content || typeof content !== "object") {
|
|
16249
|
+
continue;
|
|
16250
|
+
}
|
|
16251
|
+
const parts = content.parts;
|
|
16252
|
+
if (!parts || !Array.isArray(parts)) {
|
|
16253
|
+
continue;
|
|
16254
|
+
}
|
|
16255
|
+
for (const part of parts) {
|
|
16256
|
+
if (!part || typeof part !== "object") {
|
|
16257
|
+
continue;
|
|
16258
|
+
}
|
|
16259
|
+
const partObj = part;
|
|
16260
|
+
if (partObj.functionCall && !partObj.thoughtSignature) {
|
|
16261
|
+
partObj.thoughtSignature = "skip_thought_signature_validator";
|
|
16262
|
+
}
|
|
16263
|
+
}
|
|
16264
|
+
}
|
|
16265
|
+
};
|
|
16266
|
+
processContents(requestPayload.contents);
|
|
16267
|
+
if (requestPayload.request && typeof requestPayload.request === "object") {
|
|
16268
|
+
processContents(requestPayload.request.contents);
|
|
16269
|
+
}
|
|
16270
|
+
}
|
|
16271
|
+
function parseJsonObject(value) {
|
|
16272
|
+
if (typeof value !== "string") {
|
|
16273
|
+
return {};
|
|
16274
|
+
}
|
|
16275
|
+
try {
|
|
16276
|
+
const parsed = JSON.parse(value);
|
|
16277
|
+
if (parsed && typeof parsed === "object") {
|
|
16278
|
+
return parsed;
|
|
16279
|
+
}
|
|
16280
|
+
return {};
|
|
16281
|
+
} catch {
|
|
16282
|
+
return {};
|
|
16283
|
+
}
|
|
16284
|
+
}
|
|
16285
|
+
|
|
16286
|
+
// src/sdk/request/thinking.ts
|
|
16287
|
+
import "crypto";
|
|
16288
|
+
function createSignatureStore() {
|
|
16289
|
+
const store = /* @__PURE__ */ new Map();
|
|
16290
|
+
return {
|
|
16291
|
+
get: (key) => store.get(key),
|
|
16292
|
+
set: (key, value) => {
|
|
16293
|
+
store.set(key, value);
|
|
16294
|
+
},
|
|
16295
|
+
has: (key) => store.has(key),
|
|
16296
|
+
delete: (key) => {
|
|
16297
|
+
store.delete(key);
|
|
16298
|
+
}
|
|
16299
|
+
};
|
|
16300
|
+
}
|
|
16301
|
+
function createThoughtBuffer() {
|
|
16302
|
+
const buffer = /* @__PURE__ */ new Map();
|
|
16303
|
+
return {
|
|
16304
|
+
get: (index) => buffer.get(index),
|
|
16305
|
+
set: (index, text) => {
|
|
16306
|
+
buffer.set(index, text);
|
|
16307
|
+
},
|
|
16308
|
+
clear: () => buffer.clear()
|
|
16309
|
+
};
|
|
16310
|
+
}
|
|
16311
|
+
var defaultSignatureStore = createSignatureStore();
|
|
16312
|
+
function hashString(str) {
|
|
16313
|
+
let hash2 = 5381;
|
|
16314
|
+
for (let i = 0; i < str.length; i++) {
|
|
16315
|
+
hash2 = (hash2 << 5) + hash2 + str.charCodeAt(i);
|
|
16316
|
+
}
|
|
16317
|
+
return (hash2 >>> 0).toString(16);
|
|
16318
|
+
}
|
|
16319
|
+
function isThinkingPart(part) {
|
|
16320
|
+
if (!part || typeof part !== "object") return false;
|
|
16321
|
+
return part.thought === true || part.type === "thinking" || part.type === "redacted_thinking";
|
|
16322
|
+
}
|
|
16323
|
+
function isFunctionResponsePart(part) {
|
|
16324
|
+
return part && typeof part === "object" && "functionResponse" in part;
|
|
16325
|
+
}
|
|
16326
|
+
function isFunctionCallPart(part) {
|
|
16327
|
+
return part && typeof part === "object" && "functionCall" in part;
|
|
16328
|
+
}
|
|
16329
|
+
function isToolResultMessage(msg) {
|
|
16330
|
+
if (!msg || msg.role !== "user") return false;
|
|
16331
|
+
const parts = msg.parts || [];
|
|
16332
|
+
return parts.some(isFunctionResponsePart);
|
|
16333
|
+
}
|
|
16334
|
+
function messageHasThinking(msg) {
|
|
16335
|
+
if (!msg || typeof msg !== "object") return false;
|
|
16336
|
+
if (Array.isArray(msg.parts)) {
|
|
16337
|
+
return msg.parts.some(isThinkingPart);
|
|
16338
|
+
}
|
|
16339
|
+
if (Array.isArray(msg.content)) {
|
|
16340
|
+
return msg.content.some(
|
|
16341
|
+
(block) => block?.type === "thinking" || block?.type === "redacted_thinking"
|
|
16342
|
+
);
|
|
16343
|
+
}
|
|
16344
|
+
return false;
|
|
16345
|
+
}
|
|
16346
|
+
function messageHasToolCalls(msg) {
|
|
16347
|
+
if (!msg || typeof msg !== "object") return false;
|
|
16348
|
+
if (Array.isArray(msg.parts)) {
|
|
16349
|
+
return msg.parts.some(isFunctionCallPart);
|
|
16350
|
+
}
|
|
16351
|
+
if (Array.isArray(msg.content)) {
|
|
16352
|
+
return msg.content.some((block) => block?.type === "tool_use");
|
|
16353
|
+
}
|
|
16354
|
+
return false;
|
|
16355
|
+
}
|
|
16356
|
+
function analyzeConversationState(contents) {
|
|
16357
|
+
const state = {
|
|
16358
|
+
inToolLoop: false,
|
|
16359
|
+
turnStartIdx: -1,
|
|
16360
|
+
turnHasThinking: false,
|
|
16361
|
+
lastModelIdx: -1,
|
|
16362
|
+
lastModelHasThinking: false,
|
|
16363
|
+
lastModelHasToolCalls: false
|
|
16364
|
+
};
|
|
16365
|
+
if (!Array.isArray(contents) || contents.length === 0) {
|
|
16366
|
+
return state;
|
|
17059
16367
|
}
|
|
17060
|
-
|
|
17061
|
-
|
|
17062
|
-
|
|
16368
|
+
let lastRealUserIdx = -1;
|
|
16369
|
+
for (let i = 0; i < contents.length; i++) {
|
|
16370
|
+
const msg = contents[i];
|
|
16371
|
+
if (msg?.role === "user" && !isToolResultMessage(msg)) {
|
|
16372
|
+
lastRealUserIdx = i;
|
|
17063
16373
|
}
|
|
17064
|
-
|
|
17065
|
-
|
|
17066
|
-
|
|
17067
|
-
|
|
16374
|
+
}
|
|
16375
|
+
for (let i = 0; i < contents.length; i++) {
|
|
16376
|
+
const msg = contents[i];
|
|
16377
|
+
const role = msg?.role;
|
|
16378
|
+
if (role === "model" || role === "assistant") {
|
|
16379
|
+
const hasThinking = messageHasThinking(msg);
|
|
16380
|
+
const hasToolCalls = messageHasToolCalls(msg);
|
|
16381
|
+
if (i > lastRealUserIdx && state.turnStartIdx === -1) {
|
|
16382
|
+
state.turnStartIdx = i;
|
|
16383
|
+
state.turnHasThinking = hasThinking;
|
|
16384
|
+
}
|
|
16385
|
+
state.lastModelIdx = i;
|
|
16386
|
+
state.lastModelHasToolCalls = hasToolCalls;
|
|
16387
|
+
state.lastModelHasThinking = hasThinking;
|
|
17068
16388
|
}
|
|
17069
|
-
|
|
17070
|
-
|
|
17071
|
-
|
|
16389
|
+
}
|
|
16390
|
+
if (contents.length > 0) {
|
|
16391
|
+
const lastMsg = contents[contents.length - 1];
|
|
16392
|
+
if (lastMsg?.role === "user" && isToolResultMessage(lastMsg)) {
|
|
16393
|
+
state.inToolLoop = true;
|
|
17072
16394
|
}
|
|
17073
|
-
|
|
17074
|
-
|
|
17075
|
-
|
|
17076
|
-
|
|
17077
|
-
|
|
17078
|
-
|
|
17079
|
-
|
|
16395
|
+
}
|
|
16396
|
+
return state;
|
|
16397
|
+
}
|
|
16398
|
+
function countTrailingToolResults(contents) {
|
|
16399
|
+
let count = 0;
|
|
16400
|
+
for (let i = contents.length - 1; i >= 0; i--) {
|
|
16401
|
+
const msg = contents[i];
|
|
16402
|
+
if (msg?.role === "user") {
|
|
16403
|
+
const parts = msg.parts || [];
|
|
16404
|
+
const functionResponses = parts.filter(isFunctionResponsePart);
|
|
16405
|
+
if (functionResponses.length > 0) {
|
|
16406
|
+
count += functionResponses.length;
|
|
16407
|
+
} else {
|
|
16408
|
+
break;
|
|
17080
16409
|
}
|
|
17081
|
-
|
|
17082
|
-
|
|
17083
|
-
|
|
17084
|
-
|
|
17085
|
-
|
|
16410
|
+
} else if (msg?.role === "model" || msg?.role === "assistant") {
|
|
16411
|
+
break;
|
|
16412
|
+
}
|
|
16413
|
+
}
|
|
16414
|
+
return count;
|
|
16415
|
+
}
|
|
16416
|
+
function closeToolLoopForThinking(contents) {
|
|
16417
|
+
const strippedContents = contents;
|
|
16418
|
+
const toolResultCount = countTrailingToolResults(strippedContents);
|
|
16419
|
+
let syntheticModelContent;
|
|
16420
|
+
if (toolResultCount === 0) {
|
|
16421
|
+
syntheticModelContent = "[Processing prev ctx.]";
|
|
16422
|
+
} else if (toolResultCount === 1) {
|
|
16423
|
+
syntheticModelContent = "[Tool exec completed.]";
|
|
16424
|
+
} else {
|
|
16425
|
+
syntheticModelContent = `[${toolResultCount} tool executions completed.]`;
|
|
16426
|
+
}
|
|
16427
|
+
const syntheticModel = {
|
|
16428
|
+
role: "model",
|
|
16429
|
+
parts: [{ text: syntheticModelContent }]
|
|
16430
|
+
};
|
|
16431
|
+
const syntheticUser = {
|
|
16432
|
+
role: "user",
|
|
16433
|
+
parts: [{ text: "[Continue]" }]
|
|
16434
|
+
};
|
|
16435
|
+
return [...strippedContents, syntheticModel, syntheticUser];
|
|
16436
|
+
}
|
|
16437
|
+
function needsThinkingRecovery(state) {
|
|
16438
|
+
return state.inToolLoop && !state.turnHasThinking;
|
|
16439
|
+
}
|
|
16440
|
+
function deduplicateThinkingText(response, sentBuffer, displayedThinkingHashes) {
|
|
16441
|
+
if (!response || typeof response !== "object") return response;
|
|
16442
|
+
const resp = response;
|
|
16443
|
+
if (Array.isArray(resp.candidates)) {
|
|
16444
|
+
const newCandidates = resp.candidates.map((candidate, index) => {
|
|
16445
|
+
const cand = candidate;
|
|
16446
|
+
if (!cand?.content) return candidate;
|
|
16447
|
+
const content = cand.content;
|
|
16448
|
+
if (!Array.isArray(content.parts)) return candidate;
|
|
16449
|
+
const newParts = content.parts.map((part) => {
|
|
16450
|
+
const p = part;
|
|
16451
|
+
if (p.thought === true || p.type === "thinking") {
|
|
16452
|
+
const fullText = p.text || p.thinking || "";
|
|
16453
|
+
if (displayedThinkingHashes) {
|
|
16454
|
+
const hash2 = hashString(fullText);
|
|
16455
|
+
if (displayedThinkingHashes.has(hash2)) {
|
|
16456
|
+
sentBuffer.set(index, fullText);
|
|
16457
|
+
return null;
|
|
16458
|
+
}
|
|
16459
|
+
displayedThinkingHashes.add(hash2);
|
|
16460
|
+
}
|
|
16461
|
+
const sentText = sentBuffer.get(index) ?? "";
|
|
16462
|
+
if (fullText.startsWith(sentText)) {
|
|
16463
|
+
const delta = fullText.slice(sentText.length);
|
|
16464
|
+
sentBuffer.set(index, fullText);
|
|
16465
|
+
if (delta) {
|
|
16466
|
+
return { ...p, text: delta, thinking: delta };
|
|
16467
|
+
}
|
|
16468
|
+
return null;
|
|
16469
|
+
}
|
|
16470
|
+
sentBuffer.set(index, fullText);
|
|
16471
|
+
return part;
|
|
16472
|
+
}
|
|
16473
|
+
return part;
|
|
16474
|
+
});
|
|
16475
|
+
const filteredParts = newParts.filter((p) => p !== null);
|
|
16476
|
+
return {
|
|
16477
|
+
...cand,
|
|
16478
|
+
content: { ...content, parts: filteredParts }
|
|
17086
16479
|
};
|
|
17087
|
-
|
|
17088
|
-
|
|
16480
|
+
});
|
|
16481
|
+
return { ...resp, candidates: newCandidates };
|
|
16482
|
+
}
|
|
16483
|
+
if (Array.isArray(resp.content)) {
|
|
16484
|
+
let thinkingIndex = 0;
|
|
16485
|
+
const newContent = resp.content.map((block) => {
|
|
16486
|
+
const b = block;
|
|
16487
|
+
if (b?.type === "thinking") {
|
|
16488
|
+
const fullText = b.thinking || b.text || "";
|
|
16489
|
+
if (displayedThinkingHashes) {
|
|
16490
|
+
const hash2 = hashString(fullText);
|
|
16491
|
+
if (displayedThinkingHashes.has(hash2)) {
|
|
16492
|
+
sentBuffer.set(thinkingIndex, fullText);
|
|
16493
|
+
thinkingIndex++;
|
|
16494
|
+
return null;
|
|
16495
|
+
}
|
|
16496
|
+
displayedThinkingHashes.add(hash2);
|
|
16497
|
+
}
|
|
16498
|
+
const sentText = sentBuffer.get(thinkingIndex) ?? "";
|
|
16499
|
+
if (fullText.startsWith(sentText)) {
|
|
16500
|
+
const delta = fullText.slice(sentText.length);
|
|
16501
|
+
sentBuffer.set(thinkingIndex, fullText);
|
|
16502
|
+
thinkingIndex++;
|
|
16503
|
+
if (delta) {
|
|
16504
|
+
return { ...b, thinking: delta, text: delta };
|
|
16505
|
+
}
|
|
16506
|
+
return null;
|
|
16507
|
+
}
|
|
16508
|
+
sentBuffer.set(thinkingIndex, fullText);
|
|
16509
|
+
thinkingIndex++;
|
|
16510
|
+
return block;
|
|
17089
16511
|
}
|
|
17090
|
-
|
|
17091
|
-
|
|
17092
|
-
|
|
17093
|
-
|
|
16512
|
+
return block;
|
|
16513
|
+
});
|
|
16514
|
+
const filteredContent = newContent.filter((b) => b !== null);
|
|
16515
|
+
if (filteredContent.length === 0) {
|
|
16516
|
+
return { ...resp, content: [] };
|
|
17094
16517
|
}
|
|
17095
|
-
|
|
17096
|
-
delete msgObj.tool_calls;
|
|
17097
|
-
delete msgObj.content;
|
|
16518
|
+
return { ...resp, content: filteredContent };
|
|
17098
16519
|
}
|
|
16520
|
+
return response;
|
|
17099
16521
|
}
|
|
17100
|
-
function
|
|
17101
|
-
|
|
17102
|
-
|
|
17103
|
-
|
|
17104
|
-
|
|
17105
|
-
|
|
17106
|
-
if (!content
|
|
17107
|
-
|
|
17108
|
-
|
|
17109
|
-
|
|
17110
|
-
|
|
17111
|
-
|
|
17112
|
-
|
|
17113
|
-
|
|
17114
|
-
|
|
17115
|
-
|
|
16522
|
+
function cacheThinkingSignaturesFromResponse(response, signatureSessionKey, signatureStore, thoughtBuffer, onCacheSignature) {
|
|
16523
|
+
if (!response || typeof response !== "object") return;
|
|
16524
|
+
const resp = response;
|
|
16525
|
+
if (Array.isArray(resp.candidates)) {
|
|
16526
|
+
resp.candidates.forEach((candidate, index) => {
|
|
16527
|
+
const cand = candidate;
|
|
16528
|
+
if (!cand?.content) return;
|
|
16529
|
+
const content = cand.content;
|
|
16530
|
+
if (!Array.isArray(content.parts)) return;
|
|
16531
|
+
content.parts.forEach((part) => {
|
|
16532
|
+
const p = part;
|
|
16533
|
+
if (p.thought === true || p.type === "thinking") {
|
|
16534
|
+
const text = p.text || p.thinking || "";
|
|
16535
|
+
if (text) {
|
|
16536
|
+
const current = thoughtBuffer.get(index) ?? "";
|
|
16537
|
+
thoughtBuffer.set(index, current + text);
|
|
16538
|
+
}
|
|
17116
16539
|
}
|
|
17117
|
-
|
|
17118
|
-
|
|
17119
|
-
|
|
16540
|
+
if (p.thoughtSignature) {
|
|
16541
|
+
const fullText = thoughtBuffer.get(index) ?? "";
|
|
16542
|
+
if (fullText) {
|
|
16543
|
+
const signature = p.thoughtSignature;
|
|
16544
|
+
onCacheSignature?.(signatureSessionKey, fullText, signature);
|
|
16545
|
+
signatureStore.set(signatureSessionKey, { text: fullText, signature });
|
|
16546
|
+
}
|
|
16547
|
+
}
|
|
16548
|
+
});
|
|
16549
|
+
});
|
|
16550
|
+
}
|
|
16551
|
+
if (Array.isArray(resp.content)) {
|
|
16552
|
+
const CLAUDE_BUFFER_KEY = 0;
|
|
16553
|
+
resp.content.forEach((block) => {
|
|
16554
|
+
const b = block;
|
|
16555
|
+
if (b?.type === "thinking") {
|
|
16556
|
+
const text = b.thinking || b.text || "";
|
|
16557
|
+
if (text) {
|
|
16558
|
+
const current = thoughtBuffer.get(CLAUDE_BUFFER_KEY) ?? "";
|
|
16559
|
+
thoughtBuffer.set(CLAUDE_BUFFER_KEY, current + text);
|
|
16560
|
+
}
|
|
16561
|
+
}
|
|
16562
|
+
if (b?.signature) {
|
|
16563
|
+
const fullText = thoughtBuffer.get(CLAUDE_BUFFER_KEY) ?? "";
|
|
16564
|
+
if (fullText) {
|
|
16565
|
+
const signature = b.signature;
|
|
16566
|
+
onCacheSignature?.(signatureSessionKey, fullText, signature);
|
|
16567
|
+
signatureStore.set(signatureSessionKey, { text: fullText, signature });
|
|
17120
16568
|
}
|
|
17121
16569
|
}
|
|
17122
|
-
}
|
|
17123
|
-
};
|
|
17124
|
-
processContents(requestPayload.contents);
|
|
17125
|
-
if (requestPayload.request && typeof requestPayload.request === "object") {
|
|
17126
|
-
processContents(requestPayload.request.contents);
|
|
16570
|
+
});
|
|
17127
16571
|
}
|
|
17128
16572
|
}
|
|
17129
|
-
function
|
|
17130
|
-
|
|
17131
|
-
|
|
16573
|
+
function transformSseEvent(eventText, signatureStore, thoughtBuffer, sentThinkingBuffer, callbacks, options, debugState) {
|
|
16574
|
+
const dataLines = [];
|
|
16575
|
+
const lines = eventText.split(/\r?\n/);
|
|
16576
|
+
let isDataEvent = false;
|
|
16577
|
+
for (const line of lines) {
|
|
16578
|
+
if (line.startsWith("data:")) {
|
|
16579
|
+
isDataEvent = true;
|
|
16580
|
+
dataLines.push(line.slice(5).trim());
|
|
16581
|
+
}
|
|
16582
|
+
}
|
|
16583
|
+
if (!isDataEvent) {
|
|
16584
|
+
return eventText;
|
|
16585
|
+
}
|
|
16586
|
+
const jsonString = dataLines.join("\n").trim();
|
|
16587
|
+
if (!jsonString) {
|
|
16588
|
+
return eventText;
|
|
17132
16589
|
}
|
|
17133
16590
|
try {
|
|
17134
|
-
const parsed = JSON.parse(
|
|
17135
|
-
if (parsed && typeof parsed === "object") {
|
|
17136
|
-
|
|
16591
|
+
const parsed = JSON.parse(jsonString);
|
|
16592
|
+
if (parsed && typeof parsed === "object" && parsed.response !== void 0) {
|
|
16593
|
+
if (options.cacheSignatures && options.signatureSessionKey) {
|
|
16594
|
+
cacheThinkingSignaturesFromResponse(
|
|
16595
|
+
parsed.response,
|
|
16596
|
+
options.signatureSessionKey,
|
|
16597
|
+
signatureStore,
|
|
16598
|
+
thoughtBuffer,
|
|
16599
|
+
callbacks.onCacheSignature
|
|
16600
|
+
);
|
|
16601
|
+
}
|
|
16602
|
+
let response = deduplicateThinkingText(
|
|
16603
|
+
parsed.response,
|
|
16604
|
+
sentThinkingBuffer,
|
|
16605
|
+
options.displayedThinkingHashes
|
|
16606
|
+
);
|
|
16607
|
+
if (options.debugText && callbacks.onInjectDebug && !debugState.injected) {
|
|
16608
|
+
response = callbacks.onInjectDebug(response, options.debugText);
|
|
16609
|
+
debugState.injected = true;
|
|
16610
|
+
}
|
|
16611
|
+
const transformed = callbacks.transformThinkingParts ? callbacks.transformThinkingParts(response) : response;
|
|
16612
|
+
return `data: ${JSON.stringify(transformed)}`;
|
|
17137
16613
|
}
|
|
17138
|
-
|
|
17139
|
-
} catch {
|
|
17140
|
-
return {};
|
|
16614
|
+
} catch (_) {
|
|
17141
16615
|
}
|
|
16616
|
+
return eventText;
|
|
16617
|
+
}
|
|
16618
|
+
function createStreamingTransformer(signatureStore, callbacks, options = {}) {
|
|
16619
|
+
const decoder2 = new TextDecoder();
|
|
16620
|
+
const encoder2 = new TextEncoder();
|
|
16621
|
+
let buffer = "";
|
|
16622
|
+
const thoughtBuffer = createThoughtBuffer();
|
|
16623
|
+
const sentThinkingBuffer = createThoughtBuffer();
|
|
16624
|
+
const debugState = { injected: false };
|
|
16625
|
+
let hasSeenUsageMetadata = false;
|
|
16626
|
+
const displayedThinkingHashes = options.displayedThinkingHashes ?? /* @__PURE__ */ new Set();
|
|
16627
|
+
const mergedOptions = { ...options, displayedThinkingHashes };
|
|
16628
|
+
return new TransformStream({
|
|
16629
|
+
transform(chunk, controller) {
|
|
16630
|
+
buffer += decoder2.decode(chunk, { stream: true });
|
|
16631
|
+
const events = buffer.split(/\r?\n\r?\n/);
|
|
16632
|
+
buffer = events.pop() || "";
|
|
16633
|
+
for (const event of events) {
|
|
16634
|
+
if (!event.trim()) continue;
|
|
16635
|
+
if (event.includes("usageMetadata")) {
|
|
16636
|
+
hasSeenUsageMetadata = true;
|
|
16637
|
+
}
|
|
16638
|
+
const transformedEvent = transformSseEvent(
|
|
16639
|
+
event,
|
|
16640
|
+
signatureStore,
|
|
16641
|
+
thoughtBuffer,
|
|
16642
|
+
sentThinkingBuffer,
|
|
16643
|
+
callbacks,
|
|
16644
|
+
mergedOptions,
|
|
16645
|
+
debugState
|
|
16646
|
+
);
|
|
16647
|
+
controller.enqueue(encoder2.encode(transformedEvent + "\n\n"));
|
|
16648
|
+
}
|
|
16649
|
+
},
|
|
16650
|
+
flush(controller) {
|
|
16651
|
+
buffer += decoder2.decode();
|
|
16652
|
+
if (buffer.trim()) {
|
|
16653
|
+
if (buffer.includes("usageMetadata")) {
|
|
16654
|
+
hasSeenUsageMetadata = true;
|
|
16655
|
+
}
|
|
16656
|
+
const transformedEvent = transformSseEvent(
|
|
16657
|
+
buffer,
|
|
16658
|
+
signatureStore,
|
|
16659
|
+
thoughtBuffer,
|
|
16660
|
+
sentThinkingBuffer,
|
|
16661
|
+
callbacks,
|
|
16662
|
+
mergedOptions,
|
|
16663
|
+
debugState
|
|
16664
|
+
);
|
|
16665
|
+
controller.enqueue(encoder2.encode(transformedEvent + "\n\n"));
|
|
16666
|
+
}
|
|
16667
|
+
if (!hasSeenUsageMetadata) {
|
|
16668
|
+
const syntheticUsage = {
|
|
16669
|
+
candidates: [
|
|
16670
|
+
{
|
|
16671
|
+
finishReason: "STOP"
|
|
16672
|
+
}
|
|
16673
|
+
],
|
|
16674
|
+
usageMetadata: {
|
|
16675
|
+
promptTokenCount: 0,
|
|
16676
|
+
candidatesTokenCount: 0,
|
|
16677
|
+
totalTokenCount: 0
|
|
16678
|
+
}
|
|
16679
|
+
};
|
|
16680
|
+
controller.enqueue(encoder2.encode(`data: ${JSON.stringify(syntheticUsage)}
|
|
16681
|
+
|
|
16682
|
+
`));
|
|
16683
|
+
}
|
|
16684
|
+
}
|
|
16685
|
+
});
|
|
17142
16686
|
}
|
|
17143
16687
|
|
|
17144
16688
|
// src/sdk/request/prepare.ts
|
|
@@ -17251,13 +16795,8 @@ function transformRequestBody(body, projectId, effectiveModel, requestedModel, t
|
|
|
17251
16795
|
let contents2 = requestPayloadInside.contents;
|
|
17252
16796
|
injectMissingToolCallIds(contents2);
|
|
17253
16797
|
fixOrphanedFunctionResponses(contents2);
|
|
17254
|
-
const
|
|
17255
|
-
|
|
17256
|
-
if (sessionId2 && tracker) {
|
|
17257
|
-
const state = tracker.getState(sessionId2) ?? tracker.recoverFromContents(sessionId2, contents2);
|
|
17258
|
-
needsRecovery = state.inToolLoop && !state.turnHasThinking;
|
|
17259
|
-
}
|
|
17260
|
-
if (needsRecovery) {
|
|
16798
|
+
const state = analyzeConversationState(contents2);
|
|
16799
|
+
if (needsThinkingRecovery(state)) {
|
|
17261
16800
|
contents2 = closeToolLoopForThinking(contents2);
|
|
17262
16801
|
}
|
|
17263
16802
|
contents2 = normalizeContentsSequence(contents2);
|
|
@@ -17285,13 +16824,8 @@ function transformRequestBody(body, projectId, effectiveModel, requestedModel, t
|
|
|
17285
16824
|
if (Array.isArray(contents)) {
|
|
17286
16825
|
injectMissingToolCallIds(contents);
|
|
17287
16826
|
fixOrphanedFunctionResponses(contents);
|
|
17288
|
-
const
|
|
17289
|
-
|
|
17290
|
-
if (sessionId && tracker) {
|
|
17291
|
-
const state = tracker.getState(sessionId) ?? tracker.recoverFromContents(sessionId, contents);
|
|
17292
|
-
needsRecovery = state.inToolLoop && !state.turnHasThinking;
|
|
17293
|
-
}
|
|
17294
|
-
if (needsRecovery) {
|
|
16827
|
+
const state = analyzeConversationState(contents);
|
|
16828
|
+
if (needsThinkingRecovery(state)) {
|
|
17295
16829
|
contents = closeToolLoopForThinking(contents);
|
|
17296
16830
|
}
|
|
17297
16831
|
contents = normalizeContentsSequence(contents);
|
|
@@ -17676,17 +17210,6 @@ function transformStreamingPayloadStream(stream, sessionId, chatLogger) {
|
|
|
17676
17210
|
onCacheSignature: (sessionKey, text, signature) => {
|
|
17677
17211
|
cacheSignature(sessionKey, text, signature);
|
|
17678
17212
|
},
|
|
17679
|
-
onTurnStateUpdate: (sessionKey, state) => {
|
|
17680
|
-
const tracker = getTurnStateTracker();
|
|
17681
|
-
if (tracker) {
|
|
17682
|
-
tracker.updateAfterResponse(sessionKey, {
|
|
17683
|
-
inToolLoop: state.lastModelHasToolCalls,
|
|
17684
|
-
turnHasThinking: state.turnHasThinking,
|
|
17685
|
-
lastModelHasThinking: state.turnHasThinking,
|
|
17686
|
-
lastModelHasToolCalls: state.lastModelHasToolCalls
|
|
17687
|
-
});
|
|
17688
|
-
}
|
|
17689
|
-
},
|
|
17690
17213
|
transformThinkingParts: (response) => {
|
|
17691
17214
|
if (response && typeof response === "object") {
|
|
17692
17215
|
return injectResponseIdFromTrace(response);
|
|
@@ -17709,20 +17232,20 @@ function transformStreamingPayloadStream(stream, sessionId, chatLogger) {
|
|
|
17709
17232
|
}
|
|
17710
17233
|
|
|
17711
17234
|
// src/sdk/chat-logger.ts
|
|
17712
|
-
import { createWriteStream, existsSync as
|
|
17713
|
-
import { join as
|
|
17235
|
+
import { createWriteStream, existsSync as existsSync2, mkdirSync as mkdirSync2 } from "fs";
|
|
17236
|
+
import { join as join2 } from "path";
|
|
17714
17237
|
import { cwd } from "process";
|
|
17715
17238
|
function createChatLogger() {
|
|
17716
17239
|
if (process.env.AGY_LOG !== "1") {
|
|
17717
17240
|
return null;
|
|
17718
17241
|
}
|
|
17719
17242
|
try {
|
|
17720
|
-
const logDir =
|
|
17721
|
-
if (!
|
|
17722
|
-
|
|
17243
|
+
const logDir = join2(cwd(), "agy_chat_log");
|
|
17244
|
+
if (!existsSync2(logDir)) {
|
|
17245
|
+
mkdirSync2(logDir, { recursive: true });
|
|
17723
17246
|
}
|
|
17724
17247
|
const timestamp = Date.now();
|
|
17725
|
-
const logFile =
|
|
17248
|
+
const logFile = join2(logDir, `${timestamp}.log`);
|
|
17726
17249
|
const stream = createWriteStream(logFile, { flags: "w", encoding: "utf8" });
|
|
17727
17250
|
return new ChatLoggerImpl(stream);
|
|
17728
17251
|
} catch (error45) {
|
|
@@ -17824,6 +17347,126 @@ var ChatLoggerImpl = class {
|
|
|
17824
17347
|
}
|
|
17825
17348
|
};
|
|
17826
17349
|
|
|
17350
|
+
// src/sdk/retry/index.ts
|
|
17351
|
+
var retryCooldownByKey = /* @__PURE__ */ new Map();
|
|
17352
|
+
var MODEL_CAPACITY_COOLDOWN_MS = 8e3;
|
|
17353
|
+
async function fetchWithRetry(input, init) {
|
|
17354
|
+
if (!canRetryRequest(init)) {
|
|
17355
|
+
return agyFetch(input, init);
|
|
17356
|
+
}
|
|
17357
|
+
const retryInit = cloneRetryableInit(init);
|
|
17358
|
+
const throttleKey = buildRetryThrottleKey(input, retryInit);
|
|
17359
|
+
await waitForRetryCooldown(throttleKey, retryInit.signal);
|
|
17360
|
+
let attempt = 1;
|
|
17361
|
+
const url2 = readRequestUrl(input);
|
|
17362
|
+
while (attempt <= DEFAULT_MAX_ATTEMPTS) {
|
|
17363
|
+
let response;
|
|
17364
|
+
try {
|
|
17365
|
+
response = await agyFetch(input, retryInit);
|
|
17366
|
+
} catch (error45) {
|
|
17367
|
+
if (attempt >= DEFAULT_MAX_ATTEMPTS || !isRetryableNetworkError(error45)) {
|
|
17368
|
+
throw error45;
|
|
17369
|
+
}
|
|
17370
|
+
if (retryInit.signal?.aborted) {
|
|
17371
|
+
throw error45;
|
|
17372
|
+
}
|
|
17373
|
+
const delayMs2 = getExponentialDelayWithJitter(attempt);
|
|
17374
|
+
await wait2(delayMs2);
|
|
17375
|
+
attempt += 1;
|
|
17376
|
+
continue;
|
|
17377
|
+
}
|
|
17378
|
+
if (!isRetryableStatus(response.status)) {
|
|
17379
|
+
return response;
|
|
17380
|
+
}
|
|
17381
|
+
const quotaContext = response.status === 429 ? await classifyQuotaResponse(response) : null;
|
|
17382
|
+
if (response.status === 429 && quotaContext?.terminal) {
|
|
17383
|
+
if (quotaContext.reason === "MODEL_CAPACITY_EXHAUSTED") {
|
|
17384
|
+
const cooldownMs = quotaContext.retryDelayMs ?? MODEL_CAPACITY_COOLDOWN_MS;
|
|
17385
|
+
setRetryCooldown(throttleKey, cooldownMs);
|
|
17386
|
+
}
|
|
17387
|
+
return response;
|
|
17388
|
+
}
|
|
17389
|
+
if (attempt >= DEFAULT_MAX_ATTEMPTS || retryInit.signal?.aborted) {
|
|
17390
|
+
return response;
|
|
17391
|
+
}
|
|
17392
|
+
const delayMs = await resolveRetryDelayMs(response, attempt, quotaContext?.retryDelayMs);
|
|
17393
|
+
if (delayMs > 0 && response.status === 429) {
|
|
17394
|
+
setRetryCooldown(throttleKey, delayMs);
|
|
17395
|
+
}
|
|
17396
|
+
if (delayMs > 0) {
|
|
17397
|
+
await wait2(delayMs);
|
|
17398
|
+
}
|
|
17399
|
+
attempt += 1;
|
|
17400
|
+
}
|
|
17401
|
+
return agyFetch(input, retryInit);
|
|
17402
|
+
}
|
|
17403
|
+
function cloneRetryableInit(init) {
|
|
17404
|
+
if (!init) {
|
|
17405
|
+
return {};
|
|
17406
|
+
}
|
|
17407
|
+
return {
|
|
17408
|
+
...init,
|
|
17409
|
+
headers: new Headers(init.headers ?? {})
|
|
17410
|
+
};
|
|
17411
|
+
}
|
|
17412
|
+
function buildRetryThrottleKey(input, init) {
|
|
17413
|
+
const url2 = readRequestUrl(input);
|
|
17414
|
+
const body = typeof init.body === "string" ? safeParseBody(init.body) : null;
|
|
17415
|
+
const project = readString2(body?.project);
|
|
17416
|
+
const model = readString2(body?.model);
|
|
17417
|
+
return `${url2}|${project ?? ""}|${model ?? ""}`;
|
|
17418
|
+
}
|
|
17419
|
+
async function waitForRetryCooldown(key, signal) {
|
|
17420
|
+
const until = retryCooldownByKey.get(key);
|
|
17421
|
+
if (!until) {
|
|
17422
|
+
return;
|
|
17423
|
+
}
|
|
17424
|
+
const remaining = until - Date.now();
|
|
17425
|
+
if (remaining <= 0) {
|
|
17426
|
+
retryCooldownByKey.delete(key);
|
|
17427
|
+
return;
|
|
17428
|
+
}
|
|
17429
|
+
if (signal?.aborted) {
|
|
17430
|
+
return;
|
|
17431
|
+
}
|
|
17432
|
+
await wait2(remaining);
|
|
17433
|
+
retryCooldownByKey.delete(key);
|
|
17434
|
+
}
|
|
17435
|
+
function setRetryCooldown(key, delayMs) {
|
|
17436
|
+
const next = Date.now() + delayMs;
|
|
17437
|
+
const current = retryCooldownByKey.get(key) ?? 0;
|
|
17438
|
+
retryCooldownByKey.set(key, Math.max(current, next));
|
|
17439
|
+
}
|
|
17440
|
+
function readRequestUrl(input) {
|
|
17441
|
+
if (typeof input === "string") {
|
|
17442
|
+
return input;
|
|
17443
|
+
}
|
|
17444
|
+
if (input instanceof URL) {
|
|
17445
|
+
return input.toString();
|
|
17446
|
+
}
|
|
17447
|
+
const request = input;
|
|
17448
|
+
if (request.url) {
|
|
17449
|
+
return request.url;
|
|
17450
|
+
}
|
|
17451
|
+
return input.toString();
|
|
17452
|
+
}
|
|
17453
|
+
function safeParseBody(body) {
|
|
17454
|
+
if (!body) {
|
|
17455
|
+
return null;
|
|
17456
|
+
}
|
|
17457
|
+
try {
|
|
17458
|
+
const parsed = JSON.parse(body);
|
|
17459
|
+
if (parsed && typeof parsed === "object") {
|
|
17460
|
+
return parsed;
|
|
17461
|
+
}
|
|
17462
|
+
} catch {
|
|
17463
|
+
}
|
|
17464
|
+
return null;
|
|
17465
|
+
}
|
|
17466
|
+
function readString2(value) {
|
|
17467
|
+
return typeof value === "string" && value.trim() ? value : void 0;
|
|
17468
|
+
}
|
|
17469
|
+
|
|
17827
17470
|
// src/plugin.ts
|
|
17828
17471
|
var AGY_QUOTA_COMMAND = "agyquota";
|
|
17829
17472
|
var AGY_QUOTA_COMMAND_TEMPLATE = `Retrieve Agy Code Assist quota usage for the current authenticated account.
|
|
@@ -18059,26 +17702,12 @@ var AgyCLIOAuthPlugin = async ({ client }) => {
|
|
|
18059
17702
|
normalizeProviderModelCosts(provider);
|
|
18060
17703
|
return STATIC_MODELS;
|
|
18061
17704
|
};
|
|
18062
|
-
|
|
18063
|
-
|
|
18064
|
-
|
|
18065
|
-
|
|
18066
|
-
|
|
18067
|
-
|
|
18068
|
-
});
|
|
18069
|
-
} catch (e) {
|
|
18070
|
-
console.warn(`[Agy Auth] initDiskSignatureCache failed, running without signature disk cache: ${e instanceof Error ? e.message : e}`);
|
|
18071
|
-
}
|
|
18072
|
-
try {
|
|
18073
|
-
initTurnStateTracker();
|
|
18074
|
-
} catch (e) {
|
|
18075
|
-
console.warn(`[Agy Auth] initTurnStateTracker failed, running without turn-state tracking: ${e instanceof Error ? e.message : e}`);
|
|
18076
|
-
}
|
|
18077
|
-
try {
|
|
18078
|
-
initCooldownPersistence();
|
|
18079
|
-
} catch (e) {
|
|
18080
|
-
console.warn(`[Agy Auth] initCooldownPersistence failed, running without cooldown disk persistence: ${e instanceof Error ? e.message : e}`);
|
|
18081
|
-
}
|
|
17705
|
+
initDiskSignatureCache({
|
|
17706
|
+
enabled: true,
|
|
17707
|
+
memory_ttl_seconds: 3600,
|
|
17708
|
+
disk_ttl_seconds: 86400,
|
|
17709
|
+
write_interval_seconds: 30
|
|
17710
|
+
});
|
|
18082
17711
|
const resolveLatestConfiguredProjectId = async (provider) => {
|
|
18083
17712
|
const configProjectId = await resolveConfiguredProjectIdFromClient(client) ?? latestAgyConfiguredProjectId;
|
|
18084
17713
|
const resolvedProjectId = resolveConfiguredProjectId({
|
|
@@ -18351,10 +17980,7 @@ function toUrlString(value) {
|
|
|
18351
17980
|
}
|
|
18352
17981
|
|
|
18353
17982
|
// index.ts
|
|
18354
|
-
var index_default =
|
|
18355
|
-
id: "@anthonyhaussman/opencode-agy-auth",
|
|
18356
|
-
server: AgyCLIOAuthPlugin
|
|
18357
|
-
};
|
|
17983
|
+
var index_default = AgyCLIOAuthPlugin;
|
|
18358
17984
|
export {
|
|
18359
17985
|
AgyCLIOAuthPlugin,
|
|
18360
17986
|
GoogleOAuthPlugin,
|