@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/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: () => isObject2,
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 isObject2(data) {
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 (isObject2(o) === false)
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 (isObject2(prot) === false)
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 = isObject2;
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 = isObject2;
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 (!isObject2(input)) {
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 number3(params) {
14835
- return _coercedNumber(ZodNumber, params);
13931
+ function wait2(ms) {
13932
+ return new Promise((resolve) => {
13933
+ setTimeout(resolve, ms);
13934
+ });
14836
13935
  }
14837
- function boolean3(params) {
14838
- return _coercedBoolean(ZodBoolean, params);
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 bigint3(params) {
14841
- return _coercedBigint(ZodBigInt, params);
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 date4(params) {
14844
- return _coercedDate(ZodDate, params);
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
- // node_modules/zod/v4/classic/external.js
14848
- config(en_default());
14849
-
14850
- // node_modules/@opencode-ai/plugin/dist/tool.js
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 readString2(value) {
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 = readString2(value);
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 = readString2(body.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 (readString2(response.responseId)) {
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
- for (const message of messages) {
17061
- if (!message || typeof message !== "object") {
17062
- continue;
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
- const msgObj = message;
17065
- const toolCalls = msgObj.tool_calls;
17066
- if (!toolCalls || !Array.isArray(toolCalls) || toolCalls.length === 0) {
17067
- continue;
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
- const parts = [];
17070
- if (typeof msgObj.content === "string" && msgObj.content.length > 0) {
17071
- parts.push({ text: msgObj.content });
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
- for (const toolCall of toolCalls) {
17074
- if (!toolCall || typeof toolCall !== "object") {
17075
- continue;
17076
- }
17077
- const fn = toolCall.function;
17078
- if (!fn || typeof fn !== "object") {
17079
- continue;
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
- const name = fn.name;
17082
- const args = parseJsonObject(fn.arguments);
17083
- const functionCallPart = {
17084
- name: name ?? "",
17085
- args
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
- if (typeof toolCall.id === "string" && toolCall.id.length > 0) {
17088
- functionCallPart.id = toolCall.id;
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
- parts.push({
17091
- functionCall: functionCallPart,
17092
- thoughtSignature: "skip_thought_signature_validator"
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
- msgObj.parts = parts;
17096
- delete msgObj.tool_calls;
17097
- delete msgObj.content;
16518
+ return { ...resp, content: filteredContent };
17098
16519
  }
16520
+ return response;
17099
16521
  }
17100
- function addThoughtSignaturesToFunctionCalls(requestPayload) {
17101
- const processContents = (contents) => {
17102
- if (!contents || !Array.isArray(contents)) {
17103
- return;
17104
- }
17105
- for (const content of contents) {
17106
- if (!content || typeof content !== "object") {
17107
- continue;
17108
- }
17109
- const parts = content.parts;
17110
- if (!parts || !Array.isArray(parts)) {
17111
- continue;
17112
- }
17113
- for (const part of parts) {
17114
- if (!part || typeof part !== "object") {
17115
- continue;
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
- const partObj = part;
17118
- if (partObj.functionCall && !partObj.thoughtSignature) {
17119
- partObj.thoughtSignature = "skip_thought_signature_validator";
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 parseJsonObject(value) {
17130
- if (typeof value !== "string") {
17131
- return {};
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(value);
17135
- if (parsed && typeof parsed === "object") {
17136
- return parsed;
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
- return {};
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 tracker = getTurnStateTracker();
17255
- let needsRecovery = false;
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 tracker = getTurnStateTracker();
17289
- let needsRecovery = false;
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 existsSync4, mkdirSync as mkdirSync4 } from "fs";
17713
- import { join as join4 } from "path";
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 = join4(cwd(), "agy_chat_log");
17721
- if (!existsSync4(logDir)) {
17722
- mkdirSync4(logDir, { recursive: true });
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 = join4(logDir, `${timestamp}.log`);
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
- try {
18063
- initDiskSignatureCache({
18064
- enabled: true,
18065
- memory_ttl_seconds: 3600,
18066
- disk_ttl_seconds: 86400,
18067
- write_interval_seconds: 30
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,